From 6c5a312fb6d92e879bf4c570b94e18bb9ffe5970 Mon Sep 17 00:00:00 2001 From: Erlend Egeberg Aasland Date: Mon, 15 Nov 2021 23:22:42 +0100 Subject: [PATCH] bpo-45677: Reword first section of `sqlite3` docs (#29326) * bpo-45677: Avoid addressing the reader as 'you' in sqlite3 docs * Adjust wording * Adjust wording again * Typo * Update Doc/library/sqlite3.rst Co-authored-by: Jacob Walls * Address review: adjust wording * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Lib/sqlite3/__init__.py Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Lib/sqlite3/__init__.py Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Apply Alex' suggestion, and apply 80 char limit to PR * Minor adjustment Co-authored-by: Jacob Walls Co-authored-by: Alex Waygood --- Doc/library/sqlite3.rst | 38 ++++++++++++++++++++------------------ Lib/sqlite3/__init__.py | 8 ++++---- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 91bf7b0e7c8..9fffe4da901 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -21,16 +21,17 @@ The sqlite3 module was written by Gerhard Häring. It provides a SQL interface compliant with the DB-API 2.0 specification described by :pep:`249`, and requires SQLite 3.7.15 or newer. -To use the module, you must first create a :class:`Connection` object that +To use the module, start by creating a :class:`Connection` object that represents the database. Here the data will be stored in the :file:`example.db` file:: import sqlite3 con = sqlite3.connect('example.db') -You can also supply the special name ``:memory:`` to create a database in RAM. +The special path name ``:memory:`` can be provided to create a temporary +database in RAM. -Once you have a :class:`Connection`, you can create a :class:`Cursor` object +Once a :class:`Connection` has been established, create a :class:`Cursor` object and call its :meth:`~Cursor.execute` method to perform SQL commands:: cur = con.cursor() @@ -49,16 +50,17 @@ and call its :meth:`~Cursor.execute` method to perform SQL commands:: # Just be sure any changes have been committed or they will be lost. con.close() -The data you've saved is persistent and is available in subsequent sessions:: +The saved data is persistent: it can be reloaded in a subsequent session even +after restarting the Python interpreter:: import sqlite3 con = sqlite3.connect('example.db') cur = con.cursor() -To retrieve data after executing a SELECT statement, you can either treat the -cursor as an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to -retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list of the -matching rows. +To retrieve data after executing a SELECT statement, either treat the cursor as +an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to +retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list +of the matching rows. This example uses the iterator form:: @@ -73,27 +75,27 @@ This example uses the iterator form:: .. _sqlite3-placeholders: -Usually your SQL operations will need to use values from Python variables. You -shouldn't assemble your query using Python's string operations because doing so -is insecure; it makes your program vulnerable to an SQL injection attack -(see the `xkcd webcomic `_ for a humorous example of -what can go wrong):: +SQL operations usually need to use values from Python variables. However, +beware of using Python's string operations to assemble queries, as they +are vulnerable to SQL injection attacks (see the `xkcd webcomic +`_ for a humorous example of what can go wrong):: # Never do this -- insecure! symbol = 'RHAT' cur.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol) -Instead, use the DB-API's parameter substitution. Put a placeholder wherever -you want to use a value, and then provide a tuple of values as the second -argument to the cursor's :meth:`~Cursor.execute` method. An SQL statement may +Instead, use the DB-API's parameter substitution. To insert a variable into a +query string, use a placeholder in the string, and substitute the actual values +into the query by providing them as a :class:`tuple` of values to the second +argument of the cursor's :meth:`~Cursor.execute` method. An SQL statement may use one of two kinds of placeholders: question marks (qmark style) or named placeholders (named style). For the qmark style, ``parameters`` must be a :term:`sequence `. For the named style, it can be either a :term:`sequence ` or :class:`dict` instance. The length of the :term:`sequence ` must match the number of placeholders, or a :exc:`ProgrammingError` is raised. If a :class:`dict` is given, it must contain -keys for all named parameters. Any extra items are ignored. Here's an example -of both styles: +keys for all named parameters. Any extra items are ignored. Here's an example of +both styles: .. literalinclude:: ../includes/sqlite3/execute_1.py diff --git a/Lib/sqlite3/__init__.py b/Lib/sqlite3/__init__.py index edc58f15b25..0dedf186b1a 100644 --- a/Lib/sqlite3/__init__.py +++ b/Lib/sqlite3/__init__.py @@ -24,18 +24,18 @@ The sqlite3 extension module provides a DB-API 2.0 (PEP 249) compilant interface to the SQLite library, and requires SQLite 3.7.15 or newer. -To use the module, you must first create a database Connection object: +To use the module, start by creating a database Connection object: import sqlite3 cx = sqlite3.connect("test.db") # test.db will be created or opened -You can also use the special database name ":memory:" to connect to a transient +The special path name ":memory:" can be provided to connect to a transient in-memory database: cx = sqlite3.connect(":memory:") # connect to a database in RAM -Once you have a Connection object, you can create a Cursor object and call its -execute() method to perform SQL queries: +Once a connection has been established, create a Cursor object and call +its execute() method to perform SQL queries: cu = cx.cursor()