Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-132413: Fix crash in _datetime when used at shutdown#132599

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
neonene wants to merge41 commits intopython:main
base:main
Choose a base branch
Loading
fromneonene:fix-132413
Open
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
41 commits
Select commitHold shift + click to select a range
a2d90ae
Update datetimetester.py
neoneneApr 16, 2025
37d317f
Make interp-dict have a strong ref to the module
neoneneApr 16, 2025
44d09c9
Fix exc leak
neoneneApr 16, 2025
19326d4
📜🤖 Added by blurb_it.
blurb-it[bot]Apr 16, 2025
c74251d
Merge branch 'main' into fix-132413
neoneneApr 16, 2025
f805ec7
Add assertion in test
neoneneApr 17, 2025
1539cc6
More assertion
neoneneApr 17, 2025
e6aa018
Allow only module's exec() to create interp-dict
neoneneApr 17, 2025
5141a76
Safer ref cycle between mod and interp-dict
neoneneApr 17, 2025
76cc153
Respect interp-dict held in module state
neoneneApr 17, 2025
e5bb7c8
Update _datetimemodule.c
neoneneApr 20, 2025
2645282
Merge branch 'main' into fix-132413
neoneneApr 20, 2025
87aa7a2
Update datetimetester.py
neoneneApr 20, 2025
b425bc8
Reword
neoneneApr 21, 2025
19de232
typo
neoneneApr 21, 2025
f7b78d9
Reword
neoneneApr 22, 2025
05811bb
Cleanup
neoneneApr 22, 2025
1416c6f
Merge branch 'main' into fix-132413
neoneneApr 22, 2025
351ac36
assert(!_Py_IsInterpreterFinalizing())
neoneneApr 24, 2025
0e4a263
Add tests
neoneneApr 25, 2025
fa0cc40
Update tests
neoneneApr 26, 2025
0377764
Take account of interp restart
neoneneApr 26, 2025
9af13a6
Add subinterp tests
neoneneApr 27, 2025
124d650
Fix tests for free-threaded builds
neoneneApr 27, 2025
c490586
Nit
neoneneApr 27, 2025
29c45a3
Merge branch 'main' into fix-132413
neoneneApr 27, 2025
db47683
Make tests generic
neoneneApr 27, 2025
ddd1635
Fix warnings
neoneneApr 27, 2025
746bf85
Update tests
neoneneApr 30, 2025
1cdaf5a
Merge branch 'main' into fix-132413
neoneneApr 30, 2025
a8f76fa
Revert to original (main)
neoneneMay 7, 2025
c7fc55e
Convert IsoCalendarDate to static type (3.12)
neoneneMay 7, 2025
b3d8a8e
Merge branch 'main' into fix-132413
neoneneMay 7, 2025
539cfed
Fix warning
neoneneMay 7, 2025
f2373f4
Merge branch 'main' into fix-132413
neoneneMay 8, 2025
d9f8544
Fix refleaks
neoneneMay 8, 2025
07ca91f
Ditto
neoneneMay 8, 2025
13b065f
Move up a function
neoneneMay 9, 2025
0052451
Smaller patch for tests
neoneneMay 13, 2025
fb29db1
Merge branch 'main' into fix-132413
neoneneMay 13, 2025
d2e2a11
Add a non-issue test case (closure)
neoneneMay 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
Revert to original (main)
  • Loading branch information
@neonene
neonene committedMay 7, 2025
commita8f76faad85906c08ef6df2ecb1b605a7d67e31c
179 changes: 21 additions & 158 deletionsLib/test/datetimetester.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -7155,73 +7155,48 @@ def test_datetime_from_timestamp(self):

self.assertEqual(dt_orig, dt_rt)

def assert_python_ok_in_subinterp(self, script, init='', fini='',
repeat=1, config='isolated'):
def test_type_check_in_subinterp(self):
# iOS requires the use of the custom framework loader,
# not the ExtensionFileLoader.
if sys.platform == "ios":
extension_loader = "AppleFrameworkLoader"
else:
extension_loader = "ExtensionFileLoader"

