Reimplement `Literal` on Python <=3.10.0 (#148)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 04f1a3f..3a3f62b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,10 @@
objects will now raise a `TypeError` if one of the `Literal` objects being
compared has a mutable parameter. (Using mutable parameters with `Literal` is
not supported by PEP 586 or by any major static type checkers.)
+- `Literal` is now reimplemented on all Python versions <= 3.10.0. The
+ `typing_extensions` version does not suffer from the bug that was fixed in
+ https://github.com/python/cpython/pull/29334. (The CPython bugfix was
+ backported to CPython 3.10.1 and 3.9.8, but no earlier.)
- Backport [CPython PR 26067](https://github.com/python/cpython/pull/26067)
(originally by Yurii Karabas), ensuring that `isinstance()` calls on
protocols raise `TypeError` when the protocol is not decorated with
diff --git a/README.md b/README.md
index 46678af..59d5d3d 100644
--- a/README.md
+++ b/README.md
@@ -143,9 +143,10 @@
- `TypeVar` gains two additional parameters, `default=` and `infer_variance=`,
in the draft PEPs [695](https://peps.python.org/pep-0695/) and [696](https://peps.python.org/pep-0696/), which are being considered for inclusion
in Python 3.12.
-- `Literal` does not flatten or deduplicate parameters on Python <3.9.1. The
- `typing_extensions` version flattens and deduplicates parameters on all
- Python versions.
+- `Literal` does not flatten or deduplicate parameters on Python <3.9.1, and a
+ caching bug was fixed in 3.10.1/3.9.8. The `typing_extensions` version
+ flattens and deduplicates parameters on all Python versions, and the caching
+ bug is also fixed on all versions.
There are a few types whose interface was modified between different
versions of typing. For example, `typing.Sequence` was modified to
diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py
index 0dbc330..9c89cfc 100644
--- a/src/test_typing_extensions.py
+++ b/src/test_typing_extensions.py
@@ -615,8 +615,8 @@
List[Literal[("foo", "bar", "baz")]]
def test_repr(self):
- # we backport various bugfixes that were added in 3.9.1
- if sys.version_info >= (3, 9, 1):
+ # we backport various bugfixes that were added in 3.10.1 and earlier
+ if sys.version_info >= (3, 10, 1):
mod_name = 'typing'
else:
mod_name = 'typing_extensions'
@@ -662,6 +662,8 @@
self.assertNotEqual(Literal[True], Literal[1])
self.assertNotEqual(Literal[1], Literal[2])
self.assertNotEqual(Literal[1, True], Literal[1])
+ self.assertNotEqual(Literal[1, True], Literal[1, 1])
+ self.assertNotEqual(Literal[1, 2], Literal[True, 2])
self.assertEqual(Literal[1], Literal[1])
self.assertEqual(Literal[1, 2], Literal[2, 1])
self.assertEqual(Literal[1, 2, 3], Literal[1, 2, 3, 3])
@@ -3601,10 +3603,10 @@
'get_type_hints',
'is_typeddict',
}
- if sys.version_info < (3, 9, 1):
- exclude |= {"Literal"}
if sys.version_info < (3, 10):
exclude |= {'get_args', 'get_origin'}
+ if sys.version_info < (3, 10, 1):
+ exclude |= {"Literal"}
if sys.version_info < (3, 11):
exclude |= {'final', 'NamedTuple', 'Any'}
if sys.version_info < (3, 12):
diff --git a/src/typing_extensions.py b/src/typing_extensions.py
index cd02b3f..b6b6bd4 100644
--- a/src/typing_extensions.py
+++ b/src/typing_extensions.py
@@ -261,8 +261,8 @@
return typing.TypeVar(name)
-# Various Literal bugs were fixed in 3.9.1, but not backported earlier than that
-if sys.version_info >= (3, 9, 1):
+# A Literal bug was fixed in 3.11.0, 3.10.1 and 3.9.8
+if sys.version_info >= (3, 10, 1):
Literal = typing.Literal
else:
def _flatten_literal_params(parameters):