-
Notifications
You must be signed in to change notification settings - Fork 2
Base implementation of PEP 696 #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: pep696
Are you sure you want to change the base?
Changes from 10 commits
0e849c5
2c278ca
fcb20ae
ef4ab4e
8e80dc7
5bddbad
85f3973
1f4b8c4
2ac3116
77ce496
037ac22
a05c2f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -828,6 +828,14 @@ def test_union_parameter_chaining(self): | |
self.assertEqual((list[T] | list[S])[int, T], list[int] | list[T]) | ||
self.assertEqual((list[T] | list[S])[int, int], list[int]) | ||
|
||
def test_union_parameter_default_ordering(self): | ||
T = typing.TypeVar("T") | ||
U = typing.TypeVar("U", default=int) | ||
|
||
self.assertEqual((list[U] | list[T]).__parameters__, (U, T)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't this raise TypeError as the next test asserts? |
||
with self.assertRaises(TypeError): | ||
list[U] | list[T] | ||
|
||
def test_union_parameter_substitution(self): | ||
def eq(actual, expected, typed=True): | ||
self.assertEqual(actual, expected) | ||
|
@@ -996,6 +1004,18 @@ def __eq__(self, other): | |
with self.assertRaises(TypeError): | ||
issubclass(int, type_) | ||
|
||
def test_generic_alias_subclass_with_defaults(self): | ||
T = typing.TypeVar("T") | ||
U = typing.TypeVar("U", default=int) | ||
class MyGeneric: | ||
__class_getitem__ = classmethod(types.GenericAlias) | ||
|
||
class Fine(MyGeneric[T, U]): | ||
... | ||
|
||
with self.assertRaises(TypeError): | ||
class NonDefaultFollows(MyGeneric[U, T]): ... | ||
|
||
def test_or_type_operator_with_bad_module(self): | ||
class BadMeta(type): | ||
__qualname__ = 'TypeVar' | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -214,6 +214,7 @@ _Py_make_parameters(PyObject *args) | |
if (parameters == NULL) | ||
return NULL; | ||
Py_ssize_t iparam = 0; | ||
bool seen_default = false; | ||
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) { | ||
PyObject *t = PyTuple_GET_ITEM(args, iarg); | ||
PyObject *subst; | ||
|
@@ -226,6 +227,25 @@ _Py_make_parameters(PyObject *args) | |
return NULL; | ||
} | ||
if (subst) { | ||
PyObject *default_; | ||
bool does_not_contain = tuple_index(parameters, nargs, t) == -1; | ||
if (does_not_contain) { | ||
if (_PyObject_LookupAttr(t, &_Py_ID(__default__), &default_) < 0) { | ||
Py_DECREF(default_); | ||
|
||
Py_DECREF(subst); | ||
return NULL; | ||
} | ||
if (!Py_IsNone(default_)) { | ||
seen_default = true; | ||
} else if (seen_default) { | ||
return PyErr_Format( | ||
PyExc_TypeError, | ||
"non-default type parameter %R follows default type parameter", | ||
t | ||
); | ||
} | ||
} | ||
|
||
iparam += tuple_add(parameters, iparam, t); | ||
Py_DECREF(subst); | ||
} | ||
|
@@ -248,7 +268,25 @@ _Py_make_parameters(PyObject *args) | |
} | ||
} | ||
for (Py_ssize_t j = 0; j < len2; j++) { | ||
PyObject *default_; | ||
PyObject *t2 = PyTuple_GET_ITEM(subparams, j); | ||
bool does_not_contain = tuple_index(parameters, nargs, t2) == -1; | ||
if (does_not_contain) { | ||
if (_PyObject_LookupAttr(t2, &_Py_ID(__default__), &default_) < 0) { | ||
Py_DECREF(default_); | ||
|
||
Py_DECREF(subst); | ||
return NULL; | ||
} | ||
if (default_ && !Py_IsNone(default_)) { | ||
seen_default = true; | ||
} else if (seen_default) { | ||
return PyErr_Format( | ||
PyExc_TypeError, | ||
"non-default type parameter %R follows default type parameter", | ||
t2 | ||
); | ||
} | ||
} | ||
iparam += tuple_add(parameters, iparam, t2); | ||
} | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.