Skip to content

Commit b81cac0

Browse files
bpo-44635: Convert None to NoneType in the union type constructor (GH-27136)
1 parent 0516299 commit b81cac0

File tree

3 files changed

+21
-9
lines changed

3 files changed

+21
-9
lines changed

Diff for: Lib/test/test_types.py

+13
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,8 @@ def test_or_types_operator(self):
612612
self.assertEqual(str | int, typing.Union[int, str])
613613
self.assertEqual(int | None, typing.Union[int, None])
614614
self.assertEqual(None | int, typing.Union[int, None])
615+
self.assertEqual(int | type(None), int | None)
616+
self.assertEqual(type(None) | int, None | int)
615617
self.assertEqual(int | str | list, typing.Union[int, str, list])
616618
self.assertEqual(int | (str | list), typing.Union[int, str, list])
617619
self.assertEqual(str | (int | list), typing.Union[int, str, list])
@@ -699,6 +701,13 @@ def test_or_type_operator_with_TypeVar(self):
699701
assert TV | str == typing.Union[TV, str]
700702
assert str | TV == typing.Union[str, TV]
701703

704+
def test_union_args(self):
705+
self.assertEqual((int | str).__args__, (int, str))
706+
self.assertEqual(((int | str) | list).__args__, (int, str, list))
707+
self.assertEqual((int | (str | list)).__args__, (int, str, list))
708+
self.assertEqual((int | None).__args__, (int, type(None)))
709+
self.assertEqual((int | type(None)).__args__, (int, type(None)))
710+
702711
def test_union_parameter_chaining(self):
703712
T = typing.TypeVar("T")
704713
S = typing.TypeVar("S")
@@ -754,7 +763,11 @@ def test_or_type_operator_with_SpecialForm(self):
754763
assert typing.Union[int, bool] | str == typing.Union[int, bool, str]
755764

756765
def test_or_type_repr(self):
766+
assert repr(int | str) == "int | str"
767+
assert repr((int | str) | list) == "int | str | list"
768+
assert repr(int | (str | list)) == "int | str | list"
757769
assert repr(int | None) == "int | None"
770+
assert repr(int | type(None)) == "int | None"
758771
assert repr(int | typing.GenericAlias(list, int)) == "int | list[int]"
759772

760773
def test_or_type_operator_with_genericalias(self):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Convert ``None`` to ``type(None)`` in the union type constructor.

Diff for: Objects/unionobject.c

+7-9
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,6 @@ union_instancecheck(PyObject *self, PyObject *instance)
6767
}
6868
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
6969
PyObject *arg = PyTuple_GET_ITEM(alias->args, iarg);
70-
if (arg == Py_None) {
71-
arg = (PyObject *)&_PyNone_Type;
72-
}
7370
if (PyType_Check(arg)) {
7471
int res = PyObject_IsInstance(instance, arg);
7572
if (res < 0) {
@@ -99,9 +96,6 @@ union_subclasscheck(PyObject *self, PyObject *instance)
9996
Py_ssize_t nargs = PyTuple_GET_SIZE(alias->args);
10097
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
10198
PyObject *arg = PyTuple_GET_ITEM(alias->args, iarg);
102-
if (arg == Py_None) {
103-
arg = (PyObject *)&_PyNone_Type;
104-
}
10599
if (PyType_Check(arg)) {
106100
int res = PyObject_IsSubclass(instance, arg);
107101
if (res < 0) {
@@ -175,9 +169,6 @@ union_richcompare(PyObject *a, PyObject *b, int op)
175169
Py_ssize_t b_arg_length = PyTuple_GET_SIZE(b_args);
176170
for (Py_ssize_t i = 0; i < b_arg_length; i++) {
177171
PyObject* arg = PyTuple_GET_ITEM(b_args, i);
178-
if (arg == (PyObject *)&_PyNone_Type) {
179-
arg = Py_None;
180-
}
181172
if (PySet_Add(b_set, arg) == -1) {
182173
Py_DECREF(b_args);
183174
goto exit;
@@ -239,6 +230,9 @@ flatten_args(PyObject* args)
239230
pos++;
240231
}
241232
} else {
233+
if (arg == Py_None) {
234+
arg = (PyObject *)&_PyNone_Type;
235+
}
242236
Py_INCREF(arg);
243237
PyTuple_SET_ITEM(flattened_args, pos, arg);
244238
pos++;
@@ -365,6 +359,10 @@ union_repr_item(_PyUnicodeWriter *writer, PyObject *p)
365359
PyObject *r = NULL;
366360
int err;
367361

362+
if (p == (PyObject *)&_PyNone_Type) {
363+
return _PyUnicodeWriter_WriteASCIIString(writer, "None", 4);
364+
}
365+
368366
if (_PyObject_LookupAttrId(p, &PyId___origin__, &tmp) < 0) {
369367
goto exit;
370368
}

0 commit comments

Comments
 (0)