Skip to content

Commit 2a586c4

Browse files
gh-90016: Deprecate default sqlite3 adapters and converters
1 parent bd3c1c1 commit 2a586c4

File tree

7 files changed

+61
-50
lines changed

7 files changed

+61
-50
lines changed

Doc/includes/sqlite3/pysqlite_datetime.py

Lines changed: 0 additions & 22 deletions
This file was deleted.

Doc/library/sqlite3.rst

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,8 @@ This function can then be registered using :func:`register_adapter`.
13051305
.. literalinclude:: ../includes/sqlite3/adapter_point_2.py
13061306

13071307

1308+
.. _sqlite3-converters:
1309+
13081310
Converting SQLite values to custom Python types
13091311
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13101312

@@ -1345,27 +1347,24 @@ The following example illustrates the implicit and explicit approaches:
13451347
.. literalinclude:: ../includes/sqlite3/converter_point.py
13461348

13471349

1348-
Default adapters and converters
1349-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1350-
1351-
There are default adapters for the date and datetime types in the datetime
1352-
module. They will be sent as ISO dates/ISO timestamps to SQLite.
1350+
Default adapters and converters (deprecated)
1351+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13531352

1354-
The default converters are registered under the name "date" for
1355-
:class:`datetime.date` and under the name "timestamp" for
1356-
:class:`datetime.datetime`.
1357-
1358-
This way, you can use date/timestamps from Python without any additional
1359-
fiddling in most cases. The format of the adapters is also compatible with the
1360-
experimental SQLite date/time functions.
1353+
.. note::
13611354

1362-
The following example demonstrates this.
1355+
The default adapters and converters are deprecated as of Python 3.12.
1356+
Use the :ref:`sqlite3-adapter-converter-recipes`
1357+
and tailor them to you need.
13631358

1364-
.. literalinclude:: ../includes/sqlite3/pysqlite_datetime.py
1359+
The deprecated default adapters and converters consists of:
13651360

1366-
If a timestamp stored in SQLite has a fractional part longer than 6
1367-
numbers, its value will be truncated to microsecond precision by the
1368-
timestamp converter.
1361+
* Adapt :class:`datetime.date` objects to ISO format :class:`strings <str>`.
1362+
* Adapt :class:`datetime.datetime` objects to ISO format :class:`strings <str>`.
1363+
* Convert :ref:`declared <sqlite3-converters>` "date" types to ``datetime.date``
1364+
objects.
1365+
* Convert declared "timestamp" types to ``datetime.datetime`` objects.
1366+
If a timestamp stored in SQLite has a fractional part longer than 6
1367+
numbers, its value will be truncated to microsecond precision.
13691368

13701369
.. note::
13711370

@@ -1374,6 +1373,12 @@ timestamp converter.
13741373
offsets in timestamps, either leave converters disabled, or register an
13751374
offset-aware converter with :func:`register_converter`.
13761375

1376+
.. versionchanged:: 3.12
1377+
1378+
Deprecated default adapters and converters.
1379+
1380+
.. deprecated:: 3.12
1381+
13771382

13781383
.. _sqlite3-adapter-converter-recipes:
13791384

Doc/whatsnew/3.12.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ CPython bytecode changes
118118
Deprecated
119119
==========
120120

121+
* The default :mod:`sqlite3` adapters and converters are now deprecated.
122+
(Contributed by Erlend E. Aasland in :gh:`90016`.)
123+
121124

122125
Pending Removal in Python 3.13
123126
==============================

Lib/sqlite3/dbapi2.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,24 @@ def TimestampFromTicks(ticks):
5555
collections.abc.Sequence.register(Row)
5656

5757
def register_adapters_and_converters():
58+
from warnings import warn
59+
60+
msg = "The default {what} are deprecated as of Python 3.12"
61+
5862
def adapt_date(val):
63+
warn(msg.format(what="adapters"), DeprecationWarning, stacklevel=2)
5964
return val.isoformat()
6065

6166
def adapt_datetime(val):
67+
warn(msg.format(what="adapters"), DeprecationWarning, stacklevel=2)
6268
return val.isoformat(" ")
6369

6470
def convert_date(val):
71+
warn(msg.format(what="converters"), DeprecationWarning, stacklevel=2)
6572
return datetime.date(*map(int, val.split(b"-")))
6673

6774
def convert_timestamp(val):
75+
warn(msg.format(what="converters"), DeprecationWarning, stacklevel=2)
6876
datepart, timepart = val.split(b" ")
6977
year, month, day = map(int, datepart.split(b"-"))
7078
timepart_full = timepart.split(b".")

