aliases = [
GenericAlias(list, T),
GenericAlias(deque, T),
- GenericAlias(X, T)
+ GenericAlias(X, T),
+ X[T],
+ list[T],
+ deque[T],
] + _UNPACKED_TUPLES
for alias in aliases:
with self.subTest(alias=alias):
self.assertEqual(a.__parameters__, (T,))
def test_dir(self):
- dir_of_gen_alias = set(dir(list[int]))
+ ga = list[int]
+ dir_of_gen_alias = set(dir(ga))
self.assertTrue(dir_of_gen_alias.issuperset(dir(list)))
- for generic_alias_property in ("__origin__", "__args__", "__parameters__"):
- self.assertIn(generic_alias_property, dir_of_gen_alias)
+ for generic_alias_property in (
+ "__origin__", "__args__", "__parameters__",
+ "__unpacked__",
+ ):
+ with self.subTest(generic_alias_property=generic_alias_property):
+ self.assertIn(generic_alias_property, dir_of_gen_alias)
+ for blocked in (
+ "__bases__",
+ "__copy__",
+ "__deepcopy__",
+ ):
+ with self.subTest(blocked=blocked):
+ self.assertNotIn(blocked, dir_of_gen_alias)
+
+ for entry in dir_of_gen_alias:
+ with self.subTest(entry=entry):
+ getattr(ga, entry) # must not raise `AttributeError`
def test_weakref(self):
for t in self.generic_types:
static const char* const attr_exceptions[] = {
"__class__",
- "__bases__",
"__origin__",
"__args__",
"__unpacked__",
"__mro_entries__",
"__reduce_ex__", // needed so we don't look up object.__reduce_ex__
"__reduce__",
+ NULL,
+};
+
+static const char* const attr_blocked[] = {
+ "__bases__",
"__copy__",
"__deepcopy__",
NULL,
{
gaobject *alias = (gaobject *)self;
if (PyUnicode_Check(name)) {
+ // When we check blocked attrs, we don't allow to proxy them to `__origin__`.
+ // Otherwise, we can break existing code.
+ for (const char * const *p = attr_blocked; ; p++) {
+ if (*p == NULL) {
+ break;
+ }
+ if (_PyUnicode_EqualToASCIIString(name, *p)) {
+ goto generic_getattr;
+ }
+ }
+
+ // When we see own attrs, it has a priority over `__origin__`'s attr.
for (const char * const *p = attr_exceptions; ; p++) {
if (*p == NULL) {
return PyObject_GetAttr(alias->origin, name);
}
if (_PyUnicode_EqualToASCIIString(name, *p)) {
- break;
+ goto generic_getattr;
}
}
}
+
+generic_getattr:
return PyObject_GenericGetAttr(self, name);
}