summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkj <28750310+Fidget-Spinner@users.noreply.github.com>2020-11-17 22:45:08 (GMT)
committerGitHub <noreply@github.com>2020-11-17 22:45:08 (GMT)
commit71ba5f52d2a80e7beffc923c54c0b6345cd0637a (patch)
treed8a107c47353ca2c875f417321172d85221247ec
parent48a9c0eb2a3304ea64d1b32fdf9db853d5d8c429 (diff)
downloadcpython-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.py90
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2020-11-12-23-16-14.bpo-42332.fEQIdk.rst1
-rw-r--r--Objects/genericaliasobject.c6
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;
}