mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
gh-120161: Fix a Crash in the _datetime Module (gh-120182)
In gh-120009 I used an atexit hook to finalize the _datetime module's static types at interpreter shutdown. However, atexit hooks are executed very early in finalization, which is a problem in the few cases where a subclass of one of those static types is still alive until the final GC collection. The static builtin types don't have this probably because they are finalized toward the end, after the final GC collection. To avoid the problem for _datetime, I have applied a similar approach here. Also, credit goes to @mgorny and @neonene for the new tests. FYI, I would have liked to take a slightly cleaner approach with managed static types, but wanted to get a smaller fix in first for the sake of backporting. I'll circle back to the cleaner approach with a future change on the main branch.
This commit is contained in:
parent
05df063ad8
commit
b2e71ff4f8
6 changed files with 133 additions and 71 deletions
|
@ -23,7 +23,7 @@ from operator import lt, le, gt, ge, eq, ne, truediv, floordiv, mod
|
|||
|
||||
from test import support
|
||||
from test.support import is_resource_enabled, ALWAYS_EQ, LARGEST, SMALLEST
|
||||
from test.support import warnings_helper
|
||||
from test.support import script_helper, warnings_helper
|
||||
|
||||
import datetime as datetime_module
|
||||
from datetime import MINYEAR, MAXYEAR
|
||||
|
@ -6822,6 +6822,48 @@ class CapiTest(unittest.TestCase):
|
|||
self.assertEqual(ret, 0)
|
||||
|
||||
|
||||
class ExtensionModuleTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
if self.__class__.__name__.endswith('Pure'):
|
||||
self.skipTest('Not relevant in pure Python')
|
||||
|
||||
@support.cpython_only
|
||||
def test_gh_120161(self):
|
||||
with self.subTest('simple'):
|
||||
script = textwrap.dedent("""
|
||||
import datetime
|
||||
from _ast import Tuple
|
||||
f = lambda: None
|
||||
Tuple.dims = property(f, f)
|
||||
|
||||
class tzutc(datetime.tzinfo):
|
||||
pass
|
||||
""")
|
||||
script_helper.assert_python_ok('-c', script)
|
||||
|
||||
with self.subTest('complex'):
|
||||
script = textwrap.dedent("""
|
||||
import asyncio
|
||||
import datetime
|
||||
from typing import Type
|
||||
|
||||
class tzutc(datetime.tzinfo):
|
||||
pass
|
||||
_EPOCHTZ = datetime.datetime(1970, 1, 1, tzinfo=tzutc())
|
||||
|
||||
class FakeDateMeta(type):
|
||||
def __instancecheck__(self, obj):
|
||||
return True
|
||||
class FakeDate(datetime.date, metaclass=FakeDateMeta):
|
||||
pass
|
||||
def pickle_fake_date(datetime_) -> Type[FakeDate]:
|
||||
# A pickle function for FakeDate
|
||||
return FakeDate
|
||||
""")
|
||||
script_helper.assert_python_ok('-c', script)
|
||||
|
||||
|
||||
def load_tests(loader, standard_tests, pattern):
|
||||
standard_tests.addTest(ZoneInfoCompleteTest())
|
||||
return standard_tests
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue