]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
feat(connection): add set_autocommit() and similar methods
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 2 Sep 2023 20:41:32 +0000 (21:41 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 11 Oct 2023 21:45:38 +0000 (23:45 +0200)
14 files changed:
docs/api/connections.rst
docs/basic/transactions.rst
docs/news.rst
psycopg/psycopg/connection.py
tests/_test_connection.py
tests/test_connection.py
tests/test_connection_async.py
tests/test_copy.py
tests/test_cursor.py
tests/test_pipeline.py
tests/test_prepared.py
tests/test_tpc.py
tests/test_transaction.py
tools/async_to_sync.py

index db25382b38f9dd4d7bda5ab5c7a47b953f12be4a..a607f07fa5191676d361f97f5fe14d5a34d6806e 100644 (file)
@@ -208,6 +208,10 @@ The `!Connection` class
         ones: you should call `!await` `~AsyncConnection.set_autocommit`
         :samp:`({value})` instead.
 
+    .. automethod:: set_autocommit
+
+        .. versionadded:: 3.2
+
     The following three properties control the characteristics of new
     transactions. See :ref:`transaction-characteristics` for details.
 
@@ -219,6 +223,10 @@ The `!Connection` class
         .. __: https://www.postgresql.org/docs/current/runtime-config-client.html
                #GUC-DEFAULT-TRANSACTION-ISOLATION
 
+    .. automethod:: set_isolation_level
+
+        .. versionadded:: 3.2
+
     .. autoattribute:: read_only
 
         `!None` means use the default set in the default_transaction_read_only__
@@ -227,6 +235,10 @@ The `!Connection` class
         .. __: https://www.postgresql.org/docs/current/runtime-config-client.html
                #GUC-DEFAULT-TRANSACTION-READ-ONLY
 
+    .. automethod:: set_read_only
+
+        .. versionadded:: 3.2
+
     .. autoattribute:: deferrable
 
         `!None` means use the default set in the default_transaction_deferrable__
@@ -235,6 +247,10 @@ The `!Connection` class
         .. __: https://www.postgresql.org/docs/current/runtime-config-client.html
                #GUC-DEFAULT-TRANSACTION-DEFERRABLE
 
+    .. automethod:: set_deferrable
+
+        .. versionadded:: 3.2
+
 
     .. rubric:: Checking and configuring the connection state
 
index fe05f9f3ef65b02684991bea43fe40186dab3501..abcecc9d2f050db9515ca94c54cf4670dc615d84 100644 (file)
@@ -328,6 +328,10 @@ In order to set these parameters you can use the connection attributes
 can only be changed if there isn't a transaction already active on the
 connection.
 
+.. versionadded:: 3.2
+   Added methods equivalent to setting the properties (such as
+   `~Connection.set_isolation_level()`) on sync connections too.
+
 .. warning::
 
    Applications running at `~IsolationLevel.REPEATABLE_READ` or
index eca84e673ff701783e17c7f2effe943204ec99b5..f7b227e9e459ce08a0f1b9ae8091da622b469549 100644 (file)
@@ -17,6 +17,8 @@ Psycopg 3.2 (unreleased)
   (:ticket:`#332`).
 - Add :ref:`raw-query-cursors` to execute queries using placeholders in
   PostgreSQL format (`$1`, `$2`...) (:ticket:`#560`).
+- Add `~Connection.set_autocommit()` on sync connections, and similar
+  transaction control methods available on the async connections.
 - Add support for libpq functions to close prepared statements and portals
   introduced in libpq v17 (:ticket:`#603`).
 - Disable receiving more than one result on the same cursor in pipeline mode,
index 73724f616f23f1ea2abcca0e8c36e5517a2779eb..4075c1fe493fdaa2799aed6392f6fddc9a965761 100644 (file)
@@ -369,18 +369,34 @@ class Connection(BaseConnection[Row]):
         return waiting.wait_conn(gen, timeout=timeout)
 
     def _set_autocommit(self, value: bool) -> None:
+        self.set_autocommit(value)
+
+    def set_autocommit(self, value: bool) -> None:
+        """Method version of the `~Connection.autocommit` setter."""
         with self.lock:
             self.wait(self._set_autocommit_gen(value))
 
     def _set_isolation_level(self, value: Optional[IsolationLevel]) -> None:
+        self.set_isolation_level(value)
+
+    def set_isolation_level(self, value: Optional[IsolationLevel]) -> None:
+        """Method version of the `~Connection.isolation_level` setter."""
         with self.lock:
             self.wait(self._set_isolation_level_gen(value))
 
     def _set_read_only(self, value: Optional[bool]) -> None:
+        self.set_read_only(value)
+
+    def set_read_only(self, value: Optional[bool]) -> None:
+        """Method version of the `~Connection.read_only` setter."""
         with self.lock:
             self.wait(self._set_read_only_gen(value))
 
     def _set_deferrable(self, value: Optional[bool]) -> None:
+        self.set_deferrable(value)
+
+    def set_deferrable(self, value: Optional[bool]) -> None:
+        """Method version of the `~Connection.deferrable` setter."""
         with self.lock:
             self.wait(self._set_deferrable_gen(value))
 
index 8ce09029351df0b1eb2237b3ca2042f3e88b5c36..296a7f7f4b95a58246d30fca4da4b8610e68c09f 100644 (file)
@@ -9,22 +9,6 @@ import pytest
 import psycopg
 
 
-async def aconn_set(conn, param, value):
-    """Equivalent of 'await conn.set_param(value)'
-
-    Converted to conn_set in sync tests.
-    """
-    await getattr(conn, f"set_{param}")(value)
-
-
-def conn_set(conn, param, value):
-    """Equivalent of 'conn.param = value'.
-
-    Converted from aconn_set in sync tests.
-    """
-    setattr(conn, param, value)
-
-
 @pytest.fixture
 def testctx(svcconn):
     svcconn.execute("create table if not exists testctx (id int primary key)")
index 914bfa647cdbea1dda98104d83d46e39497dc74c..f995e5b0befbd3322e98339fa628ae70079b1f4c 100644 (file)
@@ -16,7 +16,7 @@ from psycopg.conninfo import conninfo_to_dict, make_conninfo
 from .utils import gc_collect, is_async
 from ._test_cursor import my_row_factory
 from ._test_connection import tx_params, tx_params_isolation, tx_values_map
-from ._test_connection import conninfo_params_timeout, conn_set
+from ._test_connection import conninfo_params_timeout
 from ._test_connection import testctx  # noqa: F401  # fixture
 from .test_adapt import make_bin_dumper, make_dumper
 
@@ -320,6 +320,25 @@ def test_autocommit_readonly_property(conn):
 
 def test_autocommit(conn):
     assert conn.autocommit is False
+    conn.set_autocommit(True)
+    assert conn.autocommit
+    cur = conn.cursor()
+    cur.execute("select 1")
+    assert cur.fetchone() == (1,)
+    assert conn.pgconn.transaction_status == conn.TransactionStatus.IDLE
+
+    conn.set_autocommit("")
+    assert isinstance(conn.autocommit, bool)
+    assert conn.autocommit is False
+
+    conn.set_autocommit("yeah")
+    assert isinstance(conn.autocommit, bool)
+    assert conn.autocommit is True
+
+
+@pytest.mark.skipif(is_async(__name__), reason="sync test only")
+def test_autocommit_property(conn):
+    assert conn.autocommit is False
 
     conn.autocommit = True
     assert conn.autocommit
@@ -349,7 +368,7 @@ def test_autocommit_intrans(conn):
     assert cur.fetchone() == (1,)
     assert conn.pgconn.transaction_status == conn.TransactionStatus.INTRANS
     with pytest.raises(psycopg.ProgrammingError):
-        conn.autocommit = True
+        conn.set_autocommit(True)
     assert not conn.autocommit
 
 
@@ -359,7 +378,7 @@ def test_autocommit_inerror(conn):
         cur.execute("meh")
     assert conn.pgconn.transaction_status == conn.TransactionStatus.INERROR
     with pytest.raises(psycopg.ProgrammingError):
-        conn.autocommit = True
+        conn.set_autocommit(True)
     assert not conn.autocommit
 
 
@@ -367,7 +386,7 @@ def test_autocommit_unknown(conn):
     conn.close()
     assert conn.pgconn.transaction_status == conn.TransactionStatus.UNKNOWN
     with pytest.raises(psycopg.OperationalError):
-        conn.autocommit = True
+        conn.set_autocommit(True)
     assert not conn.autocommit
 
 
@@ -481,7 +500,7 @@ def test_notify_handlers(conn):
     conn.add_notify_handler(cb1)
     conn.add_notify_handler(lambda n: nots2.append(n))
 
-    conn.autocommit = True
+    conn.set_autocommit(True)
     cur = conn.cursor()
     cur.execute("listen foo")
     cur.execute("notify foo, 'n1'")
@@ -627,9 +646,9 @@ def test_transaction_param_readonly_property(conn, param):
 @pytest.mark.parametrize("autocommit", [True, False])
 @pytest.mark.parametrize("param", tx_params_isolation)
 def test_set_transaction_param_implicit(conn, param, autocommit):
-    conn.autocommit = autocommit
+    conn.set_autocommit(autocommit)
     for value in param.values:
-        conn_set(conn, param.name, value)
+        getattr(conn, f"set_{param.name}")(value)
         cur = conn.execute(
             "select current_setting(%s), current_setting(%s)",
             [f"transaction_{param.guc}", f"default_transaction_{param.guc}"],
@@ -651,13 +670,13 @@ def test_set_transaction_param_reset(conn, param):
     conn.commit()
 
     for value in param.values:
-        conn_set(conn, param.name, value)
+        getattr(conn, f"set_{param.name}")(value)
         cur = conn.execute("select current_setting(%s)", [f"transaction_{param.guc}"])
         (pgval,) = cur.fetchone()
         assert tx_values_map[pgval] == value
         conn.rollback()
 
-        conn_set(conn, param.name, None)
+        getattr(conn, f"set_{param.name}")(None)
         cur = conn.execute("select current_setting(%s)", [f"transaction_{param.guc}"])
         (pgval,) = cur.fetchone()
         assert tx_values_map[pgval] == tx_values_map[param.non_default]
@@ -667,9 +686,9 @@ def test_set_transaction_param_reset(conn, param):
 @pytest.mark.parametrize("autocommit", [True, False])
 @pytest.mark.parametrize("param", tx_params_isolation)
 def test_set_transaction_param_block(conn, param, autocommit):
-    conn.autocommit = autocommit
+    conn.set_autocommit(autocommit)
     for value in param.values:
-        conn_set(conn, param.name, value)
+        getattr(conn, f"set_{param.name}")(value)
         with conn.transaction():
             cur = conn.execute(
                 "select current_setting(%s)", [f"transaction_{param.guc}"]
@@ -683,7 +702,7 @@ def test_set_transaction_param_not_intrans_implicit(conn, param):
     conn.execute("select 1")
     value = param.values[0]
     with pytest.raises(psycopg.ProgrammingError):
-        conn_set(conn, param.name, value)
+        getattr(conn, f"set_{param.name}")(value)
 
 
 @pytest.mark.parametrize("param", tx_params)
@@ -691,17 +710,32 @@ def test_set_transaction_param_not_intrans_block(conn, param):
     value = param.values[0]
     with conn.transaction():
         with pytest.raises(psycopg.ProgrammingError):
-            conn_set(conn, param.name, value)
+            getattr(conn, f"set_{param.name}")(value)
 
 
 @pytest.mark.parametrize("param", tx_params)
 def test_set_transaction_param_not_intrans_external(conn, param):
     value = param.values[0]
-
-    conn.autocommit = True
+    conn.set_autocommit(True)
     conn.execute("begin")
     with pytest.raises(psycopg.ProgrammingError):
-        conn_set(conn, param.name, value)
+        getattr(conn, f"set_{param.name}")(value)
+
+
+@pytest.mark.skipif(is_async(__name__), reason="sync test only")
+@pytest.mark.crdb("skip", reason="transaction isolation")
+def test_set_transaction_param_all_property(conn):
+    params: List[Any] = tx_params[:]
+    params[2] = params[2].values[0]
+
+    for param in params:
+        value = param.values[0]
+        setattr(conn, param.name, value)
+
+    for param in params:
+        cur = conn.execute("select current_setting(%s)", [f"transaction_{param.guc}"])
+        pgval = cur.fetchone()[0]
+        assert tx_values_map[pgval] == value
 
 
 @pytest.mark.crdb("skip", reason="transaction isolation")
@@ -711,7 +745,7 @@ def test_set_transaction_param_all(conn):
 
     for param in params:
         value = param.values[0]
-        conn_set(conn, param.name, value)
+        getattr(conn, f"set_{param.name}")(value)
 
     for param in params:
         cur = conn.execute("select current_setting(%s)", [f"transaction_{param.guc}"])
@@ -720,6 +754,22 @@ def test_set_transaction_param_all(conn):
 
 
 def test_set_transaction_param_strange(conn):
+    for val in ("asdf", 0, 5):
+        with pytest.raises(ValueError):
+            conn.set_isolation_level(val)
+
+    conn.set_isolation_level(psycopg.IsolationLevel.SERIALIZABLE.value)
+    assert conn.isolation_level is psycopg.IsolationLevel.SERIALIZABLE
+
+    conn.set_read_only(1)
+    assert conn.read_only is True
+
+    conn.set_deferrable(0)
+    assert conn.deferrable is False
+
+
+@pytest.mark.skipif(is_async(__name__), reason="sync test only")
+def test_set_transaction_param_strange_property(conn):
     for val in ("asdf", 0, 5):
         with pytest.raises(ValueError):
             conn.isolation_level = val
index b9a0c005e239216a0c11427afb33bcf2c0dff66f..7830cf9a212dc6fc27085811ec5bb378f9e04caf 100644 (file)
@@ -13,7 +13,7 @@ from psycopg.conninfo import conninfo_to_dict, make_conninfo
 from .utils import gc_collect, is_async
 from ._test_cursor import my_row_factory
 from ._test_connection import tx_params, tx_params_isolation, tx_values_map
-from ._test_connection import conninfo_params_timeout, aconn_set
+from ._test_connection import conninfo_params_timeout
 from ._test_connection import testctx  # noqa: F401  # fixture
 from .test_adapt import make_bin_dumper, make_dumper
 
@@ -334,6 +334,26 @@ async def test_autocommit(aconn):
     assert aconn.autocommit is True
 
 
+@pytest.mark.skipif(is_async(__name__), reason="sync test only")
+def test_autocommit_property(conn):
+    assert conn.autocommit is False
+
+    conn.autocommit = True
+    assert conn.autocommit
+    cur = conn.cursor()
+    cur.execute("select 1")
+    assert cur.fetchone() == (1,)
+    assert conn.pgconn.transaction_status == conn.TransactionStatus.IDLE
+
+    conn.autocommit = ""
+    assert isinstance(conn.autocommit, bool)
+    assert conn.autocommit is False
+
+    conn.autocommit = "yeah"
+    assert isinstance(conn.autocommit, bool)
+    assert conn.autocommit is True
+
+
 async def test_autocommit_connect(aconn_cls, dsn):
     aconn = await aconn_cls.connect(dsn, autocommit=True)
     assert aconn.autocommit
@@ -630,7 +650,7 @@ async def test_transaction_param_readonly_property(aconn, param):
 async def test_set_transaction_param_implicit(aconn, param, autocommit):
     await aconn.set_autocommit(autocommit)
     for value in param.values:
-        await aconn_set(aconn, param.name, value)
+        await getattr(aconn, f"set_{param.name}")(value)
         cur = await aconn.execute(
             "select current_setting(%s), current_setting(%s)",
             [f"transaction_{param.guc}", f"default_transaction_{param.guc}"],
@@ -652,7 +672,7 @@ async def test_set_transaction_param_reset(aconn, param):
     await aconn.commit()
 
     for value in param.values:
-        await aconn_set(aconn, param.name, value)
+        await getattr(aconn, f"set_{param.name}")(value)
         cur = await aconn.execute(
             "select current_setting(%s)", [f"transaction_{param.guc}"]
         )
@@ -660,7 +680,7 @@ async def test_set_transaction_param_reset(aconn, param):
         assert tx_values_map[pgval] == value
         await aconn.rollback()
 
-        await aconn_set(aconn, param.name, None)
+        await getattr(aconn, f"set_{param.name}")(None)
         cur = await aconn.execute(
             "select current_setting(%s)", [f"transaction_{param.guc}"]
         )
@@ -674,7 +694,7 @@ async def test_set_transaction_param_reset(aconn, param):
 async def test_set_transaction_param_block(aconn, param, autocommit):
     await aconn.set_autocommit(autocommit)
     for value in param.values:
-        await aconn_set(aconn, param.name, value)
+        await getattr(aconn, f"set_{param.name}")(value)
         async with aconn.transaction():
             cur = await aconn.execute(
                 "select current_setting(%s)", [f"transaction_{param.guc}"]
@@ -688,7 +708,7 @@ async def test_set_transaction_param_not_intrans_implicit(aconn, param):
     await aconn.execute("select 1")
     value = param.values[0]
     with pytest.raises(psycopg.ProgrammingError):
-        await aconn_set(aconn, param.name, value)
+        await getattr(aconn, f"set_{param.name}")(value)
 
 
 @pytest.mark.parametrize("param", tx_params)
@@ -696,7 +716,7 @@ async def test_set_transaction_param_not_intrans_block(aconn, param):
     value = param.values[0]
     async with aconn.transaction():
         with pytest.raises(psycopg.ProgrammingError):
-            await aconn_set(aconn, param.name, value)
+            await getattr(aconn, f"set_{param.name}")(value)
 
 
 @pytest.mark.parametrize("param", tx_params)
@@ -705,7 +725,23 @@ async def test_set_transaction_param_not_intrans_external(aconn, param):
     await aconn.set_autocommit(True)
     await aconn.execute("begin")
     with pytest.raises(psycopg.ProgrammingError):
-        await aconn_set(aconn, param.name, value)
+        await getattr(aconn, f"set_{param.name}")(value)
+
+
+@pytest.mark.skipif(is_async(__name__), reason="sync test only")
+@pytest.mark.crdb("skip", reason="transaction isolation")
+def test_set_transaction_param_all_property(conn):
+    params: List[Any] = tx_params[:]
+    params[2] = params[2].values[0]
+
+    for param in params:
+        value = param.values[0]
+        setattr(conn, param.name, value)
+
+    for param in params:
+        cur = conn.execute("select current_setting(%s)", [f"transaction_{param.guc}"])
+        pgval = cur.fetchone()[0]
+        assert tx_values_map[pgval] == value
 
 
 @pytest.mark.crdb("skip", reason="transaction isolation")
@@ -715,7 +751,7 @@ async def test_set_transaction_param_all(aconn):
 
     for param in params:
         value = param.values[0]
-        await aconn_set(aconn, param.name, value)
+        await getattr(aconn, f"set_{param.name}")(value)
 
     for param in params:
         cur = await aconn.execute(
@@ -740,6 +776,22 @@ async def test_set_transaction_param_strange(aconn):
     assert aconn.deferrable is False
 
 
+@pytest.mark.skipif(is_async(__name__), reason="sync test only")
+def test_set_transaction_param_strange_property(conn):
+    for val in ("asdf", 0, 5):
+        with pytest.raises(ValueError):
+            conn.isolation_level = val
+
+    conn.isolation_level = psycopg.IsolationLevel.SERIALIZABLE.value
+    assert conn.isolation_level is psycopg.IsolationLevel.SERIALIZABLE
+
+    conn.read_only = 1
+    assert conn.read_only is True
+
+    conn.deferrable = 0
+    assert conn.deferrable is False
+
+
 @pytest.mark.parametrize("dsn, kwargs, exp", conninfo_params_timeout)
 async def test_get_connection_params(aconn_cls, dsn, kwargs, exp, setpgenv):
     setpgenv({})
index f4deaf98beb53e7cc1415cc4ce6acee4c6b6a4ce..5ab25a86285b133bade3537d4ddb9ee7458cea55 100644 (file)
@@ -213,7 +213,7 @@ def test_copy_in_buffers_pg_error(conn):
 
 
 def test_copy_bad_result(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
 
     cur = conn.cursor()
 
index 5377d0d1e4fa2630dda37a8d876a88f18141c281..f459b4943b323e83f8f8e175d9284c0333764cdb 100644 (file)
@@ -708,7 +708,7 @@ def test_stream_error_tx(conn):
 
 
 def test_stream_error_notx(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     cur = conn.cursor()
     with pytest.raises(psycopg.ProgrammingError):
         for rec in cur.stream("wat"):
@@ -741,7 +741,7 @@ def test_stream_error_python_consumed(conn):
 
 @pytest.mark.parametrize("autocommit", [False, True])
 def test_stream_close(conn, autocommit):
-    conn.autocommit = autocommit
+    conn.set_autocommit(autocommit)
     cur = conn.cursor()
     with pytest.raises(psycopg.OperationalError):
         for rec in cur.stream("select generate_series(1, 3)"):
@@ -815,7 +815,7 @@ def test_message_0x33(conn):
     notices = []
     conn.add_notice_handler(lambda diag: notices.append(diag.message_primary))
 
-    conn.autocommit = True
+    conn.set_autocommit(True)
     with conn.pipeline():
         cur = conn.execute("select 'test'")
         assert cur.fetchone() == ("test",)
index 35028795fbc42a766fa441cad8357bec978414d5..da46dbc40e015e670bff2ac204add05ea2db9a3a 100644 (file)
@@ -143,7 +143,7 @@ def test_pipeline_processed_at_exit(conn):
 
 
 def test_pipeline_errors_processed_at_exit(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     with pytest.raises(e.UndefinedTable):
         with conn.pipeline():
             conn.execute("select * from nosuchtable")
@@ -172,7 +172,7 @@ def test_pipeline(conn):
 
 
 def test_autocommit(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     with conn.pipeline(), conn.cursor() as c:
         c.execute("select 1")
 
@@ -181,7 +181,7 @@ def test_autocommit(conn):
 
 
 def test_pipeline_aborted(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     with conn.pipeline() as p:
         c1 = conn.execute("select 1")
         with pytest.raises(e.UndefinedTable):
@@ -217,7 +217,7 @@ def test_sync_syncs_results(conn):
 
 @pytest.mark.flakey("assert rarely fails randomly in CI blocking release")
 def test_sync_syncs_errors(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     with conn.pipeline() as p:
         conn.execute("select 1 from nosuchtable")
         with pytest.raises(e.UndefinedTable):
@@ -272,7 +272,7 @@ def test_errors_raised_on_nested_transaction_exit(conn):
 
 
 def test_implicit_transaction(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     with conn.pipeline():
         assert conn.pgconn.transaction_status == pq.TransactionStatus.IDLE
         conn.execute("select 'before'")
@@ -319,7 +319,7 @@ def test_fetch_no_result(conn):
 
 
 def test_executemany(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     conn.execute("drop table if exists execmanypipeline")
     conn.execute(
         "create unlogged table execmanypipeline (id serial primary key, num integer)"
@@ -339,7 +339,7 @@ def test_executemany(conn):
 
 
 def test_executemany_no_returning(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     conn.execute("drop table if exists execmanypipelinenoreturning")
     conn.execute(
         """create unlogged table execmanypipelinenoreturning
@@ -361,7 +361,7 @@ def test_executemany_no_returning(conn):
 
 @pytest.mark.crdb("skip", reason="temp tables")
 def test_executemany_trace(conn, trace):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     cur = conn.cursor()
     cur.execute("create temp table trace (id int)")
     t = trace.trace(conn)
@@ -379,7 +379,7 @@ def test_executemany_trace(conn, trace):
 
 @pytest.mark.crdb("skip", reason="temp tables")
 def test_executemany_trace_returning(conn, trace):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     cur = conn.cursor()
     cur.execute("create temp table trace (id int)")
     t = trace.trace(conn)
@@ -401,7 +401,7 @@ def test_executemany_trace_returning(conn, trace):
 
 
 def test_prepared(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     with conn.pipeline():
         c1 = conn.execute("select %s::int", [10], prepare=True)
         c2 = conn.execute(
@@ -435,8 +435,7 @@ def test_prepare_error(conn):
     An invalid prepared statement, in a pipeline, should be discarded at exit
     and not reused.
     """
-
-    conn.autocommit = True
+    conn.set_autocommit(True)
     stmt = "INSERT INTO nosuchtable(data) VALUES (%s)"
     with pytest.raises(psycopg.errors.UndefinedTable):
         with conn.pipeline():
@@ -514,7 +513,7 @@ def test_outer_transaction_error(conn):
 
 
 def test_rollback_explicit(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     with conn.pipeline():
         with pytest.raises(e.DivisionByZero):
             cur = conn.execute("select 1 / %s", [0])
@@ -524,7 +523,7 @@ def test_rollback_explicit(conn):
 
 
 def test_rollback_transaction(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     with pytest.raises(e.DivisionByZero):
         with conn.pipeline():
             with conn.transaction():
@@ -538,7 +537,7 @@ def test_message_0x33(conn):
     notices = []
     conn.add_notice_handler(lambda diag: notices.append(diag.message_primary))
 
-    conn.autocommit = True
+    conn.set_autocommit(True)
     with conn.pipeline():
         cur = conn.execute("select 'test'")
         assert cur.fetchone() == ("test",)
@@ -581,7 +580,7 @@ def test_concurrency(conn):
         conn.execute("update accessed set value = now()")
         return cur
 
-    conn.autocommit = True
+    conn.set_autocommit(True)
 
     (before,) = conn.execute("select value from accessed").fetchone()
 
index eb34a1b1144587870ef6fcb6da10e73a52b8dc4f..c639f8ac336b2e58771034ecdde01b2310c12385 100644 (file)
@@ -103,7 +103,7 @@ def test_no_prepare_multi_with_drop(conn):
 
 
 def test_no_prepare_error(conn):
-    conn.autocommit = True
+    conn.set_autocommit(True)
     for i in range(10):
         with pytest.raises(conn.ProgrammingError):
             conn.execute("select wat")
index c5bbc34f552a4f8e7981e90ad7014cbb0ec0a067..41023ccc87f92af303bba9048172827d917bc5ef 100644 (file)
@@ -163,8 +163,7 @@ class TestTPC:
 
     def test_recovered_xids(self, conn, tpc):
         # insert a few test xns
-
-        conn.autocommit = True
+        conn.set_autocommit(True)
         cur = conn.cursor()
         cur.execute("begin; prepare transaction '1-foo'")
         cur.execute("begin; prepare transaction '2-bar'")
index b73e6c87f2a1f251d1e0b6e9e0a42aa1d85d299f..a82a8f9c7fce0ae8fa3d65fb3be4486a3e1b9bf8 100644 (file)
@@ -149,20 +149,19 @@ def test_prohibits_use_of_commit_rollback_autocommit(conn):
     or the autocommit setting on the connection, as this would interfere
     with the transaction scope being managed by the Transaction block.
     """
-
-    conn.autocommit = False
+    conn.set_autocommit(False)
     conn.commit()
     conn.rollback()
 
     with conn.transaction():
         with pytest.raises(e.ProgrammingError):
-            conn.autocommit = False
+            conn.set_autocommit(False)
         with pytest.raises(e.ProgrammingError):
             conn.commit()
         with pytest.raises(e.ProgrammingError):
             conn.rollback()
 
-    conn.autocommit = False
+    conn.set_autocommit(False)
     conn.commit()
     conn.rollback()
 
@@ -172,8 +171,7 @@ def test_preserves_autocommit(conn, autocommit):
     """
     Connection.autocommit is unchanged both during and after Transaction block.
     """
-
-    conn.autocommit = autocommit
+    conn.set_autocommit(autocommit)
     with conn.transaction():
         assert conn.autocommit is autocommit
     assert conn.autocommit is autocommit
@@ -189,8 +187,7 @@ def test_autocommit_off_but_no_tx_started_successful_exit(conn, svcconn):
     Outcome:
     * Changes made within Transaction context are committed
     """
-
-    conn.autocommit = False
+    conn.set_autocommit(False)
     assert not in_transaction(conn)
     with conn.transaction():
         insert_row(conn, "new")
@@ -211,8 +208,7 @@ def test_autocommit_off_but_no_tx_started_exception_exit(conn, svcconn):
     Outcome:
     * Changes made within Transaction context are discarded
     """
-
-    conn.autocommit = False
+    conn.set_autocommit(False)
     assert not in_transaction(conn)
     with pytest.raises(ExpectedException):
         with conn.transaction():
@@ -238,8 +234,7 @@ def test_autocommit_off_and_tx_in_progress_successful_exit(conn, pipeline, svcco
     * Outer transaction is left running, and no changes are visible to an
       outside observer from another connection.
     """
-
-    conn.autocommit = False
+    conn.set_autocommit(False)
     insert_row(conn, "prior")
     if pipeline:
         pipeline.sync()
@@ -266,8 +261,7 @@ def test_autocommit_off_and_tx_in_progress_exception_exit(conn, pipeline, svccon
     * Outer transaction is left running, and no changes are visible to an
       outside observer from another connection.
     """
-
-    conn.autocommit = False
+    conn.set_autocommit(False)
     insert_row(conn, "prior")
     if pipeline:
         pipeline.sync()
@@ -645,7 +639,7 @@ def test_str(conn, pipeline):
 
 @pytest.mark.parametrize("exit_error", [None, ZeroDivisionError, Rollback])
 def test_out_of_order_exit(conn, exit_error):
-    conn.autocommit = True
+    conn.set_autocommit(True)
 
     t1 = conn.transaction()
     t1.__enter__()
@@ -679,7 +673,7 @@ def test_out_of_order_implicit_begin(conn, exit_error):
 
 @pytest.mark.parametrize("exit_error", [None, ZeroDivisionError, Rollback])
 def test_out_of_order_exit_same_name(conn, exit_error):
-    conn.autocommit = True
+    conn.set_autocommit(True)
 
     t1 = conn.transaction("save")
     t1.__enter__()
index 3375656fcbc01cd6c3eae2ef3f0ab5dd0e46b9b5..080267e57870eac65916e17eb4b70947f1ca65c9 100755 (executable)
@@ -34,7 +34,6 @@ def async_to_sync(tree: ast.AST) -> ast.AST:
     tree = BlanksInserter().visit(tree)
     tree = RenameAsyncToSync().visit(tree)
     tree = AsyncToSync().visit(tree)
-    tree = FixAsyncSetters().visit(tree)
     return tree
 
 
@@ -128,7 +127,6 @@ class RenameAsyncToSync(ast.NodeTransformer):
         "acommands": "commands",
         "aconn": "conn",
         "aconn_cls": "conn_cls",
-        "aconn_set": "conn_set",
         "alist": "list",
         "anext": "next",
         "apipeline": "pipeline",
@@ -243,37 +241,6 @@ class RenameAsyncToSync(ast.NodeTransformer):
         return node
 
 
-class FixAsyncSetters(ast.NodeTransformer):
-    setters_map = {
-        "set_autocommit": "autocommit",
-        "set_read_only": "read_only",
-        "set_isolation_level": "isolation_level",
-        "set_deferrable": "deferrable",
-    }
-
-    def visit_Call(self, node: ast.Call) -> ast.AST:
-        new_node = self._fix_setter(node)
-        if new_node:
-            return new_node
-
-        self.generic_visit(node)
-        return node
-
-    def _fix_setter(self, node: ast.Call) -> ast.AST | None:
-        if not isinstance(node.func, ast.Attribute):
-            return None
-        if node.func.attr not in self.setters_map:
-            return None
-        obj = node.func.value
-        arg = node.args[0]
-        new_node = ast.Assign(
-            targets=[ast.Attribute(value=obj, attr=self.setters_map[node.func.attr])],
-            value=arg,
-        )
-        ast.copy_location(new_node, node)
-        return new_node
-
-
 class BlanksInserter(ast.NodeTransformer):
     """
     Restore the missing spaces in the source (or something similar)