mirror of
https://github.com/python/cpython.git
synced 2025-09-30 20:31:52 +00:00
[3.9] bpo-42332: Add weakref slot to types.GenericAlias (GH-23250) (GH-23309)
(cherry picked from commit 384b7a4bd9
)
This commit is contained in:
parent
48a9c0eb2a
commit
71ba5f52d2
3 changed files with 59 additions and 38 deletions
|
@ -13,7 +13,10 @@ from contextvars import ContextVar, Token
|
||||||
from dataclasses import Field
|
from dataclasses import Field
|
||||||
from functools import partial, partialmethod, cached_property
|
from functools import partial, partialmethod, cached_property
|
||||||
from mailbox import Mailbox, _PartialFile
|
from mailbox import Mailbox, _PartialFile
|
||||||
from ctypes import Array, LibraryLoader
|
try:
|
||||||
|
import ctypes
|
||||||
|
except ImportError:
|
||||||
|
ctypes = None
|
||||||
from difflib import SequenceMatcher
|
from difflib import SequenceMatcher
|
||||||
from filecmp import dircmp
|
from filecmp import dircmp
|
||||||
from fileinput import FileInput
|
from fileinput import FileInput
|
||||||
|
@ -44,45 +47,46 @@ V = TypeVar('V')
|
||||||
|
|
||||||
class BaseTest(unittest.TestCase):
|
class BaseTest(unittest.TestCase):
|
||||||
"""Test basics."""
|
"""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):
|
def test_subscriptable(self):
|
||||||
for t in (type, tuple, list, dict, set, frozenset, enumerate,
|
for t in self.generic_types:
|
||||||
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,
|
|
||||||
):
|
|
||||||
if t is None:
|
if t is None:
|
||||||
continue
|
continue
|
||||||
tname = t.__name__
|
tname = t.__name__
|
||||||
|
@ -289,5 +293,15 @@ class BaseTest(unittest.TestCase):
|
||||||
for generic_alias_property in ("__origin__", "__args__", "__parameters__"):
|
for generic_alias_property in ("__origin__", "__args__", "__parameters__"):
|
||||||
self.assertIn(generic_alias_property, dir_of_gen_alias)
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
:class:`types.GenericAlias` objects can now be the targets of weakrefs.
|
|
@ -9,6 +9,7 @@ typedef struct {
|
||||||
PyObject *origin;
|
PyObject *origin;
|
||||||
PyObject *args;
|
PyObject *args;
|
||||||
PyObject *parameters;
|
PyObject *parameters;
|
||||||
|
PyObject* weakreflist;
|
||||||
} gaobject;
|
} gaobject;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -17,6 +18,9 @@ ga_dealloc(PyObject *self)
|
||||||
gaobject *alias = (gaobject *)self;
|
gaobject *alias = (gaobject *)self;
|
||||||
|
|
||||||
_PyObject_GC_UNTRACK(self);
|
_PyObject_GC_UNTRACK(self);
|
||||||
|
if (alias->weakreflist != NULL) {
|
||||||
|
PyObject_ClearWeakRefs((PyObject *)alias);
|
||||||
|
}
|
||||||
Py_XDECREF(alias->origin);
|
Py_XDECREF(alias->origin);
|
||||||
Py_XDECREF(alias->args);
|
Py_XDECREF(alias->args);
|
||||||
Py_XDECREF(alias->parameters);
|
Py_XDECREF(alias->parameters);
|
||||||
|
@ -593,6 +597,7 @@ PyTypeObject Py_GenericAliasType = {
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
|
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
|
||||||
.tp_traverse = ga_traverse,
|
.tp_traverse = ga_traverse,
|
||||||
.tp_richcompare = ga_richcompare,
|
.tp_richcompare = ga_richcompare,
|
||||||
|
.tp_weaklistoffset = offsetof(gaobject, weakreflist),
|
||||||
.tp_methods = ga_methods,
|
.tp_methods = ga_methods,
|
||||||
.tp_members = ga_members,
|
.tp_members = ga_members,
|
||||||
.tp_alloc = PyType_GenericAlloc,
|
.tp_alloc = PyType_GenericAlloc,
|
||||||
|
@ -624,6 +629,7 @@ Py_GenericAlias(PyObject *origin, PyObject *args)
|
||||||
alias->origin = origin;
|
alias->origin = origin;
|
||||||
alias->args = args;
|
alias->args = args;
|
||||||
alias->parameters = NULL;
|
alias->parameters = NULL;
|
||||||
|
alias->weakreflist = NULL;
|
||||||
_PyObject_GC_TRACK(alias);
|
_PyObject_GC_TRACK(alias);
|
||||||
return (PyObject *)alias;
|
return (PyObject *)alias;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue