bpo-42332: Add weakref slot to types.GenericAlias (GH-23250)

Automerge-Triggered-By: GH:gvanrossum
This commit is contained in:
kj 2020-11-16 11:27:23 +08:00 committed by GitHub
parent c272d40e5b
commit 384b7a4bd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 38 deletions

View File

@ -47,46 +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):
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:
types.extend((ctypes.Array, ctypes.LibraryLoader))
for t in types:
for t in self.generic_types:
if t is None:
continue
tname = t.__name__
@ -293,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()

View File

@ -0,0 +1 @@
:class:`types.GenericAlias` objects can now be the targets of weakrefs.

View File

@ -10,6 +10,7 @@ typedef struct {
PyObject *origin;
PyObject *args;
PyObject *parameters;
PyObject* weakreflist;
} gaobject;
static void
@ -18,6 +19,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);
@ -599,6 +603,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,
@ -630,6 +635,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;
}