Lib/test/test_sqlite3/test_regression.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ def test_type_map_usage(self):
129129
con = sqlite.connect(":memory:",detect_types=sqlite.PARSE_DECLTYPES)
130130
cur = con.cursor()
131131
cur.execute("create table foo(bar timestamp)")
132-
cur.execute("insert into foo(bar) values (?)", (datetime.datetime.now(),))
132+
with self.assertWarnsRegex(DeprecationWarning, "adapters"):
133+
cur.execute("insert into foo(bar) values (?)", (datetime.datetime.now(),))
133134
cur.execute(SELECT)
134135
cur.execute("drop table foo")
135136
cur.execute("create table foo(bar integer)")
@@ -305,7 +306,8 @@ def test_convert_timestamp_microsecond_padding(self):
305306
cur.execute("INSERT INTO t (x) VALUES ('2012-04-04 15:06:00.123456789')")
306307

307308
cur.execute("SELECT * FROM t")
308-
values = [x[0] for x in cur.fetchall()]
309+
with self.assertWarnsRegex(DeprecationWarning, "converters"):
310+
values = [x[0] for x in cur.fetchall()]
309311

310312
self.assertEqual(values, [
311313
datetime.datetime(2012, 4, 4, 15, 6, 0, 456000),

Lib/test/test_sqlite3/test_types.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -496,38 +496,51 @@ def tearDown(self):
496496

497497
def test_sqlite_date(self):
498498
d = sqlite.Date(2004, 2, 14)
499-
self.cur.execute("insert into test(d) values (?)", (d,))
499+
with self.assertWarnsRegex(DeprecationWarning, "adapters") as cm:
500+
self.cur.execute("insert into test(d) values (?)", (d,))
501+
self.assertEqual(cm.filename, __file__)
500502
self.cur.execute("select d from test")
501-
d2 = self.cur.fetchone()[0]
503+
with self.assertWarnsRegex(DeprecationWarning, "converters") as cm:
504+
d2 = self.cur.fetchone()[0]
505+
self.assertEqual(cm.filename, __file__)
502506
self.assertEqual(d, d2)
503507

504508
def test_sqlite_timestamp(self):
505509
ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0)
506-
self.cur.execute("insert into test(ts) values (?)", (ts,))
510+
with self.assertWarnsRegex(DeprecationWarning, "adapters") as cm:
511+
self.cur.execute("insert into test(ts) values (?)", (ts,))
512+
self.assertEqual(cm.filename, __file__)
507513
self.cur.execute("select ts from test")
508-
ts2 = self.cur.fetchone()[0]
514+
with self.assertWarnsRegex(DeprecationWarning, "converters") as cm:
515+
ts2 = self.cur.fetchone()[0]
516+
self.assertEqual(cm.filename, __file__)
509517
self.assertEqual(ts, ts2)
510518

511519
def test_sql_timestamp(self):
512520
now = datetime.datetime.utcnow()
513521
self.cur.execute("insert into test(ts) values (current_timestamp)")
514522
self.cur.execute("select ts from test")
515-
ts = self.cur.fetchone()[0]
523+
with self.assertWarnsRegex(DeprecationWarning, "converters"):
524+
ts = self.cur.fetchone()[0]
516525
self.assertEqual(type(ts), datetime.datetime)
517526
self.assertEqual(ts.year, now.year)
518527

519528
def test_date_time_sub_seconds(self):
520529
ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0, 500000)
521-
self.cur.execute("insert into test(ts) values (?)", (ts,))
530+
with self.assertWarnsRegex(DeprecationWarning, "adapters"):
531+
self.cur.execute("insert into test(ts) values (?)", (ts,))
522532
self.cur.execute("select ts from test")
523-
ts2 = self.cur.fetchone()[0]
533+
with self.assertWarnsRegex(DeprecationWarning, "converters"):
534+
ts2 = self.cur.fetchone()[0]
524535
self.assertEqual(ts, ts2)
525536

526537
def test_date_time_sub_seconds_floating_point(self):
527538
ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0, 510241)
528-
self.cur.execute("insert into test(ts) values (?)", (ts,))
539+
with self.assertWarnsRegex(DeprecationWarning, "adapters"):
540+
self.cur.execute("insert into test(ts) values (?)", (ts,))
529541
self.cur.execute("select ts from test")
530-
ts2 = self.cur.fetchone()[0]
542+
with self.assertWarnsRegex(DeprecationWarning, "converters"):
543+
ts2 = self.cur.fetchone()[0]
531544
self.assertEqual(ts, ts2)
532545

533546

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Deprecate default :mod:`sqlite3` adapters and converters. Patch by Erlend E.
2+
Aasland.

0 commit comments

Comments
 (0)