diff options
author | kj <28750310+Fidget-Spinner@users.noreply.github.com> | 2020-11-17 22:45:08 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-17 22:45:08 (GMT) |
commit | 71ba5f52d2a80e7beffc923c54c0b6345cd0637a (patch) | |
tree | d8a107c47353ca2c875f417321172d85221247ec | |
parent | 48a9c0eb2a3304ea64d1b32fdf9db853d5d8c429 (diff) | |
download | cpython-71ba5f52d2a80e7beffc923c54c0b6345cd0637a.zip cpython-71ba5f52d2a80e7beffc923c54c0b6345cd0637a.tar.gz cpython-71ba5f52d2a80e7beffc923c54c0b6345cd0637a.tar.bz2 |
[3.9] bpo-42332: Add weakref slot to types.GenericAlias (GH-23250) (GH-23309)
(cherry picked from commit 384b7a4bd988986bca227c7e85c32d766da74708)
-rw-r--r-- | Lib/test/test_genericalias.py | 90 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2020-11-12-23-16-14.bpo-42332.fEQIdk.rst | 1 | ||||
-rw-r--r-- | Objects/genericaliasobject.c | 6 |
3 files changed, 59 insertions, 38 deletions
diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 240aad0..912fb33 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -13,7 +13,10 @@ from contextvars import ContextVar, Token from dataclasses import Field from functools import partial, partialmethod, cached_property from mailbox import Mailbox, _PartialFile -from ctypes import Array, LibraryLoader +try: + import ctypes +except ImportError: + ctypes = None from difflib import SequenceMatcher from filecmp import dircmp from fileinput import FileInput @@ -44,45 +47,46 @@ V = TypeVar('V') class BaseTest(unittest.TestCase): """Test basics.""" + generic_types = [type, tuple, list, dict, set, frozenset, enumerate, + defaultdict, deque, + SequenceMatcher, + dircmp, + FileInput, + OrderedDict, Counter, UserDict, UserList, + Pattern, Match, + partial, partialmethod, cached_property, + AbstractContextManager, AbstractAsyncContextManager, + Awaitable, Coroutine, + AsyncIterable, AsyncIterator, + AsyncGenerator, Generator, + Iterable, Iterator, + Reversible, + Container, Collection, + Callable, + Mailbox, _PartialFile, + ContextVar, Token, + Field, + Set, MutableSet, + Mapping, MutableMapping, MappingView, + KeysView, ItemsView, ValuesView, + Sequence, MutableSequence, + MappingProxyType, AsyncGeneratorType, + DirEntry, + chain, + TemporaryDirectory, SpooledTemporaryFile, + Queue, SimpleQueue, + _AssertRaisesContext, + SplitResult, ParseResult, + ValueProxy, ApplyResult, + WeakSet, ReferenceType, ref, + ShareableList, MPSimpleQueue, + Future, _WorkItem, + Morsel] + if ctypes is not None: + generic_types.extend((ctypes.Array, ctypes.LibraryLoader)) def test_subscriptable(self): - for t in (type, tuple, list, dict, set, frozenset, enumerate, - defaultdict, deque, - SequenceMatcher, - dircmp, - FileInput, - OrderedDict, Counter, UserDict, UserList, - Pattern, Match, - partial, partialmethod, cached_property, - AbstractContextManager, AbstractAsyncContextManager, - Awaitable, Coroutine, - AsyncIterable, AsyncIterator, - AsyncGenerator, Generator, - Iterable, Iterator, - Reversible, - Container, Collection, - Callable, - Mailbox, _PartialFile, - ContextVar, Token, - Field, - Set, MutableSet, - Mapping, MutableMapping, MappingView, - KeysView, ItemsView, ValuesView, - Sequence, MutableSequence, - MappingProxyType, AsyncGeneratorType, - DirEntry, - chain, - TemporaryDirectory, SpooledTemporaryFile, - Queue, SimpleQueue, - _AssertRaisesContext, - Array, LibraryLoader, - SplitResult, ParseResult, - ValueProxy, ApplyResult, - WeakSet, ReferenceType, ref, - ShareableList, MPSimpleQueue, - Future, _WorkItem, - Morsel, - ): + for t in self.generic_types: if t is None: continue tname = t.__name__ @@ -289,5 +293,15 @@ class BaseTest(unittest.TestCase): for generic_alias_property in ("__origin__", "__args__", "__parameters__"): self.assertIn(generic_alias_property, dir_of_gen_alias) + def test_weakref(self): + for t in self.generic_types: + if t is None: + continue + tname = t.__name__ + with self.subTest(f"Testing {tname}"): + alias = t[int] + self.assertEqual(ref(alias)(), alias) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-11-12-23-16-14.bpo-42332.fEQIdk.rst b/Misc/NEWS.d/next/Core and Builtins/2020-11-12-23-16-14.bpo-42332.fEQIdk.rst new file mode 100644 index 0000000..8a2cb87 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-11-12-23-16-14.bpo-42332.fEQIdk.rst @@ -0,0 +1 @@ +:class:`types.GenericAlias` objects can now be the targets of weakrefs. diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 3e850b5..4b6c8c6 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -9,6 +9,7 @@ typedef struct { PyObject *origin; PyObject *args; PyObject *parameters; + PyObject* weakreflist; } gaobject; static void @@ -17,6 +18,9 @@ ga_dealloc(PyObject *self) gaobject *alias = (gaobject *)self; _PyObject_GC_UNTRACK(self); + if (alias->weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject *)alias); + } Py_XDECREF(alias->origin); Py_XDECREF(alias->args); Py_XDECREF(alias->parameters); @@ -593,6 +597,7 @@ PyTypeObject Py_GenericAliasType = { .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .tp_traverse = ga_traverse, .tp_richcompare = ga_richcompare, + .tp_weaklistoffset = offsetof(gaobject, weakreflist), .tp_methods = ga_methods, .tp_members = ga_members, .tp_alloc = PyType_GenericAlloc, @@ -624,6 +629,7 @@ Py_GenericAlias(PyObject *origin, PyObject *args) alias->origin = origin; alias->args = args; alias->parameters = NULL; + alias->weakreflist = NULL; _PyObject_GC_TRACK(alias); return (PyObject *)alias; } |