code = textwrap.dedent(f'''
subinterp_code = """
script = textwrap.dedent(f"""
if {_interpreters is None}:
import _testcapi
import _testcapi as module
module.test_datetime_capi()
else:
import importlib.machinery
import importlib.util
fullname = '_testcapi_datetime'
origin = importlib.util.find_spec('_testcapi').origin
loader = importlib.machinery.{extension_loader}(fullname, origin)
spec = importlib.util.spec_from_loader(fullname, loader)
_testcapi = importlib.util.module_from_spec(spec)
spec.loader.exec_module(_testcapi)
interp_index = $INTERP_INDEX$
setup = _testcapi.test_datetime_capi_newinterp # call it if needed
$SCRIPT$
"""
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

import _testcapi
from test import support
setup = _testcapi.test_datetime_capi_newinterp
$INIT$

for idx in range({repeat}):
subcode = subinterp_code.replace('$INTERP_INDEX$', str(idx))
if {_interpreters is None}:
ret = support.run_in_subinterp(subcode)
else:
import _interpreters
config = _interpreters.new_config('{config}').__dict__
ret = support.run_in_subinterp_with_config(subcode, **config)
assert ret == 0
$FINI$
''')
code = code.replace('$INIT$', init).replace('$FINI$', fini)
code = code.replace('$SCRIPT$', script)

res = script_helper.assert_python_ok('-c', code)
return res

def test_type_check_in_subinterp(self):
script = textwrap.dedent(f"""
def run(type_checker, obj):
if not type_checker(obj, True):
raise TypeError(f'{{type(obj)}} is not C API type')

setup()
import _datetime
run(_testcapi.datetime_check_date, _datetime.date.today())
run(_testcapi.datetime_check_datetime, _datetime.datetime.now())
run(_testcapi.datetime_check_time, _datetime.time(12, 30))
run(_testcapi.datetime_check_delta, _datetime.timedelta(1))
run(_testcapi.datetime_check_tzinfo, _datetime.tzinfo())
""")
self.assert_python_ok_in_subinterp(script)
if _interpreters is not None:
with self.subTest(name := 'legacy'):
self.assert_python_ok_in_subinterp(script, config=name)
run(module.datetime_check_date, _datetime.date.today())
run(module.datetime_check_datetime, _datetime.datetime.now())
run(module.datetime_check_time, _datetime.time(12, 30))
run(module.datetime_check_delta, _datetime.timedelta(1))
run(module.datetime_check_tzinfo, _datetime.tzinfo())
""")
if _interpreters is None:
ret = support.run_in_subinterp(script)
self.assertEqual(ret, 0)
else:
for name in ('isolated', 'legacy'):
with self.subTest(name):
config = _interpreters.new_config(name).__dict__
ret = support.run_in_subinterp_with_config(script, **config)
self.assertEqual(ret, 0)


class ExtensionModuleTests(unittest.TestCase):
Expand All@@ -7230,9 +7205,6 @@ def setUp(self):
if self.__class__.__name__.endswith('Pure'):
self.skipTest('Not relevant in pure Python')

def assert_python_ok_in_subinterp(self, *args, **kwargs):
return CapiTest.assert_python_ok_in_subinterp(self, *args, **kwargs)

@support.cpython_only
def test_gh_120161(self):
with self.subTest('simple'):
Expand DownExpand Up@@ -7298,117 +7270,8 @@ def test_update_type_cache(self):
assert isinstance(_datetime.timezone.utc, _datetime.tzinfo)
del sys.modules['_datetime']
""")
res = script_helper.assert_python_ok('-c', script)
self.assertFalse(res.err)

def test_module_free(self):
script = textwrap.dedent("""
import sys
import gc
import weakref
ws = weakref.WeakSet()
for _ in range(3):
import _datetime
timedelta = _datetime.timedelta # static type
ws.add(_datetime)
del sys.modules['_datetime']
del _datetime
gc.collect()
assert len(ws) == 1 # only one remains
""")
script_helper.assert_python_ok('-c', script)

