From b939ee7c87fd9a7810db8597039a26ad7dab4d2c Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Tue, 20 May 2025 17:06:06 +0200 Subject: [PATCH] fix: change signature of SQL.join() to allow a sequence of Any We declared accepting a sequence of Composable, but, because we passed the joined values to `Composite`, actually non-composable were interpreted as `Literal`. Make this behaviour explicit by testing it and fixing the signature. --- psycopg/psycopg/sql.py | 6 +++--- tests/test_sql.py | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/psycopg/psycopg/sql.py b/psycopg/psycopg/sql.py index 172110afe..8e025513c 100644 --- a/psycopg/psycopg/sql.py +++ b/psycopg/psycopg/sql.py @@ -288,12 +288,12 @@ class SQL(Composable): return Composed(rv) - def join(self, seq: Iterable[Composable]) -> Composed: + def join(self, seq: Iterable[Any]) -> Composed: """ Join a sequence of `Composable`. - :param seq: the elements to join. - :type seq: iterable of `!Composable` + :param seq: the elements to join. Elements that are not `Composable` + will be considered `Literal`. Use the `!SQL` object's string to separate the elements in `!seq`. Note that `Composed` objects are iterable too, so they can be used as diff --git a/tests/test_sql.py b/tests/test_sql.py index a5807f0a0..1e9c8c342 100644 --- a/tests/test_sql.py +++ b/tests/test_sql.py @@ -493,6 +493,10 @@ class TestSQL: assert isinstance(obj, sql.Composed) assert obj.as_string(conn) == '"foo", bar, 42' + obj = sql.SQL(", ").join(["foo", "bar", 42]) + assert isinstance(obj, sql.Composed) + assert obj.as_string(conn) == """'foo', 'bar', 42""" + obj = sql.SQL(", ").join([]) assert obj == sql.Composed([]) -- 2.47.2