]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.15] gh-153896: Deduplicate unhashable arguments in `typing.Literal` (GH-153914...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Sun, 19 Jul 2026 08:29:23 +0000 (10:29 +0200)
committerGitHub <noreply@github.com>
Sun, 19 Jul 2026 08:29:23 +0000 (08:29 +0000)
gh-153896: Deduplicate unhashable arguments in `typing.Literal` (GH-153914)
(cherry picked from commit a53b5b126749133e50692fe0c3729f5580ee8500)

Co-authored-by: Massimiliano Bruni <massimiliano.bruni@icloud.com>
Co-authored-by: Tomas R. <tomas.roun8@gmail.com>
Lib/test/test_typing.py
Lib/typing.py
Misc/NEWS.d/next/Library/2026-07-18-10-52-10.gh-issue-153896.87oevp.rst [new file with mode: 0644]

index 0c57c83491042dfcb859c25e00f5dcd68f10ae36..986b41b18a2acc132ce5e152a485b63792170668 100644 (file)
@@ -2796,8 +2796,14 @@ class LiteralTests(BaseTestCase):
         self.assertEqual(Literal[1, 2, 3].__args__, (1, 2, 3))
         self.assertEqual(Literal[1, 2, 3, 3].__args__, (1, 2, 3))
         self.assertEqual(Literal[1, Literal[2], Literal[3, 4]].__args__, (1, 2, 3, 4))
-        # Mutable arguments will not be deduplicated
-        self.assertEqual(Literal[[], []].__args__, ([], []))
+        # Unhashable arguments will be deduplicated too
+        self.assertEqual(Literal[[], []].__args__, ([],))
+        self.assertEqual(Literal[{"a": 1}, {"a": 1}].__args__, ({"a": 1},))
+        self.assertEqual(
+            Literal[1, {'a': 'b'}, 2, {'a': 'b'}, 3].__args__,
+            (1, {'a': 'b'}, 2, 3),
+        )
+        self.assertEqual(Literal[{1}, {1}, {2}, {2}].__args__, ({1}, {2}))
 
     def test_flatten(self):
         l1 = Literal[Literal[1], Literal[2], Literal[3]]
index 8b17cbbae2f6ec6283dcd2ac926a2ea680f14818..5b764419d8afaa79d0745b99b4493af3dddcccc3 100644 (file)
@@ -788,13 +788,16 @@ def Literal(self, *parameters):
     # There is no '_type_check' call because arguments to Literal[...] are
     # values, not types.
     parameters = _flatten_literal_params(parameters)
+    value_and_type_parameters = list(_value_and_type_iter(parameters))
+    deduplicated_parameters = tuple(
+        p
+        for p, _ in _deduplicate(
+            value_and_type_parameters,
+            unhashable_fallback=True,
+        )
+    )
 
-    try:
-        parameters = tuple(p for p, _ in _deduplicate(list(_value_and_type_iter(parameters))))
-    except TypeError:  # unhashable parameters
-        pass
-
-    return _LiteralGenericAlias(self, parameters)
+    return _LiteralGenericAlias(self, deduplicated_parameters)
 
 
 @_SpecialForm
diff --git a/Misc/NEWS.d/next/Library/2026-07-18-10-52-10.gh-issue-153896.87oevp.rst b/Misc/NEWS.d/next/Library/2026-07-18-10-52-10.gh-issue-153896.87oevp.rst
new file mode 100644 (file)
index 0000000..217a3d3
--- /dev/null
@@ -0,0 +1 @@
+Deduplicate unhashable args in :data:`typing.Literal`.