From: Daniele Varrazzo Date: Fri, 14 May 2021 21:11:50 +0000 (+0200) Subject: Drop connection.set_client_encoding X-Git-Tag: 3.0~54^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ab54ad1ac7e915f12822ea926310784032128dac;p=thirdparty%2Fpsycopg.git Drop connection.set_client_encoding The property might have been super useful in pre-unicode times, but now it is really an implementation detail. The connection encoding can be still changed setting the GUC or with a PGOPTION or option in the connection params. --- diff --git a/docs/api/connections.rst b/docs/api/connections.rst index 8fff068d5..19d3ae2c5 100644 --- a/docs/api/connections.rst +++ b/docs/api/connections.rst @@ -227,10 +227,6 @@ The `!Connection` class .. autoattribute:: client_encoding - The property is writable for sync connections, read-only for async - ones: you should call ``await`` `~AsyncConnection.set_client_encoding`\ - :samp:`({value})` instead. - The value returned is always normalized to the Python codec `~codecs.CodecInfo.name`:: @@ -356,7 +352,6 @@ The `!AsyncConnection` class ... .. automethod:: notifies - .. automethod:: set_client_encoding .. automethod:: set_autocommit .. automethod:: set_isolation_level .. automethod:: set_read_only diff --git a/psycopg/psycopg/connection.py b/psycopg/psycopg/connection.py index 419f01939..8b4900a01 100644 --- a/psycopg/psycopg/connection.py +++ b/psycopg/psycopg/connection.py @@ -265,22 +265,6 @@ class BaseConnection(Generic[Row]): pgenc = self.pgconn.parameter_status(b"client_encoding") or b"UTF8" return encodings.pg2py(pgenc) - @client_encoding.setter - def client_encoding(self, name: str) -> None: - self._set_client_encoding(name) - - def _set_client_encoding(self, name: str) -> None: - raise NotImplementedError - - def _set_client_encoding_gen(self, name: str) -> PQGen[None]: - self.pgconn.send_query_params( - b"SELECT set_config('client_encoding', $1, false)", - [encodings.py2pg(name)], - ) - (result,) = yield from execute(self.pgconn) - if result.status != ExecStatus.TUPLES_OK: - raise e.error_from_result(result, encoding=self.client_encoding) - @property def info(self) -> ConnectionInfo: """A `ConnectionInfo` attribute to inspect connection properties.""" @@ -806,7 +790,3 @@ class Connection(BaseConnection[Row]): def _set_deferrable(self, value: Optional[bool]) -> None: with self.lock: super()._set_deferrable(value) - - def _set_client_encoding(self, name: str) -> None: - with self.lock: - self.wait(self._set_client_encoding_gen(name)) diff --git a/psycopg/psycopg/connection_async.py b/psycopg/psycopg/connection_async.py index 44bd6d040..7f6b3a3af 100644 --- a/psycopg/psycopg/connection_async.py +++ b/psycopg/psycopg/connection_async.py @@ -318,14 +318,6 @@ class AsyncConnection(BaseConnection[Row]): async with self.lock: super()._set_deferrable(value) - def _set_client_encoding(self, name: str) -> None: - self._no_set_async("client_encoding") - - async def set_client_encoding(self, name: str) -> None: - """Async version of the `~Connection.client_encoding` setter.""" - async with self.lock: - await self.wait(self._set_client_encoding_gen(name)) - def _no_set_async(self, attribute: str) -> None: raise AttributeError( f"'the {attribute!r} property is read-only on async connections:" diff --git a/tests/test_connection.py b/tests/test_connection.py index 97b094cda..07044cb05 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -304,15 +304,6 @@ def test_get_encoding(conn): assert conn.client_encoding == encodings.pg2py(enc) -def test_set_encoding(conn): - newenc = "iso8859-1" if conn.client_encoding != "iso8859-1" else "utf-8" - assert conn.client_encoding != newenc - conn.client_encoding = newenc - assert conn.client_encoding == newenc - (enc,) = conn.cursor().execute("show client_encoding").fetchone() - assert encodings.pg2py(enc) == newenc - - @pytest.mark.parametrize( "enc, out, codec", [ @@ -325,7 +316,7 @@ def test_set_encoding(conn): ], ) def test_normalize_encoding(conn, enc, out, codec): - conn.client_encoding = enc + conn.execute("select set_config('client_encoding', %s, false)", [enc]) assert conn.pgconn.parameter_status(b"client_encoding").decode() == out assert conn.client_encoding == codec @@ -354,11 +345,6 @@ def test_set_encoding_unsupported(conn): cur.execute("select 'x'") -def test_set_encoding_bad(conn): - with pytest.raises(LookupError): - conn.client_encoding = "WAT" - - @pytest.mark.parametrize( "args, kwargs, want", [ diff --git a/tests/test_connection_async.py b/tests/test_connection_async.py index 7423c1466..06c08de39 100644 --- a/tests/test_connection_async.py +++ b/tests/test_connection_async.py @@ -317,20 +317,6 @@ async def test_get_encoding(aconn): assert aconn.client_encoding == encodings.pg2py(enc) -async def test_set_encoding(aconn): - newenc = "iso8859-1" if aconn.client_encoding != "iso8859-1" else "utf-8" - assert aconn.client_encoding != newenc - with pytest.raises(AttributeError): - aconn.client_encoding = newenc - assert aconn.client_encoding != newenc - await aconn.set_client_encoding(newenc) - assert aconn.client_encoding == newenc - cur = aconn.cursor() - await cur.execute("show client_encoding") - (enc,) = await cur.fetchone() - assert encodings.pg2py(enc) == newenc - - @pytest.mark.parametrize( "enc, out, codec", [ @@ -343,7 +329,9 @@ async def test_set_encoding(aconn): ], ) async def test_normalize_encoding(aconn, enc, out, codec): - await aconn.set_client_encoding(enc) + await aconn.execute( + "select set_config('client_encoding', %s, false)", [enc] + ) assert aconn.pgconn.parameter_status(b"client_encoding").decode() == out assert aconn.client_encoding == codec @@ -372,11 +360,6 @@ async def test_set_encoding_unsupported(aconn): await cur.execute("select 'x'") -async def test_set_encoding_bad(aconn): - with pytest.raises(LookupError): - await aconn.set_client_encoding("WAT") - - @pytest.mark.parametrize( "args, kwargs, want", [ diff --git a/tests/test_copy.py b/tests/test_copy.py index 043eb860f..305082206 100644 --- a/tests/test_copy.py +++ b/tests/test_copy.py @@ -140,7 +140,7 @@ def test_set_custom_type(conn, hstore): def test_copy_out_allchars(conn, format): cur = conn.cursor() chars = list(map(chr, range(1, 256))) + [eur] - conn.client_encoding = "utf8" + conn.execute("set client_encoding to utf8") rows = [] query = sql.SQL( "copy (select unnest({}::text[])) to stdout (format {})" @@ -392,7 +392,7 @@ def test_copy_in_allchars(conn): cur = conn.cursor() ensure_table(cur, sample_tabledef) - conn.client_encoding = "utf8" + conn.execute("set client_encoding to utf8") with cur.copy("copy copy_in from stdin (format text)") as copy: for i in range(1, 256): copy.write_row((i, None, chr(i))) diff --git a/tests/test_copy_async.py b/tests/test_copy_async.py index 37ab5e1f8..5242f0437 100644 --- a/tests/test_copy_async.py +++ b/tests/test_copy_async.py @@ -117,7 +117,7 @@ async def test_set_custom_type(aconn, hstore): async def test_copy_out_allchars(aconn, format): cur = aconn.cursor() chars = list(map(chr, range(1, 256))) + [eur] - await aconn.set_client_encoding("utf8") + await aconn.execute("set client_encoding to utf8") rows = [] query = sql.SQL( "copy (select unnest({}::text[])) to stdout (format {})" @@ -381,7 +381,7 @@ async def test_copy_in_allchars(aconn): cur = aconn.cursor() await ensure_table(cur, sample_tabledef) - await aconn.set_client_encoding("utf8") + await aconn.execute("set client_encoding to utf8") async with cur.copy("copy copy_in from stdin (format text)") as copy: for i in range(1, 256): await copy.write_row((i, None, chr(i))) diff --git a/tests/test_cursor.py b/tests/test_cursor.py index 078277320..b6abecc46 100644 --- a/tests/test_cursor.py +++ b/tests/test_cursor.py @@ -140,14 +140,14 @@ def test_binary_cursor_text_override(conn): @pytest.mark.parametrize("encoding", ["utf8", "latin9"]) def test_query_encode(conn, encoding): - conn.client_encoding = encoding + conn.execute(f"set client_encoding to {encoding}") cur = conn.cursor() (res,) = cur.execute("select '\u20ac'").fetchone() assert res == "\u20ac" def test_query_badenc(conn): - conn.client_encoding = "latin1" + conn.execute("set client_encoding to latin1") cur = conn.cursor() with pytest.raises(UnicodeEncodeError): cur.execute("select '\u20ac'") diff --git a/tests/test_cursor_async.py b/tests/test_cursor_async.py index 54c2a99c7..6e1fa5d86 100644 --- a/tests/test_cursor_async.py +++ b/tests/test_cursor_async.py @@ -143,7 +143,7 @@ async def test_binary_cursor_text_override(aconn): @pytest.mark.parametrize("encoding", ["utf8", "latin9"]) async def test_query_encode(aconn, encoding): - await aconn.set_client_encoding(encoding) + await aconn.execute(f"set client_encoding to {encoding}") cur = aconn.cursor() await cur.execute("select '\u20ac'") (res,) = await cur.fetchone() @@ -151,7 +151,7 @@ async def test_query_encode(aconn, encoding): async def test_query_badenc(aconn): - await aconn.set_client_encoding("latin1") + await aconn.execute("set client_encoding to latin1") cur = aconn.cursor() with pytest.raises(UnicodeEncodeError): await cur.execute("select '\u20ac'") diff --git a/tests/test_errors.py b/tests/test_errors.py index 15e429ec9..cd92f4d94 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -74,7 +74,7 @@ def test_diag_encoding(conn, enc): msgs = [] conn.pgconn.exec_(b"set client_min_messages to notice") conn.add_notice_handler(lambda diag: msgs.append(diag.message_primary)) - conn.client_encoding = enc + conn.execute(f"set client_encoding to {enc}") cur = conn.cursor() cur.execute( "do $$begin raise notice 'hello %', chr(8364); end$$ language plpgsql" @@ -84,7 +84,8 @@ def test_diag_encoding(conn, enc): @pytest.mark.parametrize("enc", ["utf8", "latin9"]) def test_error_encoding(conn, enc): - conn.client_encoding = enc + with conn.transaction(): + conn.execute(f"set client_encoding to {enc}") cur = conn.cursor() with pytest.raises(e.DatabaseError) as excinfo: cur.execute( diff --git a/tests/test_sql.py b/tests/test_sql.py index b2c6264c8..44f0f0390 100644 --- a/tests/test_sql.py +++ b/tests/test_sql.py @@ -9,6 +9,7 @@ import pytest from psycopg import pq, sql, ProgrammingError from psycopg.adapt import PyFormat +from psycopg._encodings import py2pgenc eur = "\u20ac" @@ -290,7 +291,7 @@ class TestIdentifier: ) def test_as_bytes(self, conn, args, want, enc): want = want.encode(enc) - conn.client_encoding = enc + conn.execute(f"set client_encoding to {py2pgenc(enc).decode()}") assert sql.Identifier(*args).as_bytes(conn) == want def test_join(self): @@ -328,9 +329,9 @@ class TestLiteral: sql.Literal(dt.date(2017, 1, 1)).as_bytes(conn) == b"'2017-01-01'" ) - conn.client_encoding = "utf8" + conn.execute("set client_encoding to utf8") assert sql.Literal(eur).as_bytes(conn) == f"'{eur}'".encode() - conn.client_encoding = "latin9" + conn.execute("set client_encoding to latin9") assert sql.Literal(eur).as_bytes(conn) == f"'{eur}'".encode("latin9") def test_eq(self): @@ -410,10 +411,10 @@ class TestSQL: def test_as_bytes(self, conn): assert sql.SQL("foo").as_bytes(conn) == b"foo" - conn.client_encoding = "utf8" + conn.execute("set client_encoding to utf8") assert sql.SQL(eur).as_bytes(conn) == eur.encode() - conn.client_encoding = "latin9" + conn.execute("set client_encoding to latin9") assert sql.SQL(eur).as_bytes(conn) == eur.encode("latin9") @@ -484,10 +485,10 @@ class TestComposed: obj = sql.Composed([sql.SQL("foo"), sql.SQL(eur)]) - conn.client_encoding = "utf8" + conn.execute("set client_encoding to utf8") assert obj.as_bytes(conn) == ("foo" + eur).encode() - conn.client_encoding = "latin9" + conn.execute("set client_encoding to latin9") assert obj.as_bytes(conn) == ("foo" + eur).encode("latin9") diff --git a/tests/types/test_string.py b/tests/types/test_string.py index 21e66d696..6070ed42c 100644 --- a/tests/types/test_string.py +++ b/tests/types/test_string.py @@ -91,11 +91,11 @@ def test_load_1char(conn, typename, fmt_out): @pytest.mark.parametrize("fmt_in", PyFormat) -@pytest.mark.parametrize("encoding", ["utf8", "latin9", "ascii"]) +@pytest.mark.parametrize("encoding", ["utf8", "latin9", "sql_ascii"]) def test_dump_enc(conn, fmt_in, encoding): cur = conn.cursor() - conn.client_encoding = encoding + conn.execute(f"set client_encoding to {encoding}") (res,) = cur.execute(f"select ascii(%{fmt_in})", (eur,)).fetchone() assert res == ord(eur) @@ -104,7 +104,7 @@ def test_dump_enc(conn, fmt_in, encoding): def test_dump_badenc(conn, fmt_in): cur = conn.cursor() - conn.client_encoding = "latin1" + conn.execute("set client_encoding to latin1") with pytest.raises(UnicodeEncodeError): cur.execute(f"select %{fmt_in}::bytea", (eur,)) @@ -113,7 +113,7 @@ def test_dump_badenc(conn, fmt_in): def test_dump_utf8_badenc(conn, fmt_in): cur = conn.cursor() - conn.client_encoding = "utf-8" + conn.execute("set client_encoding to utf8") with pytest.raises(UnicodeEncodeError): cur.execute(f"select %{fmt_in}", ("\uddf8",)) @@ -151,8 +151,8 @@ def test_dump_text_oid(conn, fmt_in): def test_load_enc(conn, typename, encoding, fmt_out): cur = conn.cursor(binary=fmt_out) - conn.client_encoding = encoding - (res,) = cur.execute(f"select chr(%s)::{typename}", (ord(eur),)).fetchone() + conn.execute(f"set client_encoding to {encoding}") + (res,) = cur.execute(f"select chr(%s)::{typename}", [ord(eur)]).fetchone() assert res == eur stmt = sql.SQL("copy (select chr({})) to stdout (format {})").format( @@ -171,9 +171,9 @@ def test_load_badenc(conn, typename, fmt_out): conn.autocommit = True cur = conn.cursor(binary=fmt_out) - conn.client_encoding = "latin1" + conn.execute("set client_encoding to latin1") with pytest.raises(psycopg.DataError): - cur.execute(f"select chr(%s)::{typename}", (ord(eur),)) + cur.execute(f"select chr(%s)::{typename}", [ord(eur)]) stmt = sql.SQL("copy (select chr({})) to stdout (format {})").format( ord(eur), sql.SQL(fmt_out.name) @@ -189,8 +189,8 @@ def test_load_badenc(conn, typename, fmt_out): def test_load_ascii(conn, typename, fmt_out): cur = conn.cursor(binary=fmt_out) - conn.client_encoding = "ascii" - cur.execute(f"select chr(%s)::{typename}", (ord(eur),)) + conn.execute("set client_encoding to sql_ascii") + cur.execute(f"select chr(%s)::{typename}", [ord(eur)]) assert cur.fetchone()[0] == eur.encode() stmt = sql.SQL("copy (select chr({})) to stdout (format {})").format( @@ -217,7 +217,7 @@ def test_text_array(conn, typename, fmt_in, fmt_out): @pytest.mark.parametrize("fmt_in", PyFormat) @pytest.mark.parametrize("fmt_out", pq.Format) def test_text_array_ascii(conn, fmt_in, fmt_out): - conn.client_encoding = "ascii" + conn.execute("set client_encoding to sql_ascii") cur = conn.cursor(binary=fmt_out) a = list(map(chr, range(1, 256))) + [eur] exp = [s.encode() for s in a]