Skip to content

Commit da6481f

Browse files
author
Erlend E. Aasland
committed
Merge branch 'main' into sqlite-threadsafety
2 parents 2465ad2 + 401272e commit da6481f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+572
-336
lines changed

Doc/extending/newtypes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ analogous to the :ref:`rich comparison methods <richcmpfuncs>`, like
393393
:c:func:`PyObject_RichCompareBool`.
394394

395395
This function is called with two Python objects and the operator as arguments,
396-
where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GT``,
396+
where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GE``,
397397
``Py_LT`` or ``Py_GT``. It should compare the two objects with respect to the
398398
specified operator and return ``Py_True`` or ``Py_False`` if the comparison is
399399
successful, ``Py_NotImplemented`` to indicate that comparison is not

Doc/library/importlib.metadata.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
.. versionchanged:: 3.10
1212
``importlib.metadata`` is no longer provisional.
1313

14-
**Source code:** :source:`Lib/importlib/metadata.py`
14+
**Source code:** :source:`Lib/importlib/metadata/__init__.py`
1515

1616
``importlib.metadata`` is a library that provides for access to installed
1717
package metadata. Built in part on Python's import system, this library

Doc/library/importlib.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,9 @@ ABC hierarchy::
815815

816816
.. versionadded:: 3.9
817817

818-
.. abstractmethod:: name()
818+
.. attribute:: name
819819

820-
The base name of this object without any parent references.
820+
Abstract. The base name of this object without any parent references.
821821

822822
.. abstractmethod:: iterdir()
823823

Doc/library/logging.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ is the module's name in the Python package namespace.
203203
attributes can then be used as you like. For example, they could be
204204
incorporated into logged messages. For example::
205205

206-
FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s'
206+
FORMAT = '%(asctime)s %(clientip)-15s %(user)-8s %(message)s'
207207
logging.basicConfig(format=FORMAT)
208208
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
209209
logger = logging.getLogger('tcpserver')
@@ -1000,7 +1000,7 @@ functions.
10001000
be used as you like. For example, they could be incorporated into logged
10011001
messages. For example::
10021002

1003-
FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s'
1003+
FORMAT = '%(asctime)s %(clientip)-15s %(user)-8s %(message)s'
10041004
logging.basicConfig(format=FORMAT)
10051005
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
10061006
logging.warning('Protocol problem: %s', 'connection reset', extra=d)

Doc/library/sqlite3.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,40 @@ Connection Objects
678678
.. versionadded:: 3.7
679679

680680

681+
.. method:: getlimit(category, /)
682+
683+
Get a connection run-time limit. *category* is the limit category to be
684+
queried.
685+
686+
Example, query the maximum length of an SQL statement::
687+
688+
import sqlite3
689+
con = sqlite3.connect(":memory:")
690+
lim = con.getlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH)
691+
print(f"SQLITE_LIMIT_SQL_LENGTH={lim}")
692+
693+
.. versionadded:: 3.11
694+
695+
696+
.. method:: setlimit(category, limit, /)
697+
698+
Set a connection run-time limit. *category* is the limit category to be
699+
set. *limit* is the new limit. If the new limit is a negative number, the
700+
limit is unchanged.
701+
702+
Attempts to increase a limit above its hard upper bound are silently
703+
truncated to the hard upper bound. Regardless of whether or not the limit
704+
was changed, the prior value of the limit is returned.
705+
706+
Example, limit the number of attached databases to 1::
707+
708+
import sqlite3
709+
con = sqlite3.connect(":memory:")
710+
con.setlimit(sqlite3.SQLITE_LIMIT_ATTACHED, 1)
711+
712+
.. versionadded:: 3.11
713+
714+
681715
.. _sqlite3-cursor-objects:
682716

683717
Cursor Objects

Doc/requirements.txt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@
33
# Sphinx version is pinned so that new versions that introduce new warnings
44
# won't suddenly cause build failures. Updating the version is fine as long
55
# as no warnings are raised by doing so.
6-
sphinx==3.2.1
7-
# Docutils version is pinned to a version compatible with Sphinx
8-
# version 3.2.1. It can be removed after bumping Sphinx version to at
9-
# least 3.5.4.
10-
docutils==0.17.1
6+
sphinx==4.2.0
117

128
blurb
139

Doc/whatsnew/3.11.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ sqlite3
248248
(Contributed by Aviv Palivoda, Daniel Shahaf, and Erlend E. Aasland in
249249
:issue:`16379`.)
250250

