From 3fbdbc756e0acadf1a0c4df12a3e5fedf5ed2a62 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 4 Nov 2023 12:44:53 +0300 Subject: [PATCH 01/14] gh-111726: Fix doctest warnings in `Doc/library/sqlite3.rst` --- Doc/library/sqlite3.rst | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index a5b3474f4bd39a..a5a75170ceccd5 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -220,6 +220,7 @@ creating a new cursor, then querying the database: >>> title, year = res.fetchone() >>> print(f'The highest scoring Monty Python movie is {title!r}, released in {year}') The highest scoring Monty Python movie is 'Monty Python and the Holy Grail', released in 1975 + >>> con.close() You've now created an SQLite database using the :mod:`!sqlite3` module, inserted data and retrieved values from it in multiple ways. @@ -418,6 +419,10 @@ Module functions ZeroDivisionError('division by zero') in callback evil_trace Error message: None + .. testcleanup:: + + conn.close() + .. function:: register_adapter(type, adapter, /) Register an *adapter* :term:`callable` to adapt the Python type *type* @@ -763,6 +768,10 @@ Connection objects ... print(row) ('acbd18db4cc2f85cedef654fccc4a4d8',) + .. testcleanup:: + + con.close() + .. versionchanged:: 3.13 Passing *name*, *narg*, and *func* as keyword arguments is deprecated. @@ -908,6 +917,7 @@ Connection objects FROM test ORDER BY x """) print(cur.fetchall()) + con.close() .. testoutput:: :hide: @@ -1221,6 +1231,8 @@ Connection objects src = sqlite3.connect('example.db') dst = sqlite3.connect(':memory:') src.backup(dst) + dst.close() + src.close() .. versionadded:: 3.7 @@ -1255,6 +1267,10 @@ Connection objects >>> con.getlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH) 1000000000 + .. testcleanup:: + + con.close() + .. versionadded:: 3.11 @@ -1491,6 +1507,10 @@ Cursor objects (1,) + .. testcleanup:: + + con.close() + .. _database cursor: https://en.wikipedia.org/wiki/Cursor_(databases) .. class:: Cursor @@ -1674,6 +1694,10 @@ Cursor objects >>> cur.connection == con True + .. testcleanup:: + + con.close() + .. attribute:: description Read-only attribute that provides the column names of the last query. To @@ -1793,6 +1817,7 @@ Blob objects greeting = blob.read() print(greeting) # outputs "b'Hello, world!'" + con.close() .. testoutput:: :hide: @@ -2105,6 +2130,7 @@ Here's an example of both styles: params = (1972,) cur.execute("SELECT * FROM lang WHERE first_appeared = ?", params) print(cur.fetchall()) + con.close() .. testoutput:: :hide: @@ -2163,6 +2189,7 @@ The object passed to *protocol* will be of type :class:`PrepareProtocol`. cur.execute("SELECT ?", (Point(4.0, -3.2),)) print(cur.fetchone()[0]) + con.close() .. testoutput:: :hide: @@ -2193,6 +2220,7 @@ This function can then be registered using :func:`register_adapter`. cur.execute("SELECT ?", (Point(1.0, 2.5),)) print(cur.fetchone()[0]) + con.close() .. testoutput:: :hide: @@ -2277,6 +2305,8 @@ The following example illustrates the implicit and explicit approaches: cur.execute("INSERT INTO test(p) VALUES(?)", (p,)) cur.execute('SELECT p AS "p [point]" FROM test') print("with column names:", cur.fetchone()[0]) + cur.close() + con.close() .. testoutput:: :hide: @@ -2515,6 +2545,10 @@ assign it to the :attr:`!row_factory` attribute: >>> con = sqlite3.connect(":memory:") >>> con.row_factory = sqlite3.Row +.. testcleanup:: + + con.close() + Queries now return :class:`!Row` objects: .. doctest:: @@ -2530,6 +2564,10 @@ Queries now return :class:`!Row` objects: >>> row["RADIUS"] # Column names are case-insensitive. 6378 +.. testcleanup:: + + con.close() + .. note:: The ``FROM`` clause can be omitted in the ``SELECT`` statement, as in the @@ -2556,6 +2594,10 @@ Using it, queries now return a :class:`!dict` instead of a :class:`!tuple`: ... print(row) {'a': 1, 'b': 2} +.. testcleanup:: + + con.close() + The following row factory returns a :term:`named tuple`: .. testcode:: @@ -2582,6 +2624,10 @@ The following row factory returns a :term:`named tuple`: >>> row.b # Attribute access. 2 +.. testcleanup:: + + con.close() + With some adjustments, the above recipe can be adapted to use a :class:`~dataclasses.dataclass`, or any other custom class, instead of a :class:`~collections.namedtuple`. From 2bdd8b2876bbeb8fbbb56096429fff4791dd178a Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 4 Nov 2023 13:04:05 +0300 Subject: [PATCH 02/14] Typo --- Doc/library/sqlite3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index a5a75170ceccd5..b2097070283784 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -421,7 +421,7 @@ Module functions .. testcleanup:: - conn.close() + con.close() .. function:: register_adapter(type, adapter, /) From faea5b27bcfc6508fba71e43532a92c416d1ce21 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 4 Nov 2023 13:05:54 +0300 Subject: [PATCH 03/14] More closes --- Doc/library/sqlite3.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index b2097070283784..c58a9b8772503e 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -16,6 +16,8 @@ src = sqlite3.connect(":memory:", isolation_level=None) dst = sqlite3.connect("tutorial.db", isolation_level=None) src.backup(dst) + src.close() + dst.close() del src, dst .. _sqlite3-intro: From 89cd0ca409d650d91e481686265f5797ae18d261 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 4 Nov 2023 13:23:05 +0300 Subject: [PATCH 04/14] More closes --- Doc/library/sqlite3.rst | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index c58a9b8772503e..18422c92c3f3f9 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -222,7 +222,10 @@ creating a new cursor, then querying the database: >>> title, year = res.fetchone() >>> print(f'The highest scoring Monty Python movie is {title!r}, released in {year}') The highest scoring Monty Python movie is 'Monty Python and the Holy Grail', released in 1975 - >>> con.close() + +.. testcleanup:: + + con.close() You've now created an SQLite database using the :mod:`!sqlite3` module, inserted data and retrieved values from it in multiple ways. @@ -1110,14 +1113,16 @@ Connection objects for row in con.execute("SELECT rowid, name, ingredients FROM recipe WHERE name MATCH 'pie'"): print(row) - con.close() - .. testoutput:: sqlite3.loadext :hide: (2, 'broccoli pie', 'broccoli cheese onions flour') (3, 'pumpkin pie', 'pumpkin sugar flour butter') + .. testcleanup:: + + con.close() + .. method:: load_extension(path, /, *, entrypoint=None) Load an SQLite extension from a shared library. @@ -2515,6 +2520,8 @@ Some useful URI tricks include: res = con2.execute("SELECT data FROM shared") assert res.fetchone() == (28,) + con1.close() + con2.close() More information about this feature, including a list of parameters, can be found in the `SQLite URI documentation`_. From 6df8ec50130b18eccf663451e91cdab8c2d2f31e Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 7 Nov 2023 11:05:06 +0300 Subject: [PATCH 05/14] Cleanup temp files --- Doc/library/sqlite3.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 18422c92c3f3f9..17e7ac00a7e6b5 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -227,6 +227,9 @@ creating a new cursor, then querying the database: con.close() + import os + os.remove("tutorial.db") + You've now created an SQLite database using the :mod:`!sqlite3` module, inserted data and retrieved values from it in multiple ways. @@ -1084,6 +1087,7 @@ Connection objects Added the ``sqlite3.enable_load_extension`` auditing event. .. testsetup:: sqlite3.loadext + :skipif: True import sqlite3 con = sqlite3.connect(":memory:") @@ -1120,6 +1124,7 @@ Connection objects (3, 'pumpkin pie', 'pumpkin sugar flour butter') .. testcleanup:: + :skipif: True con.close() @@ -1171,6 +1176,11 @@ Connection objects f.write('%s\n' % line) con.close() + .. testcleanup:: + + import os + os.remove('dump.sql') + .. seealso:: :ref:`sqlite3-howto-encoding` @@ -1231,6 +1241,11 @@ Connection objects Copied 0 of 0 pages... + .. testcleanup:: + + import os + os.remove('backup.db') + Example 2, copy an existing database into a transient copy: .. testcode:: @@ -1241,6 +1256,11 @@ Connection objects dst.close() src.close() + .. testcleanup:: + + import os + os.remove('example.db') + .. versionadded:: 3.7 .. seealso:: From 9113b0112126363f084cf021e6196ca833a3c206 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 7 Nov 2023 11:40:46 +0300 Subject: [PATCH 06/14] Restore unraisable hook --- Doc/library/sqlite3.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 17e7ac00a7e6b5..42cd452e57fe3c 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -225,7 +225,7 @@ creating a new cursor, then querying the database: .. testcleanup:: - con.close() + new_con.close() import os os.remove("tutorial.db") @@ -409,6 +409,8 @@ Module functions .. testsetup:: sqlite3.trace import sqlite3 + import sys + old_hook = sys.unraisablehook .. doctest:: sqlite3.trace @@ -421,15 +423,15 @@ Module functions >>> def debug(unraisable): ... print(f"{unraisable.exc_value!r} in callback {unraisable.object.__name__}") ... print(f"Error message: {unraisable.err_msg}") - >>> import sys >>> sys.unraisablehook = debug >>> cur = con.execute("SELECT 1") ZeroDivisionError('division by zero') in callback evil_trace Error message: None - .. testcleanup:: + .. testcleanup:: sqlite3.trace con.close() + sys.unraisablehook = old_hook .. function:: register_adapter(type, adapter, /) From 9c119d58b81c5a8007170915afe7b36c63bb6631 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 7 Nov 2023 12:42:03 +0300 Subject: [PATCH 07/14] Use correct test names --- Doc/library/sqlite3.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 42cd452e57fe3c..c8dcb067a0082a 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -1296,7 +1296,7 @@ Connection objects >>> con.getlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH) 1000000000 - .. testcleanup:: + .. testcleanup:: sqlite3.limits con.close() @@ -1536,10 +1536,6 @@ Cursor objects (1,) - .. testcleanup:: - - con.close() - .. _database cursor: https://en.wikipedia.org/wiki/Cursor_(databases) .. class:: Cursor @@ -1617,6 +1613,10 @@ Cursor objects # cur is an sqlite3.Cursor object cur.executemany("INSERT INTO data VALUES(?)", rows) + .. testcleanup:: sqlite3.cursor + + con.close() + .. note:: Any resulting rows are discarded, From f6414d80cca19a0c5d0d0b915fd0a2e1706a972f Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 7 Apr 2024 00:46:30 +0200 Subject: [PATCH 08/14] Don't test load ext stuff since we cannot skip it conditionally --- Doc/library/sqlite3.rst | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index bb596cc265305f..9348679eea792e 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -1088,14 +1088,10 @@ Connection objects .. versionchanged:: 3.10 Added the ``sqlite3.enable_load_extension`` auditing event. - .. testsetup:: sqlite3.loadext - :skipif: True + .. We cannot doctest the load extension API, since there is no convenient + way to skip it. - import sqlite3 - con = sqlite3.connect(":memory:") - - .. testcode:: sqlite3.loadext - :skipif: True # not testable at the moment + .. code-block:: con.enable_load_extension(True) @@ -1119,17 +1115,6 @@ Connection objects for row in con.execute("SELECT rowid, name, ingredients FROM recipe WHERE name MATCH 'pie'"): print(row) - .. testoutput:: sqlite3.loadext - :hide: - - (2, 'broccoli pie', 'broccoli cheese onions flour') - (3, 'pumpkin pie', 'pumpkin sugar flour butter') - - .. testcleanup:: - :skipif: True - - con.close() - .. method:: load_extension(path, /, *, entrypoint=None) Load an SQLite extension from a shared library. From a6f2509f369bc02dd55687c21fd7aebdbd5594af Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 7 Apr 2024 00:46:55 +0200 Subject: [PATCH 09/14] Remove silly example of sys.unraisablehook --- Doc/library/sqlite3.rst | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 9348679eea792e..bbcc99c1392d7d 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -403,35 +403,12 @@ Module functions will get tracebacks from callbacks on :data:`sys.stderr`. Use ``False`` to disable the feature again. - Register an :func:`unraisable hook handler ` for an - improved debug experience: - - .. testsetup:: sqlite3.trace - - import sqlite3 - import sys - old_hook = sys.unraisablehook - - .. doctest:: sqlite3.trace - - >>> sqlite3.enable_callback_tracebacks(True) - >>> con = sqlite3.connect(":memory:") - >>> def evil_trace(stmt): - ... 5/0 - ... - >>> con.set_trace_callback(evil_trace) - >>> def debug(unraisable): - ... print(f"{unraisable.exc_value!r} in callback {unraisable.object.__name__}") - ... print(f"Error message: {unraisable.err_msg}") - >>> sys.unraisablehook = debug - >>> cur = con.execute("SELECT 1") - ZeroDivisionError('division by zero') in callback evil_trace - Error message: None - - .. testcleanup:: sqlite3.trace + .. note:: - con.close() - sys.unraisablehook = old_hook + Exceptions that are raised in user-defined function callbacks are + raised as unraisable exceptions. + Use an :func:`unraisable hook handler ` for + introspection of the failed callback. .. function:: register_adapter(type, adapter, /) From 389640cdd0235da69f9c2957ccb40cbf3ffd66b3 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 8 Apr 2024 08:39:02 +0200 Subject: [PATCH 10/14] Align with changes from gh-117604 --- Doc/library/sqlite3.rst | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 8cb538d5bd1a98..570b92b68ebbbd 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -227,9 +227,6 @@ creating a new cursor, then querying the database: new_con.close() - import os - os.remove("tutorial.db") - You've now created an SQLite database using the :mod:`!sqlite3` module, inserted data and retrieved values from it in multiple ways. @@ -1147,11 +1144,6 @@ Connection objects f.write('%s\n' % line) con.close() - .. testcleanup:: - - import os - os.remove('dump.sql') - .. seealso:: :ref:`sqlite3-howto-encoding` @@ -1214,11 +1206,6 @@ Connection objects Copied 0 of 0 pages... - .. testcleanup:: - - import os - os.remove('backup.db') - Example 2, copy an existing database into a transient copy: .. testcode:: @@ -1229,11 +1216,6 @@ Connection objects dst.close() src.close() - .. testcleanup:: - - import os - os.remove('example.db') - .. versionadded:: 3.7 .. seealso:: From 4432e6bf38e228ec7f24bd8556c84ee6d6b2a9a5 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 8 Apr 2024 09:06:30 +0200 Subject: [PATCH 11/14] Revert "Remove silly example of sys.unraisablehook" This reverts commit a6f2509f369bc02dd55687c21fd7aebdbd5594af. --- Doc/library/sqlite3.rst | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 570b92b68ebbbd..de26d7704e7785 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -400,12 +400,35 @@ Module functions will get tracebacks from callbacks on :data:`sys.stderr`. Use ``False`` to disable the feature again. - .. note:: + Register an :func:`unraisable hook handler ` for an + improved debug experience: + + .. testsetup:: sqlite3.trace - Exceptions that are raised in user-defined function callbacks are - raised as unraisable exceptions. - Use an :func:`unraisable hook handler ` for - introspection of the failed callback. + import sqlite3 + import sys + old_hook = sys.unraisablehook + + .. doctest:: sqlite3.trace + + >>> sqlite3.enable_callback_tracebacks(True) + >>> con = sqlite3.connect(":memory:") + >>> def evil_trace(stmt): + ... 5/0 + ... + >>> con.set_trace_callback(evil_trace) + >>> def debug(unraisable): + ... print(f"{unraisable.exc_value!r} in callback {unraisable.object.__name__}") + ... print(f"Error message: {unraisable.err_msg}") + >>> sys.unraisablehook = debug + >>> cur = con.execute("SELECT 1") + ZeroDivisionError('division by zero') in callback evil_trace + Error message: None + + .. testcleanup:: sqlite3.trace + + con.close() + sys.unraisablehook = old_hook .. function:: register_adapter(type, adapter, /) From 9cef674ecc179718b96d1b0b57861a10edc5c251 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 8 Apr 2024 09:06:49 +0200 Subject: [PATCH 12/14] Revert "Don't test load ext stuff since we cannot skip it conditionally" This reverts commit f6414d80cca19a0c5d0d0b915fd0a2e1706a972f. --- Doc/library/sqlite3.rst | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index de26d7704e7785..4efc4e63c9984d 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -1085,10 +1085,14 @@ Connection objects .. versionchanged:: 3.10 Added the ``sqlite3.enable_load_extension`` auditing event. - .. We cannot doctest the load extension API, since there is no convenient - way to skip it. + .. testsetup:: sqlite3.loadext + :skipif: True - .. code-block:: + import sqlite3 + con = sqlite3.connect(":memory:") + + .. testcode:: sqlite3.loadext + :skipif: True # not testable at the moment con.enable_load_extension(True) @@ -1112,6 +1116,17 @@ Connection objects for row in con.execute("SELECT rowid, name, ingredients FROM recipe WHERE name MATCH 'pie'"): print(row) + .. testoutput:: sqlite3.loadext + :hide: + + (2, 'broccoli pie', 'broccoli cheese onions flour') + (3, 'pumpkin pie', 'pumpkin sugar flour butter') + + .. testcleanup:: + :skipif: True + + con.close() + .. method:: load_extension(path, /, *, entrypoint=None) Load an SQLite extension from a shared library. From fbf5c6cd118579eff779f0e39b4482efb5d2f2e0 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 8 Apr 2024 09:10:22 +0200 Subject: [PATCH 13/14] Remove changes done by gh-117623 --- Doc/library/sqlite3.rst | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 4efc4e63c9984d..78f578dcc82d3c 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -406,8 +406,6 @@ Module functions .. testsetup:: sqlite3.trace import sqlite3 - import sys - old_hook = sys.unraisablehook .. doctest:: sqlite3.trace @@ -425,11 +423,6 @@ Module functions ZeroDivisionError('division by zero') in callback evil_trace Error message: None - .. testcleanup:: sqlite3.trace - - con.close() - sys.unraisablehook = old_hook - .. function:: register_adapter(type, adapter, /) Register an *adapter* :term:`callable` to adapt the Python type *type* @@ -1086,7 +1079,6 @@ Connection objects Added the ``sqlite3.enable_load_extension`` auditing event. .. testsetup:: sqlite3.loadext - :skipif: True import sqlite3 con = sqlite3.connect(":memory:") @@ -1116,6 +1108,8 @@ Connection objects for row in con.execute("SELECT rowid, name, ingredients FROM recipe WHERE name MATCH 'pie'"): print(row) + con.close() + .. testoutput:: sqlite3.loadext :hide: @@ -1123,7 +1117,6 @@ Connection objects (3, 'pumpkin pie', 'pumpkin sugar flour butter') .. testcleanup:: - :skipif: True con.close() From f170f7ccb53cb6ac9e115bee306ed37b20630088 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 8 Apr 2024 11:11:57 +0200 Subject: [PATCH 14/14] Fix the remaining resource warnings; looks like Sphinx has an inconsistency with the doctest and testcleanup directives --- Doc/library/sqlite3.rst | 42 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 8cb30047d641cd..e6961821b639b9 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -222,10 +222,7 @@ creating a new cursor, then querying the database: >>> title, year = res.fetchone() >>> print(f'The highest scoring Monty Python movie is {title!r}, released in {year}') The highest scoring Monty Python movie is 'Monty Python and the Holy Grail', released in 1975 - -.. testcleanup:: - - new_con.close() + >>> new_con.close() You've now created an SQLite database using the :mod:`!sqlite3` module, inserted data and retrieved values from it in multiple ways. @@ -750,10 +747,7 @@ Connection objects >>> for row in con.execute("SELECT md5(?)", (b"foo",)): ... print(row) ('acbd18db4cc2f85cedef654fccc4a4d8',) - - .. testcleanup:: - - con.close() + >>> con.close() .. versionchanged:: 3.13 @@ -1248,10 +1242,6 @@ Connection objects >>> con.getlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH) 1000000000 - .. testcleanup:: sqlite3.limits - - con.close() - .. versionadded:: 3.11 @@ -1284,6 +1274,10 @@ Connection objects >>> con.getlimit(sqlite3.SQLITE_LIMIT_ATTACHED) 1 + .. testcleanup:: sqlite3.limits + + con.close() + .. versionadded:: 3.11 .. _SQLite limit category: https://www.sqlite.org/c3ref/c_limit_attached.html @@ -1674,10 +1668,7 @@ Cursor objects >>> cur = con.cursor() >>> cur.connection == con True - - .. testcleanup:: - - con.close() + >>> con.close() .. attribute:: description @@ -2528,10 +2519,6 @@ assign it to the :attr:`!row_factory` attribute: >>> con = sqlite3.connect(":memory:") >>> con.row_factory = sqlite3.Row -.. testcleanup:: - - con.close() - Queries now return :class:`!Row` objects: .. doctest:: @@ -2546,10 +2533,7 @@ Queries now return :class:`!Row` objects: 'Earth' >>> row["RADIUS"] # Column names are case-insensitive. 6378 - -.. testcleanup:: - - con.close() + >>> con.close() .. note:: @@ -2576,10 +2560,7 @@ Using it, queries now return a :class:`!dict` instead of a :class:`!tuple`: >>> for row in con.execute("SELECT 1 AS a, 2 AS b"): ... print(row) {'a': 1, 'b': 2} - -.. testcleanup:: - - con.close() + >>> con.close() The following row factory returns a :term:`named tuple`: @@ -2606,10 +2587,7 @@ The following row factory returns a :term:`named tuple`: 1 >>> row.b # Attribute access. 2 - -.. testcleanup:: - - con.close() + >>> con.close() With some adjustments, the above recipe can be adapted to use a :class:`~dataclasses.dataclass`, or any other custom class,