gh-111726: Explicitly close database connections in sqlite3 doctests (#111730)

Co-authored-by: Erlend E. Aasland <erlend@python.org>
This commit is contained in:
Nikita Sobolev 2024-04-08 12:29:47 +03:00 committed by GitHub
parent e338e1a4ec
commit a7702663e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -16,6 +16,8 @@
src = sqlite3.connect(":memory:", isolation_level=None) src = sqlite3.connect(":memory:", isolation_level=None)
dst = sqlite3.connect("tutorial.db", isolation_level=None) dst = sqlite3.connect("tutorial.db", isolation_level=None)
src.backup(dst) src.backup(dst)
src.close()
dst.close()
del src, dst del src, dst
.. _sqlite3-intro: .. _sqlite3-intro:
@ -220,6 +222,7 @@ creating a new cursor, then querying the database:
>>> title, year = res.fetchone() >>> title, year = res.fetchone()
>>> print(f'The highest scoring Monty Python movie is {title!r}, released in {year}') >>> 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 The highest scoring Monty Python movie is 'Monty Python and the Holy Grail', released in 1975
>>> new_con.close()
You've now created an SQLite database using the :mod:`!sqlite3` module, You've now created an SQLite database using the :mod:`!sqlite3` module,
inserted data and retrieved values from it in multiple ways. inserted data and retrieved values from it in multiple ways.
@ -744,6 +747,7 @@ Connection objects
>>> for row in con.execute("SELECT md5(?)", (b"foo",)): >>> for row in con.execute("SELECT md5(?)", (b"foo",)):
... print(row) ... print(row)
('acbd18db4cc2f85cedef654fccc4a4d8',) ('acbd18db4cc2f85cedef654fccc4a4d8',)
>>> con.close()
.. versionchanged:: 3.13 .. versionchanged:: 3.13
@ -890,6 +894,7 @@ Connection objects
FROM test ORDER BY x FROM test ORDER BY x
""") """)
print(cur.fetchall()) print(cur.fetchall())
con.close()
.. testoutput:: .. testoutput::
:hide: :hide:
@ -1201,6 +1206,8 @@ Connection objects
src = sqlite3.connect('example.db') src = sqlite3.connect('example.db')
dst = sqlite3.connect(':memory:') dst = sqlite3.connect(':memory:')
src.backup(dst) src.backup(dst)
dst.close()
src.close()
.. versionadded:: 3.7 .. versionadded:: 3.7
@ -1267,6 +1274,10 @@ Connection objects
>>> con.getlimit(sqlite3.SQLITE_LIMIT_ATTACHED) >>> con.getlimit(sqlite3.SQLITE_LIMIT_ATTACHED)
1 1
.. testcleanup:: sqlite3.limits
con.close()
.. versionadded:: 3.11 .. versionadded:: 3.11
.. _SQLite limit category: https://www.sqlite.org/c3ref/c_limit_attached.html .. _SQLite limit category: https://www.sqlite.org/c3ref/c_limit_attached.html
@ -1548,6 +1559,10 @@ Cursor objects
# cur is an sqlite3.Cursor object # cur is an sqlite3.Cursor object
cur.executemany("INSERT INTO data VALUES(?)", rows) cur.executemany("INSERT INTO data VALUES(?)", rows)
.. testcleanup:: sqlite3.cursor
con.close()
.. note:: .. note::
Any resulting rows are discarded, Any resulting rows are discarded,
@ -1653,6 +1668,7 @@ Cursor objects
>>> cur = con.cursor() >>> cur = con.cursor()
>>> cur.connection == con >>> cur.connection == con
True True
>>> con.close()
.. attribute:: description .. attribute:: description
@ -1773,6 +1789,7 @@ Blob objects
greeting = blob.read() greeting = blob.read()
print(greeting) # outputs "b'Hello, world!'" print(greeting) # outputs "b'Hello, world!'"
con.close()
.. testoutput:: .. testoutput::
:hide: :hide:
@ -2085,6 +2102,7 @@ Here's an example of both styles:
params = (1972,) params = (1972,)
cur.execute("SELECT * FROM lang WHERE first_appeared = ?", params) cur.execute("SELECT * FROM lang WHERE first_appeared = ?", params)
print(cur.fetchall()) print(cur.fetchall())
con.close()
.. testoutput:: .. testoutput::
:hide: :hide:
@ -2143,6 +2161,7 @@ The object passed to *protocol* will be of type :class:`PrepareProtocol`.
cur.execute("SELECT ?", (Point(4.0, -3.2),)) cur.execute("SELECT ?", (Point(4.0, -3.2),))
print(cur.fetchone()[0]) print(cur.fetchone()[0])
con.close()
.. testoutput:: .. testoutput::
:hide: :hide:
@ -2173,6 +2192,7 @@ This function can then be registered using :func:`register_adapter`.
cur.execute("SELECT ?", (Point(1.0, 2.5),)) cur.execute("SELECT ?", (Point(1.0, 2.5),))
print(cur.fetchone()[0]) print(cur.fetchone()[0])
con.close()
.. testoutput:: .. testoutput::
:hide: :hide:
@ -2257,6 +2277,8 @@ The following example illustrates the implicit and explicit approaches:
cur.execute("INSERT INTO test(p) VALUES(?)", (p,)) cur.execute("INSERT INTO test(p) VALUES(?)", (p,))
cur.execute('SELECT p AS "p [point]" FROM test') cur.execute('SELECT p AS "p [point]" FROM test')
print("with column names:", cur.fetchone()[0]) print("with column names:", cur.fetchone()[0])
cur.close()
con.close()
.. testoutput:: .. testoutput::
:hide: :hide:
@ -2463,6 +2485,8 @@ Some useful URI tricks include:
res = con2.execute("SELECT data FROM shared") res = con2.execute("SELECT data FROM shared")
assert res.fetchone() == (28,) assert res.fetchone() == (28,)
con1.close()
con2.close()
More information about this feature, including a list of parameters, More information about this feature, including a list of parameters,
can be found in the `SQLite URI documentation`_. can be found in the `SQLite URI documentation`_.
@ -2509,6 +2533,7 @@ Queries now return :class:`!Row` objects:
'Earth' 'Earth'
>>> row["RADIUS"] # Column names are case-insensitive. >>> row["RADIUS"] # Column names are case-insensitive.
6378 6378
>>> con.close()
.. note:: .. note::
@ -2535,6 +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"): >>> for row in con.execute("SELECT 1 AS a, 2 AS b"):
... print(row) ... print(row)
{'a': 1, 'b': 2} {'a': 1, 'b': 2}
>>> con.close()
The following row factory returns a :term:`named tuple`: The following row factory returns a :term:`named tuple`:
@ -2561,6 +2587,7 @@ The following row factory returns a :term:`named tuple`:
1 1
>>> row.b # Attribute access. >>> row.b # Attribute access.
2 2
>>> con.close()
With some adjustments, the above recipe can be adapted to use a With some adjustments, the above recipe can be adapted to use a
:class:`~dataclasses.dataclass`, or any other custom class, :class:`~dataclasses.dataclass`, or any other custom class,