251+
* Add :meth:`~sqlite3.Connection.setlimit` and
252+
:meth:`~sqlite3.Connection.getlimit` to :class:`sqlite3.Connection` for
253+
setting and getting SQLite limits by connection basis.
254+
(Contributed by Erlend E. Aasland in :issue:`45243`.)
255+
251256
* :mod:`sqlite3` now sets :attr:`sqlite3.threadsafety` based on the default
252257
threading mode the underlying SQLite library has been compiled with.
253258
(Contributed by Erlend E. Aasland in :issue:`45613`.)

Lib/test/datetimetester.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131
from datetime import date, datetime
3232
import time as _time
3333

34-
import _testcapi
34+
try:
35+
import _testcapi
36+
except ImportError:
37+
_testcapi = None
3538

3639
# Needed by test_datetime
3740
import _strptime
@@ -5918,6 +5921,7 @@ class IranTest(ZoneInfoTest):
59185921
zonename = 'Asia/Tehran'
59195922

59205923

5924+
@unittest.skipIf(_testcapi is None, 'need _testcapi module')
59215925
class CapiTest(unittest.TestCase):
59225926
def setUp(self):
59235927
# Since the C API is not present in the _Pure tests, skip all tests

Lib/test/libregrtest/pgo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
'test_pprint',
4141
'test_re',
4242
'test_set',
43-
'test_sqlite',
43+
'test_sqlite3',
4444
'test_statistics',
4545
'test_struct',
4646
'test_tabnanny',

Lib/test/string_tests.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import unittest, string, sys, struct
66
from test import support
7+
from test.support import import_helper
78
from collections import UserList
89
import random
910

@@ -1328,17 +1329,17 @@ class X(object): pass
13281329

13291330
@support.cpython_only
13301331
def test_formatting_c_limits(self):
1331-
from _testcapi import PY_SSIZE_T_MAX, INT_MAX, UINT_MAX
1332-
SIZE_MAX = (1 << (PY_SSIZE_T_MAX.bit_length() + 1)) - 1
1332+
_testcapi = import_helper.import_module('_testcapi')
1333+
SIZE_MAX = (1 << (_testcapi.PY_SSIZE_T_MAX.bit_length() + 1)) - 1
13331334
self.checkraises(OverflowError, '%*s', '__mod__',
1334-
(PY_SSIZE_T_MAX + 1, ''))
1335+
(_testcapi.PY_SSIZE_T_MAX + 1, ''))
13351336
self.checkraises(OverflowError, '%.*f', '__mod__',
1336-
(INT_MAX + 1, 1. / 7))
1337+
(_testcapi.INT_MAX + 1, 1. / 7))
13371338
# Issue 15989
13381339
self.checkraises(OverflowError, '%*s', '__mod__',
13391340
(SIZE_MAX + 1, ''))
13401341
self.checkraises(OverflowError, '%.*f', '__mod__',
1341-
(UINT_MAX + 1, 1. / 7))
1342+
(_testcapi.UINT_MAX + 1, 1. / 7))
13421343

13431344
def test_floatformatting(self):
13441345
# float formatting

Lib/test/support/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,10 @@ def requires_lzma(reason='requires lzma'):
444444
return unittest.skipUnless(lzma, reason)
445445

446446
def has_no_debug_ranges():
447-
import _testinternalcapi
447+
try:
448+
import _testinternalcapi
449+
except ImportError:
450+
raise unittest.SkipTest("_testinternalcapi required")
448451
config = _testinternalcapi.get_config()
449452
return bool(config['no_debug_ranges'])
450453

@@ -692,7 +695,10 @@ def calcvobjsize(fmt):
692695
_TPFLAGS_HEAPTYPE = 1<<9
693696

