Skip to content

Commit 612eed6

Browse files
Merge branch 'main' into bigmemtest-isolate
2 parents b3b0ebc + 60dff5a commit 612eed6

14 files changed

Lines changed: 2039 additions & 1356 deletions

File tree

Lib/concurrent/interpreters/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,14 @@ def create():
6868

6969
def list_all():
7070
"""Return all existing interpreters."""
71-
return [Interpreter(id, _whence=whence)
72-
for id, whence in _interpreters.list_all(require_ready=True)]
71+
interps = []
72+
for id, whence in _interpreters.list_all(require_ready=True):
73+
try:
74+
interps.append(Interpreter(id, _whence=whence))
75+
except InterpreterNotFoundError:
76+
# It was destroyed after it was listed.
77+
pass
78+
return interps
7379

7480

7581
def get_current():

Lib/importlib/_bootstrap_external.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,10 @@ def _bless_my_loader(module_globals):
634634
loader = module_globals.get('__loader__', None)
635635
spec = module_globals.get('__spec__', missing)
636636

637+
# The __main__ module of a script or the REPL has __spec__ set to None.
638+
if spec is None and module_globals.get('__name__') == '__main__':
639+
return loader
640+
637641
if loader is None:
638642
if spec is missing:
639643
# If working with a module:

Lib/stringprep.py

Lines changed: 257 additions & 66 deletions
Large diffs are not rendered by default.

Lib/test/test_codecs.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,15 @@ def test_builtin_encode(self):
16951695
self.assertEqual("pyth\xf6n.org".encode("idna"), b"xn--pythn-mua.org")
16961696
self.assertEqual("pyth\xf6n.org.".encode("idna"), b"xn--pythn-mua.org.")
16971697

1698+
@support.subTests(['unicode', 'encoded'], [
1699+
('\N{CHEROKEE LETTER A}\N{CHEROKEE LETTER A}', b"xn--58da"),
1700+
('\N{GEORGIAN CAPITAL LETTER AN}.', b"xn--7md."),
1701+
('\N{CYRILLIC LETTER PALOCHKA}.example', b"xn--d5a.example"),
1702+
('\N{ROMAN NUMERAL REVERSED ONE HUNDRED}.example.', b"xn--q5g.example."),
1703+
])
1704+
def test_new_unicode_case_folding(self, unicode, encoded):
1705+
self.assertEqual(unicode.encode("idna"), encoded)
1706+
16981707
def test_builtin_encode_invalid(self):
16991708
for case, expected in self.invalid_encode_testcases:
17001709
with self.subTest(case=case, expected=expected):

Lib/test/test_interpreters/test_api.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,21 @@ def test_idempotent(self):
289289
for interp1, interp2 in zip(actual, expected):
290290
self.assertIs(interp1, interp2)
291291

292+
def test_destroyed_by_gc(self):
293+
# gh-155997: the interpreter is destroyed while list_all() runs.
294+
interp = interpreters.create()
295+
interpid = interp.id
296+
cycle = []
297+
cycle.append(cycle)
298+
cycle.append(interp)
299+
# The cycle holds the only reference, so only the collector frees it.
300+
with support.disable_gc():
301+
del interp, cycle
302+
303+
with support.gc_threshold(1):
304+
ids = [i.id for i in interpreters.list_all()]
305+
self.assertNotIn(interpid, ids)
306+
292307
def test_created_with_capi(self):
293308
mainid, *_ = _interpreters.get_main()
294309
interpid1 = _interpreters.create()

Lib/test/test_unicodedata.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ def test_category(self):
321321
self.assertRaises(TypeError, self.db.category, 'xx')
322322

323323
def test_bidirectional(self):
324-
self.assertEqual(self.db.bidirectional('\uFFFE'), 'BN')
324+
self.assertEqual(self.db.bidirectional('\uFFFE'), '' if self.old else 'BN')
325325
self.assertEqual(self.db.bidirectional(' '), 'WS')
326326
self.assertEqual(self.db.bidirectional('A'), 'L')
327327
self.assertEqual(self.db.bidirectional('\U00020000'), 'L')
@@ -350,15 +350,13 @@ def test_bidirectional(self):
350350
self.assertRaises(TypeError, self.db.bidirectional, 'xx')
351351

352352
def test_bidirectional_unassigned(self):
353-
if self.old:
354-
return
355-
self.assertEqual(self.db.bidirectional('\u0378'), 'L')
356-
self.assertEqual(self.db.bidirectional('\u077F'), 'AL')
357-
self.assertEqual(self.db.bidirectional('\u20CF'), 'ET')
358-
self.assertEqual(self.db.bidirectional('\u0590'), 'R')
359-
self.assertEqual(self.db.bidirectional('\uFFFF'), 'BN')
360-
self.assertEqual(self.db.bidirectional('\U0001FFFE'), 'BN')
361-
self.assertEqual(self.db.bidirectional('\U00010D01'), 'AL')
353+
self.assertEqual(self.db.bidirectional('\u0378'), '' if self.old else 'L')
354+
self.assertEqual(self.db.bidirectional('\u077F'), '' if self.old else 'AL')
355+
self.assertEqual(self.db.bidirectional('\u20CF'), '' if self.old else 'ET')
356+
self.assertEqual(self.db.bidirectional('\u0590'), '' if self.old else 'R')
357+
self.assertEqual(self.db.bidirectional('\uFFFF'), '' if self.old else 'BN')
358+
self.assertEqual(self.db.bidirectional('\U0001FFFE'), '' if self.old else 'BN')
359+
self.assertEqual(self.db.bidirectional('\U00010D01'), '' if self.old else 'AL')
362360

363361
def test_decomposition(self):
364362
self.assertEqual(self.db.decomposition('\uFFFE'),'')
@@ -1104,9 +1102,9 @@ def test_block_invalid_input(self):
11041102
class Unicode_3_2_0_FunctionsTest(unittest.TestCase, BaseUnicodeFunctionsTest):
11051103
db = unicodedata.ucd_3_2_0
11061104
old = True
1107-
expectedchecksum = ('cb5bbbd1f55b67371e18222b90a8e21c87f16b72'
1105+
expectedchecksum = ('883824cb6c0ccf994e4451ebf281e2d6d479af47'
11081106
if quicktest else
1109-
'74936dffe949d99203a47e6a66565b2fc337bae7')
1107+
'68cd01e2c680b851c1fcab012efb5635b2229c2b')
11101108

11111109

11121110
class UnicodeMiscTest(unittest.TestCase):

Lib/test/test_warnings/__init__.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,6 +1717,59 @@ def test_issue_8766(self):
17171717
assert_python_ok('-c', 'pass', '-W', 'always', PYTHONPATH=cwd)
17181718

17191719

1720+
class WarnExplicitMainTests(BaseTest):
1721+
# gh-123011: warn_explicit() with module globals of the __main__ module,
1722+
# no matter how it is executed.
1723+
code = ('import warnings\n'
1724+
'warnings.warn_explicit("eggs", UserWarning, "bar", 1,\n'
1725+
' module_globals=globals())\n')
1726+
1727+
def prepare_code(self):
1728+
"""Make the subprocess use the tested implementation."""
1729+
if self.module is py_warnings:
1730+
return ("import sys\n"
1731+
"sys.modules['_warnings'] = None\n") + self.code
1732+
return self.code
1733+
1734+
def check(self, err):
1735+
lines = err.decode().splitlines()
1736+
# Only the Python implementation adds the source line.
1737+
if len(lines) > 1 and lines[1].startswith(' '):
1738+
del lines[1]
1739+
self.assertEqual(lines, ['bar:1: UserWarning: eggs'])
1740+
1741+
def make_script(self, dirname):
1742+
filename = os.path.join(dirname, 'spam.py')
1743+
with open(filename, 'w', encoding='utf-8') as f:
1744+
f.write(self.prepare_code())
1745+
return filename
1746+
1747+
def test_script(self):
1748+
# __main__ has __spec__ set to None.
1749+
with os_helper.temp_dir() as dirname:
1750+
filename = self.make_script(dirname)
1751+
rc, out, err = assert_python_ok(filename)
1752+
self.check(err)
1753+
1754+
def test_module(self):
1755+
# __main__ has __spec__ of the module executed with -m.
1756+
with os_helper.temp_dir() as dirname:
1757+
self.make_script(dirname)
1758+
rc, out, err = assert_python_ok('-m', 'spam', PYTHONPATH=dirname)
1759+
self.check(err)
1760+
1761+
def test_command(self):
1762+
# __main__ has the built-in importer as a loader.
1763+
rc, out, err = assert_python_ok('-c', self.prepare_code())
1764+
self.check(err)
1765+
1766+
class CWarnExplicitMainTests(WarnExplicitMainTests, unittest.TestCase):
1767+
module = c_warnings
1768+
1769+
class PyWarnExplicitMainTests(WarnExplicitMainTests, unittest.TestCase):
1770+
module = py_warnings
1771+
1772+
17201773
class FinalizationTest(unittest.TestCase):
17211774
def test_finalization(self):
17221775
# Issue #19421: warnings.warn() should not crash
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:func:`warnings.warn_explicit` no longer emits a spurious
2+
:exc:`DeprecationWarning` or raises :exc:`ImportError` when it is called with
3+
the globals of the :mod:`__main__` module.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :func:`concurrent.interpreters.list_all`. It failed if an interpreter
2+
was destroyed during the call, in particular by a garbage collection which
3+
finalized the object owning the last reference to it.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Change the :mod:`stringprep` module and :mod:`encodings.idna` codec to not
2+
consider Unicode codepoint attributes beyond those defined in :rfc:`3454`.

0 commit comments

Comments
 (0)