]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-140348: Fix using | on unusual objects plus Unions (#140383)
authorJelle Zijlstra <jelle.zijlstra@gmail.com>
Mon, 3 Nov 2025 14:50:37 +0000 (06:50 -0800)
committerGitHub <noreply@github.com>
Mon, 3 Nov 2025 14:50:37 +0000 (06:50 -0800)
Lib/test/test_typing.py
Misc/NEWS.d/next/Library/2025-10-20-12-33-49.gh-issue-140348.SAKnQZ.rst [new file with mode: 0644]
Objects/unionobject.c

index 4076004bc13c85f42e3366516e925d8ae36a9835..e896df518447c57c5f5b70444258708e1114c760 100644 (file)
@@ -2283,6 +2283,15 @@ class UnionTests(BaseTestCase):
         self.assertEqual(Union[Literal[1], Literal[Ints.B], Literal[True]].__args__,
                          (Literal[1], Literal[Ints.B], Literal[True]))
 
+    def test_allow_non_types_in_or(self):
+        # gh-140348: Test that using | with a Union object allows things that are
+        # not allowed by is_unionable().
+        U1 = Union[int, str]
+        self.assertEqual(U1 | float, Union[int, str, float])
+        self.assertEqual(U1 | "float", Union[int, str, "float"])
+        self.assertEqual(float | U1, Union[float, int, str])
+        self.assertEqual("float" | U1, Union["float", int, str])
+
 
 class TupleTests(BaseTestCase):
 
diff --git a/Misc/NEWS.d/next/Library/2025-10-20-12-33-49.gh-issue-140348.SAKnQZ.rst b/Misc/NEWS.d/next/Library/2025-10-20-12-33-49.gh-issue-140348.SAKnQZ.rst
new file mode 100644 (file)
index 0000000..16d5b2a
--- /dev/null
@@ -0,0 +1,3 @@
+Fix regression in Python 3.14.0 where using the ``|`` operator on a
+:class:`typing.Union` object combined with an object that is not a type
+would raise an error.
index c4ece0fe09f01854bc5494568203179f4061347c..a47d6193d7088977907c014bb28212ab08f31ff8 100644 (file)
@@ -393,8 +393,23 @@ static PyGetSetDef union_properties[] = {
     {0}
 };
 
+static PyObject *
+union_nb_or(PyObject *a, PyObject *b)
+{
+    unionbuilder ub;
+    if (!unionbuilder_init(&ub, true)) {
+        return NULL;
+    }
+    if (!unionbuilder_add_single(&ub, a) ||
+        !unionbuilder_add_single(&ub, b)) {
+        unionbuilder_finalize(&ub);
+        return NULL;
+    }
+    return make_union(&ub);
+}
+
 static PyNumberMethods union_as_number = {
-        .nb_or = _Py_union_type_or, // Add __or__ function
+        .nb_or = union_nb_or, // Add __or__ function
 };
 
 static const char* const cls_attrs[] = {