694697
def check_sizeof(test, o, size):
695-
import _testinternalcapi
698+
try:
699+
import _testinternalcapi
700+
except ImportError:
701+
raise unittest.SkipTest("_testinternalcapi required")
696702
result = sys.getsizeof(o)
697703
# add GC header size
698704
if ((type(o) == type) and (o.__flags__ & _TPFLAGS_HEAPTYPE) or\

Lib/test/test_array.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import collections.abc
66
import unittest
77
from test import support
8+
from test.support import import_helper
89
from test.support import os_helper
910
from test.support import _2G
1011
import weakref
@@ -1147,9 +1148,9 @@ def test_initialize_with_unicode(self):
11471148

11481149
@support.cpython_only
11491150
def test_obsolete_write_lock(self):
1150-
from _testcapi import getbuffer_with_null_view
1151+
_testcapi = import_helper.import_module('_testcapi')
11511152
a = array.array('B', b"")
1152-
self.assertRaises(BufferError, getbuffer_with_null_view, a)
1153+
self.assertRaises(BufferError, _testcapi.getbuffer_with_null_view, a)
11531154

11541155
def test_free_after_iterating(self):
11551156
support.check_free_after_iterating(self, iter, array.array,

Lib/test/test_bytes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,8 +1650,8 @@ def delslice():
16501650

16511651
@test.support.cpython_only
16521652
def test_obsolete_write_lock(self):
1653-
from _testcapi import getbuffer_with_null_view
1654-
self.assertRaises(BufferError, getbuffer_with_null_view, bytearray())
1653+
_testcapi = import_helper.import_module('_testcapi')
1654+
self.assertRaises(BufferError, _testcapi.getbuffer_with_null_view, bytearray())
16551655

16561656
def test_iterator_pickling2(self):
16571657
orig = bytearray(b'abc')

Lib/test/test_cmath.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from test.support import requires_IEEE_754, cpython_only
1+
from test.support import requires_IEEE_754, cpython_only, import_helper
22
from test.test_math import parse_testfile, test_file
33
import test.test_math as test_math
44
import unittest
@@ -452,13 +452,13 @@ def test_polar(self):
452452
@cpython_only
453453
def test_polar_errno(self):
454454
# Issue #24489: check a previously set C errno doesn't disturb polar()
455-
from _testcapi import set_errno
455+
_testcapi = import_helper.import_module('_testcapi')
456456
def polar_with_errno_set(z):
457-
set_errno(11)
457+
_testcapi.set_errno(11)
458458
try:
459459
return polar(z)
460460
finally:
461-
set_errno(0)
461+
_testcapi.set_errno(0)
462462
self.check_polar(polar_with_errno_set)
463463

464464
def test_phase(self):

Lib/test/test_codecs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1970,6 +1970,7 @@ def test_basics(self):
19701970
"encoding=%r" % encoding)
19711971

19721972
@support.cpython_only
1973+
@unittest.skipIf(_testcapi is None, 'need _testcapi module')
19731974
def test_basics_capi(self):
19741975
s = "abc123" # all codecs should be able to encode these
19751976
for encoding in all_unicode_encodings:

Lib/test/test_dict.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import unittest
99
import weakref
1010
from test import support
11+
from test.support import import_helper
1112

1213

1314
class DictTest(unittest.TestCase):
@@ -1541,7 +1542,8 @@ class CAPITest(unittest.TestCase):
15411542
# Test _PyDict_GetItem_KnownHash()
15421543
@support.cpython_only
15431544
def test_getitem_knownhash(self):
1544-
from _testcapi import dict_getitem_knownhash
1545+
_testcapi = import_helper.import_module('_testcapi')
1546+
dict_getitem_knownhash = _testcapi.dict_getitem_knownhash
15451547

15461548
d = {'x': 1, 'y': 2, 'z': 3}
15471549
self.assertEqual(dict_getitem_knownhash(d, 'x', hash('x')), 1)

Lib/test/test_embed.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,7 @@ def test_init_use_frozen_modules(self):
14941494
class SetConfigTests(unittest.TestCase):
14951495
def test_set_config(self):
14961496
# bpo-42260: Test _PyInterpreterState_SetConfig()
1497+
import_helper.import_module('_testcapi')
14971498
cmd = [sys.executable, '-I', '-m', 'test._test_embed_set_config']
14981499
proc = subprocess.run(cmd,
14991500
stdout=subprocess.PIPE,

Lib/test/test_float.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import unittest
99

1010
from test import support
11+
from test.support import import_helper
1112
from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
1213
INVALID_UNDERSCORE_LITERALS)
1314
from math import isinf, isnan, copysign, ldexp
@@ -714,7 +715,7 @@ def test_float_specials_do_unpack(self):
714715

715716
@support.requires_IEEE_754
716717
def test_serialized_float_rounding(self):
717-
from _testcapi import FLT_MAX
718+
FLT_MAX = import_helper.import_module('_testcapi').FLT_MAX
718719
self.assertEqual(struct.pack("<f", 3.40282356e38), struct.pack("<f", FLT_MAX))
719720
self.assertEqual(struct.pack("<f", -3.40282356e38), struct.pack("<f", -FLT_MAX))
720721

Lib/test/test_sqlite3/test_dbapi.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,25 @@ def test_module_constants(self):
176176
"SQLITE_TOOBIG",
177177
"SQLITE_TRANSACTION",
178178
"SQLITE_UPDATE",
179+
# Run-time limit categories
180+
"SQLITE_LIMIT_LENGTH",
181+
"SQLITE_LIMIT_SQL_LENGTH",
182+
"SQLITE_LIMIT_COLUMN",
183+
"SQLITE_LIMIT_EXPR_DEPTH",
184+
"SQLITE_LIMIT_COMPOUND_SELECT",
185+
"SQLITE_LIMIT_VDBE_OP",
186+
"SQLITE_LIMIT_FUNCTION_ARG",
187+
"SQLITE_LIMIT_ATTACHED",
188+
"SQLITE_LIMIT_LIKE_PATTERN_LENGTH",
189+
"SQLITE_LIMIT_VARIABLE_NUMBER",
190+
"SQLITE_LIMIT_TRIGGER_DEPTH",
179191
]
180192
if sqlite.sqlite_version_info >= (3, 7, 17):
181193
consts += ["SQLITE_NOTICE", "SQLITE_WARNING"]
182194
if sqlite.sqlite_version_info >= (3, 8, 3):
183195
consts.append("SQLITE_RECURSIVE")
196+
if sqlite.sqlite_version_info >= (3, 8, 7):
197+
consts.append("SQLITE_LIMIT_WORKER_THREADS")
184198
consts += ["PARSE_DECLTYPES", "PARSE_COLNAMES"]
185199
for const in consts:
186200
with self.subTest(const=const):
@@ -341,6 +355,28 @@ def test_drop_unused_refs(self):
341355
cu = self.cx.execute(f"select {n}")
342356
self.assertEqual(cu.fetchone()[0], n)
343357

