mirror of https://github.com/python/cpython.git
bpo-44653: Support typing types in parameter substitution in the union type. (GH-27247) (#27296)
(cherry picked from commit 2e3744d50b
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
9608719e12
commit
21db59fc75
|
@ -772,6 +772,36 @@ 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_substitution(self):
|
||||
def eq(actual, expected):
|
||||
self.assertEqual(actual, expected)
|
||||
self.assertIs(type(actual), type(expected))
|
||||
|
||||
T = typing.TypeVar('T')
|
||||
S = typing.TypeVar('S')
|
||||
NT = typing.NewType('NT', str)
|
||||
x = int | T | bytes
|
||||
|
||||
eq(x[str], int | str | bytes)
|
||||
eq(x[list[int]], int | list[int] | bytes)
|
||||
eq(x[typing.List], int | typing.List | bytes)
|
||||
eq(x[typing.List[int]], int | typing.List[int] | bytes)
|
||||
eq(x[typing.Hashable], int | typing.Hashable | bytes)
|
||||
eq(x[collections.abc.Hashable],
|
||||
int | collections.abc.Hashable | bytes)
|
||||
eq(x[typing.Callable[[int], str]],
|
||||
int | typing.Callable[[int], str] | bytes)
|
||||
eq(x[collections.abc.Callable[[int], str]],
|
||||
int | collections.abc.Callable[[int], str] | bytes)
|
||||
eq(x[typing.Tuple[int, str]], int | typing.Tuple[int, str] | bytes)
|
||||
eq(x[typing.Literal['none']], int | typing.Literal['none'] | bytes)
|
||||
eq(x[str | list], int | str | list | bytes)
|
||||
eq(x[typing.Union[str, list]], typing.Union[int, str, list, bytes])
|
||||
eq(x[str | int], int | str | bytes)
|
||||
eq(x[typing.Union[str, int]], typing.Union[int, str, bytes])
|
||||
eq(x[NT], int | NT | bytes)
|
||||
eq(x[S], int | S | bytes)
|
||||
|
||||
def test_union_parameter_substitution_errors(self):
|
||||
T = typing.TypeVar("T")
|
||||
x = int | T
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Support :mod:`typing` types in parameter substitution in the union type.
|
|
@ -446,23 +446,22 @@ union_getitem(PyObject *self, PyObject *item)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Check arguments are unionable.
|
||||
PyObject *res;
|
||||
Py_ssize_t nargs = PyTuple_GET_SIZE(newargs);
|
||||
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
|
||||
PyObject *arg = PyTuple_GET_ITEM(newargs, iarg);
|
||||
int is_arg_unionable = is_unionable(arg);
|
||||
if (is_arg_unionable <= 0) {
|
||||
Py_DECREF(newargs);
|
||||
if (is_arg_unionable == 0) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"Each union argument must be a type, got %.100R", arg);
|
||||
if (nargs == 0) {
|
||||
res = make_union(newargs);
|
||||
}
|
||||
else {
|
||||
res = PyTuple_GET_ITEM(newargs, 0);
|
||||
Py_INCREF(res);
|
||||
for (Py_ssize_t iarg = 1; iarg < nargs; iarg++) {
|
||||
PyObject *arg = PyTuple_GET_ITEM(newargs, iarg);
|
||||
Py_SETREF(res, PyNumber_Or(res, arg));
|
||||
if (res == NULL) {
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *res = make_union(newargs);
|
||||
|
||||
Py_DECREF(newargs);
|
||||
return res;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue