[3.10] bpo-44635: Convert None to NoneType in the union type constructor (GH-27136). (GH-27142)

(cherry picked from commit b81cac0560)
This commit is contained in:
Serhiy Storchaka 2021-07-15 10:15:14 +03:00 committed by GitHub
parent 016af14d93
commit 6dec525582
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 9 deletions

View file

@ -612,6 +612,8 @@ class TypesTests(unittest.TestCase):
self.assertEqual(str | int, typing.Union[int, str])
self.assertEqual(int | None, typing.Union[int, None])
self.assertEqual(None | int, typing.Union[int, None])
self.assertEqual(int | type(None), int | None)
self.assertEqual(type(None) | int, None | int)
self.assertEqual(int | str | list, typing.Union[int, str, list])
self.assertEqual(int | (str | list), typing.Union[int, str, list])
self.assertEqual(str | (int | list), typing.Union[int, str, list])
@ -699,6 +701,13 @@ class TypesTests(unittest.TestCase):
assert TV | str == typing.Union[TV, str]
assert str | TV == typing.Union[str, TV]
def test_union_args(self):
self.assertEqual((int | str).__args__, (int, str))
self.assertEqual(((int | str) | list).__args__, (int, str, list))
self.assertEqual((int | (str | list)).__args__, (int, str, list))
self.assertEqual((int | None).__args__, (int, type(None)))
self.assertEqual((int | type(None)).__args__, (int, type(None)))
def test_or_type_operator_with_forward(self):
T = typing.TypeVar('T')
ForwardAfter = T | 'Forward'
@ -744,7 +753,11 @@ class TypesTests(unittest.TestCase):
assert typing.Union[int, bool] | str == typing.Union[int, bool, str]
def test_or_type_repr(self):
assert repr(int | str) == "int | str"
assert repr((int | str) | list) == "int | str | list"
assert repr(int | (str | list)) == "int | str | list"
assert repr(int | None) == "int | None"
assert repr(int | type(None)) == "int | None"
assert repr(int | typing.GenericAlias(list, int)) == "int | list[int]"
def test_or_type_operator_with_genericalias(self):

View file

@ -0,0 +1 @@
Convert ``None`` to ``type(None)`` in the union type constructor.

View file

@ -64,9 +64,6 @@ union_instancecheck(PyObject *self, PyObject *instance)
}
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
PyObject *arg = PyTuple_GET_ITEM(alias->args, iarg);
if (arg == Py_None) {
arg = (PyObject *)&_PyNone_Type;
}
if (PyType_Check(arg)) {
int res = PyObject_IsInstance(instance, arg);
if (res < 0) {
@ -96,9 +93,6 @@ union_subclasscheck(PyObject *self, PyObject *instance)
Py_ssize_t nargs = PyTuple_GET_SIZE(alias->args);
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
PyObject *arg = PyTuple_GET_ITEM(alias->args, iarg);
if (arg == Py_None) {
arg = (PyObject *)&_PyNone_Type;
}
if (PyType_Check(arg)) {
int res = PyObject_IsSubclass(instance, arg);
if (res < 0) {
@ -172,9 +166,6 @@ union_richcompare(PyObject *a, PyObject *b, int op)
Py_ssize_t b_arg_length = PyTuple_GET_SIZE(b_args);
for (Py_ssize_t i = 0; i < b_arg_length; i++) {
PyObject* arg = PyTuple_GET_ITEM(b_args, i);
if (arg == (PyObject *)&_PyNone_Type) {
arg = Py_None;
}
if (PySet_Add(b_set, arg) == -1) {
Py_DECREF(b_args);
goto exit;
@ -236,6 +227,9 @@ flatten_args(PyObject* args)
pos++;
}
} else {
if (arg == Py_None) {
arg = (PyObject *)&_PyNone_Type;
}
Py_INCREF(arg);
PyTuple_SET_ITEM(flattened_args, pos, arg);
pos++;
@ -362,6 +356,10 @@ union_repr_item(_PyUnicodeWriter *writer, PyObject *p)
PyObject *r = NULL;
int err;
if (p == (PyObject *)&_PyNone_Type) {
return _PyUnicodeWriter_WriteASCIIString(writer, "None", 4);
}
if (_PyObject_LookupAttrId(p, &PyId___origin__, &tmp) < 0) {
goto exit;
}