358+
def test_connection_limits(self):
359+
category = sqlite.SQLITE_LIMIT_SQL_LENGTH
360+
saved_limit = self.cx.getlimit(category)
361+
try:
362+
new_limit = 10
363+
prev_limit = self.cx.setlimit(category, new_limit)
364+
self.assertEqual(saved_limit, prev_limit)
365+
self.assertEqual(self.cx.getlimit(category), new_limit)
366+
msg = "string or blob too big"
367+
self.assertRaisesRegex(sqlite.DataError, msg,
368+
self.cx.execute, "select 1 as '16'")
369+
finally: # restore saved limit
370+
self.cx.setlimit(category, saved_limit)
371+
372+
def test_connection_bad_limit_category(self):
373+
msg = "'category' is out of bounds"
374+
cat = 1111
375+
self.assertRaisesRegex(sqlite.ProgrammingError, msg,
376+
self.cx.getlimit, cat)
377+
self.assertRaisesRegex(sqlite.ProgrammingError, msg,
378+
self.cx.setlimit, cat, 0)
379+
344380

345381
class UninitialisedConnectionTests(unittest.TestCase):
346382
def setUp(self):
@@ -776,6 +812,8 @@ def test_check_connection_thread(self):
776812
lambda: self.con.set_trace_callback(None),
777813
lambda: self.con.set_authorizer(None),
778814
lambda: self.con.create_collation("foo", None),
815+
lambda: self.con.setlimit(sqlite.SQLITE_LIMIT_LENGTH, -1),
816+
lambda: self.con.getlimit(sqlite.SQLITE_LIMIT_LENGTH),
779817
]
780818
for fn in fns:
781819
with self.subTest(fn=fn):

Lib/test/test_struct.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sys
88

99
from test import support
10+
from test.support import import_helper
1011
from test.support.script_helper import assert_python_ok
1112

1213
ISBIGENDIAN = sys.byteorder == "big"
@@ -680,17 +681,17 @@ def test_issue35714(self):
680681

681682
@support.cpython_only
682683
def test_issue45034_unsigned(self):
683-
from _testcapi import USHRT_MAX
684-
error_msg = f'ushort format requires 0 <= number <= {USHRT_MAX}'
684+
_testcapi = import_helper.import_module('_testcapi')
685+
error_msg = f'ushort format requires 0 <= number <= {_testcapi.USHRT_MAX}'
685686
with self.assertRaisesRegex(struct.error, error_msg):
686687
struct.pack('H', 70000) # too large
687688
with self.assertRaisesRegex(struct.error, error_msg):
688689
struct.pack('H', -1) # too small
689690

690691
@support.cpython_only
691692
def test_issue45034_signed(self):
692-
from _testcapi import SHRT_MIN, SHRT_MAX
693-
error_msg = f'short format requires {SHRT_MIN} <= number <= {SHRT_MAX}'
693+
_testcapi = import_helper.import_module('_testcapi')
694+
error_msg = f'short format requires {_testcapi.SHRT_MIN} <= number <= {_testcapi.SHRT_MAX}'
694695
with self.assertRaisesRegex(struct.error, error_msg):
695696
struct.pack('h', 70000) # too large
696697
with self.assertRaisesRegex(struct.error, error_msg):

0 commit comments

Comments
 (0)