@unittest.skipIf(not support.Py_DEBUG, "Debug builds only")
def test_no_leak(self):
script = textwrap.dedent("""
import datetime
datetime.datetime.strptime('20000101', '%Y%m%d').strftime('%Y%m%d')
""")
res = script_helper.assert_python_ok('-X', 'showrefcount', '-c', script)
self.assertIn(b'[0 refs, 0 blocks]', res.err)

def test_static_type_on_subinterp(self):
script = textwrap.dedent("""
date = _testcapi.get_capi_types()['date']
date.today
""")
with_setup = 'setup()' + script
with self.subTest('[PyDateTime_IMPORT] main: no, sub: yes'):
self.assert_python_ok_in_subinterp(with_setup)

with self.subTest('[PyDateTime_IMPORT] main: yes, sub: yes'):
# Fails if the setup() means test_datetime_capi() rather than
# test_datetime_capi_newinterp()
self.assert_python_ok_in_subinterp(with_setup, 'setup()')
self.assert_python_ok_in_subinterp('setup()', fini=with_setup)
self.assert_python_ok_in_subinterp(with_setup, repeat=2)

with_import = 'import _datetime' + script
with self.subTest('Explicit import'):
self.assert_python_ok_in_subinterp(with_import, 'setup()')

with_import = textwrap.dedent("""
timedelta = _testcapi.get_capi_types()['timedelta']
timedelta(days=1)
""") + script
with self.subTest('Implicit import'):
self.assert_python_ok_in_subinterp(with_import, 'setup()')

def test_static_type_at_shutdown(self):
# gh-132413
script = textwrap.dedent("""
import sys
import _datetime
timedelta = _datetime.timedelta

def gen():
try:
yield
finally:
# Exceptions are ignored here
assert not sys.modules
td = _datetime.timedelta(days=1)
assert td.days == 1
td = timedelta(days=1)
assert td.days == 1
assert not sys.modules

it = gen()
next(it)
""")
with self.subTest('MainInterpreter'):
res = script_helper.assert_python_ok('-c', script)
self.assertFalse(res.err)
with self.subTest('Subinterpreter'):
res = self.assert_python_ok_in_subinterp(script)
self.assertFalse(res.err)

script = textwrap.dedent("""
import sys
timedelta = _testcapi.get_capi_types()['timedelta']

def gen():
try:
yield
finally:
# Exceptions are ignored here
assert not sys.modules
td = timedelta(days=1)
assert td.days == 1
assert not sys.modules

it = gen()
next(it)
""")
with self.subTest('[PyDateTime_IMPORT] main: yes, sub: no'):
res = self.assert_python_ok_in_subinterp(script, 'setup()')
self.assertIn(b'ImportError: sys.meta_path is None', res.err)

with_import = 'setup()' + script
with self.subTest('[PyDateTime_IMPORT] main: no, sub: yes'):
res = self.assert_python_ok_in_subinterp(with_import)
self.assertFalse(res.err)


def load_tests(loader, standard_tests, pattern):
standard_tests.addTest(ZoneInfoCompleteTest())
Expand Down
28 changes: 0 additions & 28 deletionsLib/test/test_embed.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -440,34 +440,6 @@ def test_datetime_reset_strptime(self):
out, err = self.run_embedded_interpreter("test_repeated_init_exec", code)
self.assertEqual(out, '20000101\n' * INIT_LOOPS)

def test_datetime_capi_at_shutdown(self):
# gh-132413: datetime module is currently tested in an interp's life.
# PyDateTime_IMPORT needs to be called at least once after the restart.
code = textwrap.dedent("""
import sys
import _testcapi
_testcapi.test_datetime_capi_newinterp()
timedelta = _testcapi.get_capi_types()['timedelta']

def gen():
try:
yield
finally:
assert not sys.modules
res = 0
try:
timedelta(days=1)
res = 1
except ImportError:
res = 2
print(res)

it = gen()
next(it)
""")
out, err = self.run_embedded_interpreter("test_repeated_init_exec", code)
self.assertEqual(out, '1\n' * INIT_LOOPS)

def test_static_types_inherited_slots(self):
script = textwrap.dedent("""
import test.support
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp