Skip to content

Commit 384b7a4

Browse files
bpo-42332: Add weakref slot to types.GenericAlias (GH-23250)
Automerge-Triggered-By: GH:gvanrossum
1 parent c272d40 commit 384b7a4

File tree

3 files changed

+55
-38
lines changed

3 files changed

+55
-38
lines changed

Lib/test/test_genericalias.py

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -47,46 +47,46 @@
4747

4848
class BaseTest(unittest.TestCase):
4949
"""Test basics."""
50+
generic_types = [type, tuple, list, dict, set, frozenset, enumerate,
51+
defaultdict, deque,
52+
SequenceMatcher,
53+
dircmp,
54+
FileInput,
55+
OrderedDict, Counter, UserDict, UserList,
56+
Pattern, Match,
57+
partial, partialmethod, cached_property,
58+
AbstractContextManager, AbstractAsyncContextManager,
59+
Awaitable, Coroutine,
60+
AsyncIterable, AsyncIterator,
61+
AsyncGenerator, Generator,
62+
Iterable, Iterator,
63+
Reversible,
64+
Container, Collection,
65+
Callable,
66+
Mailbox, _PartialFile,
67+
ContextVar, Token,
68+
Field,
69+
Set, MutableSet,
70+
Mapping, MutableMapping, MappingView,
71+
KeysView, ItemsView, ValuesView,
72+
Sequence, MutableSequence,
73+
MappingProxyType, AsyncGeneratorType,
74+
DirEntry,
75+
chain,
76+
TemporaryDirectory, SpooledTemporaryFile,
77+
Queue, SimpleQueue,
78+
_AssertRaisesContext,
79+
SplitResult, ParseResult,
80+
ValueProxy, ApplyResult,
81+
WeakSet, ReferenceType, ref,
82+
ShareableList, MPSimpleQueue,
83+
Future, _WorkItem,
84+
Morsel]
85+
if ctypes is not None:
86+
generic_types.extend((ctypes.Array, ctypes.LibraryLoader))
5087

5188
def test_subscriptable(self):
52-
types = [type, tuple, list, dict, set, frozenset, enumerate,
53-
defaultdict, deque,
54-
SequenceMatcher,
55-
dircmp,
56-
FileInput,
57-
OrderedDict, Counter, UserDict, UserList,
58-
Pattern, Match,
59-
partial, partialmethod, cached_property,
60-
AbstractContextManager, AbstractAsyncContextManager,
61-
Awaitable, Coroutine,
62-
AsyncIterable, AsyncIterator,
63-
AsyncGenerator, Generator,
64-
Iterable, Iterator,
65-
Reversible,
66-
Container, Collection,
67-
Callable,
68-
Mailbox, _PartialFile,
69-
ContextVar, Token,
70-
Field,
71-
Set, MutableSet,
72-
Mapping, MutableMapping, MappingView,
73-
KeysView, ItemsView, ValuesView,
74-
Sequence, MutableSequence,
75-
MappingProxyType, AsyncGeneratorType,
76-
DirEntry,
77-
chain,
78-
TemporaryDirectory, SpooledTemporaryFile,
79-
Queue, SimpleQueue,
80-
_AssertRaisesContext,
81-
SplitResult, ParseResult,
82-
ValueProxy, ApplyResult,
83-
WeakSet, ReferenceType, ref,
84-
ShareableList, MPSimpleQueue,
85-
Future, _WorkItem,
86-
Morsel]
87-
if ctypes is not None:
88-
types.extend((ctypes.Array, ctypes.LibraryLoader))
89-
for t in types:
89+
for t in self.generic_types:
9090
if t is None:
9191
continue
9292
tname = t.__name__
@@ -293,5 +293,15 @@ def test_dir(self):
293293
for generic_alias_property in ("__origin__", "__args__", "__parameters__"):
294294
self.assertIn(generic_alias_property, dir_of_gen_alias)
295295

296+
def test_weakref(self):
297+
for t in self.generic_types:
298+
if t is None:
299+
continue
300+
tname = t.__name__
301+
with self.subTest(f"Testing {tname}"):
302+
alias = t[int]
303+
self.assertEqual(ref(alias)(), alias)
304+
305+
296306
if __name__ == "__main__":
297307
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:class:`types.GenericAlias` objects can now be the targets of weakrefs.

Objects/genericaliasobject.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ typedef struct {
1010
PyObject *origin;
1111
PyObject *args;
1212
PyObject *parameters;
13+
PyObject* weakreflist;
1314
} gaobject;
1415

1516
static void
@@ -18,6 +19,9 @@ ga_dealloc(PyObject *self)
1819
gaobject *alias = (gaobject *)self;
1920

2021
_PyObject_GC_UNTRACK(self);
22+
if (alias->weakreflist != NULL) {
23+
PyObject_ClearWeakRefs((PyObject *)alias);
24+
}
2125
Py_XDECREF(alias->origin);
2226
Py_XDECREF(alias->args);
2327
Py_XDECREF(alias->parameters);
@@ -599,6 +603,7 @@ PyTypeObject Py_GenericAliasType = {
599603
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
600604
.tp_traverse = ga_traverse,
601605
.tp_richcompare = ga_richcompare,
606+
.tp_weaklistoffset = offsetof(gaobject, weakreflist),
602607
.tp_methods = ga_methods,
603608
.tp_members = ga_members,
604609
.tp_alloc = PyType_GenericAlloc,
@@ -630,6 +635,7 @@ Py_GenericAlias(PyObject *origin, PyObject *args)
630635
alias->origin = origin;
631636
alias->args = args;
632637
alias->parameters = NULL;
638+
alias->weakreflist = NULL;
633639
_PyObject_GC_TRACK(alias);
634640
return (PyObject *)alias;
635641
}

0 commit comments

Comments
 (0)