Skip to content

Commit 04c73e5

Browse files
gh-95432: Add doctest for sqlite3 tutorial (#96193)
1 parent 1499d73 commit 04c73e5

File tree

1 file changed

+47
-16
lines changed

1 file changed

+47
-16
lines changed

Doc/library/sqlite3.rst

+47-16
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@
88

99
**Source code:** :source:`Lib/sqlite3/`
1010

11+
.. Make sure we always doctest the tutorial with an empty database.
12+
13+
.. testsetup::
14+
15+
import sqlite3
16+
src = sqlite3.connect(":memory:", isolation_level=None)
17+
dst = sqlite3.connect("tutorial.db", isolation_level=None)
18+
src.backup(dst)
19+
del src, dst
1120

1221
.. _sqlite3-intro:
1322

@@ -65,7 +74,9 @@ First, we need to create a new database and open
6574
a database connection to allow :mod:`!sqlite3` to work with it.
6675
Call :func:`sqlite3.connect` to to create a connection to
6776
the database :file:`tutorial.db` in the current working directory,
68-
implicitly creating it if it does not exist::
77+
implicitly creating it if it does not exist:
78+
79+
.. testcode::
6980

7081
import sqlite3
7182
con = sqlite3.connect("tutorial.db")
@@ -75,7 +86,9 @@ represents the connection to the on-disk database.
7586

7687
In order to execute SQL statements and fetch results from SQL queries,
7788
we will need to use a database cursor.
78-
Call :meth:`con.cursor() <Connection.cursor>` to create the :class:`Cursor`::
89+
Call :meth:`con.cursor() <Connection.cursor>` to create the :class:`Cursor`:
90+
91+
.. testcode::
7992

8093
cur = con.cursor()
8194

@@ -86,7 +99,9 @@ For simplicity, we can just use column names in the table declaration --
8699
thanks to the `flexible typing`_ feature of SQLite,
87100
specifying the data types is optional.
88101
Execute the ``CREATE TABLE`` statement
89-
by calling :meth:`cur.execute(...) <Cursor.execute>`::
102+
by calling :meth:`cur.execute(...) <Cursor.execute>`:
103+
104+
.. testcode::
90105

91106
cur.execute("CREATE TABLE movie(title, year, score)")
92107

@@ -99,7 +114,9 @@ which should now contain an entry for the ``movie`` table definition
99114
(see `The Schema Table`_ for details).
100115
Execute that query by calling :meth:`cur.execute(...) <Cursor.execute>`,
101116
assign the result to ``res``,
102-
and call :meth:`res.fetchone() <Cursor.fetchone>` to fetch the resulting row::
117+
and call :meth:`res.fetchone() <Cursor.fetchone>` to fetch the resulting row:
118+
119+
.. doctest::
103120

104121
>>> res = cur.execute("SELECT name FROM sqlite_master")
105122
>>> res.fetchone()
@@ -108,15 +125,19 @@ and call :meth:`res.fetchone() <Cursor.fetchone>` to fetch the resulting row::
108125
We can see that the table has been created,
109126
as the query returns a :class:`tuple` containing the table's name.
110127
If we query ``sqlite_master`` for a non-existent table ``spam``,
111-
:meth:`!res.fetchone()` will return ``None``::
128+
:meth:`!res.fetchone()` will return ``None``:
129+
130+
.. doctest::
112131

113132
>>> res = cur.execute("SELECT name FROM sqlite_master WHERE name='spam'")
114133
>>> res.fetchone() is None
115134
True
116135

117136
Now, add two rows of data supplied as SQL literals
118137
by executing an ``INSERT`` statement,
119-
once again by calling :meth:`cur.execute(...) <Cursor.execute>`::
138+
once again by calling :meth:`cur.execute(...) <Cursor.execute>`:
139+
140+
.. testcode::
120141

121142
cur.execute("""
122143
INSERT INTO movie VALUES
@@ -128,15 +149,19 @@ The ``INSERT`` statement implicitly opens a transaction,
128149
which needs to be committed before changes are saved in the database
129150
(see :ref:`sqlite3-controlling-transactions` for details).
130151
Call :meth:`con.commit() <Connection.commit>` on the connection object
131-
to commit the transaction::
152+
to commit the transaction:
153+
154+
.. testcode::
132155

133156
con.commit()
134157

135158
We can verify that the data was inserted correctly
136159
by executing a ``SELECT`` query.
137160
Use the now-familiar :meth:`cur.execute(...) <Cursor.execute>` to
138161
assign the result to ``res``,
139-
and call :meth:`res.fetchall() <Cursor.fetchall>` to return all resulting rows::
162+
and call :meth:`res.fetchall() <Cursor.fetchall>` to return all resulting rows:
163+
164+
.. doctest::
140165

141166
>>> res = cur.execute("SELECT score FROM movie")
142167
>>> res.fetchall()
@@ -146,7 +171,9 @@ The result is a :class:`list` of two :class:`!tuple`\s, one per row,
146171
each containing that row's ``score`` value.
147172

148173
Now, insert three more rows by calling
149-
:meth:`cur.executemany(...) <Cursor.executemany>`::
174+
:meth:`cur.executemany(...) <Cursor.executemany>`:
175+
176+
.. testcode::
150177

151178
data = [
152179
("Monty Python Live at the Hollywood Bowl", 1982, 7.9),
@@ -164,14 +191,16 @@ to avoid `SQL injection attacks`_
164191

165192
We can verify that the new rows were inserted
166193
by executing a ``SELECT`` query,
167-
this time iterating over the results of the query::
194+
this time iterating over the results of the query:
195+
196+
.. doctest::
168197

169198
>>> for row in cur.execute("SELECT year, title FROM movie ORDER BY year"):
170199
... print(row)
171-
(1971, "And Now for Something Completely Different")
172-
(1975, "Monty Python and the Holy Grail")
200+
(1971, 'And Now for Something Completely Different')
201+
(1975, 'Monty Python and the Holy Grail')
173202
(1979, "Monty Python's Life of Brian")
174-
(1982, "Monty Python Live at the Hollywood Bowl")
203+
(1982, 'Monty Python Live at the Hollywood Bowl')
175204
(1983, "Monty Python's The Meaning of Life")
176205

177206
Each row is a two-item :class:`tuple` of ``(year, title)``,
@@ -180,15 +209,17 @@ matching the columns selected in the query.
180209
Finally, verify that the database has been written to disk
181210
by calling :meth:`con.close() <Connection.close>`
182211
to close the existing connection, opening a new one,
183-
creating a new cursor, then querying the database::
212+
creating a new cursor, then querying the database:
213+
214+
.. doctest::
184215

185216
>>> con.close()
186217
>>> new_con = sqlite3.connect("tutorial.db")
187218
>>> new_cur = new_con.cursor()
188-
>>> res = new_cur.execute("SELECT year, title FROM movie ORDER BY score DESC"):
219+
>>> res = new_cur.execute("SELECT title, year FROM movie ORDER BY score DESC")
189220
>>> title, year = res.fetchone()
190221
>>> print(f'The highest scoring Monty Python movie is {title!r}, released in {year}')
191-
'The highest scoring Monty Python movie is "Monty Python and the Holy Grail", released in 1975'
222+
The highest scoring Monty Python movie is 'Monty Python and the Holy Grail', released in 1975
192223

193224
You've now created an SQLite database using the :mod:`!sqlite3` module,
194225
inserted data and retrieved values from it in multiple ways.

0 commit comments

Comments
 (0)