import annotationlib
+import atexit
import contextlib
import collections
import collections.abc
class InternalsTests(BaseTestCase):
def test_collect_parameters(self):
typing = import_helper.import_fresh_module("typing")
+ # Importing typing registers an internal function named _clear_caches
+ # with atexit. The throwaway module created here installs its own
+ # handler, which holds the module alive and keeps references until
+ # interpreter shutdown even after the test finishes. Each repetition
+ # of this test under -R would therefore leak another module copy. To
+ # avoid this, we unregister the handler once the test is done.
+ self.addCleanup(atexit.unregister, typing._clear_caches)
+
with self.assertWarnsRegex(
DeprecationWarning,
"The private _collect_parameters function is deprecated"
with self.assertWarns(DeprecationWarning):
from typing import ByteString
+ # Drop the exit handler of this throwaway copy, see the comment in
+ # InternalsTests.test_collect_parameters.
+ self.addCleanup(atexit.unregister, sys.modules["typing"]._clear_caches)
+
with self.assertWarns(DeprecationWarning):
self.assertIsInstance(b'', ByteString)
with self.assertWarns(DeprecationWarning):
"""
from abc import abstractmethod, ABCMeta
+import atexit
import collections
from collections import defaultdict
import collections.abc
cleanup()
+# Release the LRU caches at shutdown, they otherwise redistribute reference
+# leaks of one extension to types of unrelated ones. See GH-151728.
+atexit.register(_clear_caches)
+
+
def _tp_cache(func=None, /, *, typed=False):
"""Internal wrapper caching __getitem__ of generic types.
--- /dev/null
+Clear the internal :mod:`typing` caches from an exit handler. Previously, an
+extension module that leaked a reference to :mod:`typing` would also keep every
+subscripted type alive past interpreter shutdown, including types owned by
+unrelated extension modules.