Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ jobs:
# For available versions, see:
# https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json
python-version:
- "3.7"
- "3.7.1"
- "3.8"
- "3.8.0"
- "3.9"
Expand All @@ -53,7 +51,6 @@ jobs:
- "3.11"
- "3.11.0"
- "3.12"
- "pypy3.7"
- "pypy3.8"
- "pypy3.9"
- "pypy3.10"
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Release 4.8.0 (???)

- Drop support for Python 3.7 (including PyPy-3.7). Patch by Alex Waygood.

# Release 4.7.1 (July 2, 2023)

- Fix support for `TypedDict`, `NamedTuple` and `is_protocol` on PyPy-3.7 and
Expand Down
2 changes: 0 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ standard library, so that users can experiment with them before they are added t
standard library. Such features should already be specified in a PEP or merged into
CPython's `main` branch.

`typing_extensions` supports Python versions 3.7 and up.

# Versioning scheme

Starting with version 4.0.0, `typing_extensions` uses
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ Therefore, it's safe to depend
on `typing_extensions` like this: `typing_extensions >=x.y, <(x+1)`,
where `x.y` is the first version that includes all features you need.

`typing_extensions` supports Python versions 3.7 and higher.

## Included items

See [the documentation](https://typing-extensions.readthedocs.io/en/latest/#) for a
Expand Down
2 changes: 1 addition & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ Example usage::
Python version support
----------------------

``typing_extensions`` currently supports Python versions 3.7 and higher. In the future,
``typing_extensions`` currently supports Python versions 3.8 and higher. In the future,
support for older Python versions will be dropped some time after that version
reaches end of life.

Expand Down
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ build-backend = "flit_core.buildapi"
[project]
name = "typing_extensions"
version = "4.7.1"
description = "Backported and Experimental Type Hints for Python 3.7+"
description = "Backported and Experimental Type Hints for Python 3.8+"
readme = "README.md"
requires-python = ">=3.7"
requires-python = ">=3.8"
license = { file = "LICENSE" }
keywords = [
"annotations",
Expand All @@ -34,7 +34,6 @@ classifiers = [
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
Expand Down
72 changes: 10 additions & 62 deletions src/test_typing_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@

# Flags used to mark tests that only apply after a specific
# version of the typing module.
TYPING_3_8_0 = sys.version_info[:3] >= (3, 8, 0)
TYPING_3_9_0 = sys.version_info[:3] >= (3, 9, 0)
TYPING_3_10_0 = sys.version_info[:3] >= (3, 10, 0)

Expand All @@ -52,10 +51,6 @@
# 3.12 changes the representation of Unpack[] (PEP 692)
TYPING_3_12_0 = sys.version_info[:3] >= (3, 12, 0)

only_with_typing_Protocol = skipUnless(
hasattr(typing, "Protocol"), "Only relevant when typing.Protocol exists"
)

# https://github.com/python/cpython/pull/27017 was backported into some 3.9 and 3.10
# versions, but not all
HAS_FORWARD_MODULE = "module" in inspect.signature(typing._type_check).parameters
Expand Down Expand Up @@ -246,13 +241,7 @@ def some(arg: NoReturn) -> NoReturn: ...
def some_str(arg: 'NoReturn') -> 'typing.NoReturn': ...

expected = {'arg': NoReturn, 'return': NoReturn}
targets = [some]

# On 3.7.0 and 3.7.1, https://github.com/python/cpython/pull/10772
# wasn't applied yet and NoReturn fails _type_check.
if not ((3, 7, 0) <= sys.version_info < (3, 7, 2)):
targets.append(some_str)
for target in targets:
for target in some, some_str:
with self.subTest(target=target):
self.assertEqual(gth(target), expected)

Expand Down Expand Up @@ -595,15 +584,11 @@ def test_basics(self):
Final[int][str]

def test_repr(self):
if hasattr(typing, 'Final') and sys.version_info[:2] >= (3, 7):
mod_name = 'typing'
else:
mod_name = 'typing_extensions'
self.assertEqual(repr(Final), mod_name + '.Final')
self.assertEqual(repr(Final), 'typing.Final')
cv = Final[int]
self.assertEqual(repr(cv), mod_name + '.Final[int]')
self.assertEqual(repr(cv), 'typing.Final[int]')
cv = Final[Employee]
self.assertEqual(repr(cv), mod_name + f'.Final[{__name__}.Employee]')
self.assertEqual(repr(cv), f'typing.Final[{__name__}.Employee]')

def test_cannot_subclass(self):
with self.assertRaises(TypeError):
Expand Down Expand Up @@ -1771,7 +1756,6 @@ class E(C, BP): pass
self.assertNotIsInstance(D(), E)
self.assertNotIsInstance(E(), D)

@only_with_typing_Protocol
def test_runtimecheckable_on_typing_dot_Protocol(self):
@runtime_checkable
class Foo(typing.Protocol):
Expand All @@ -1784,7 +1768,6 @@ def __init__(self):
self.assertIsInstance(Bar(), Foo)
self.assertNotIsInstance(object(), Foo)

@only_with_typing_Protocol
def test_typing_dot_runtimecheckable_on_Protocol(self):
@typing.runtime_checkable
class Foo(Protocol):
Expand All @@ -1797,7 +1780,6 @@ def __init__(self):
self.assertIsInstance(Bar(), Foo)
self.assertNotIsInstance(object(), Foo)

@only_with_typing_Protocol
def test_typing_Protocol_and_extensions_Protocol_can_mix(self):
class TypingProto(typing.Protocol):
x: int
Expand Down Expand Up @@ -3173,7 +3155,6 @@ def c(self) -> int: return 5
with self.assertRaisesRegex(TypeError, "not a Protocol"):
get_protocol_members(ConcreteInherit())

@only_with_typing_Protocol
def test_get_protocol_members_typing(self):
with self.assertRaisesRegex(TypeError, "not a Protocol"):
get_protocol_members(typing.Protocol)
Expand Down Expand Up @@ -3222,7 +3203,6 @@ def test_is_protocol(self):
# Protocol is not itself a protocol
self.assertFalse(is_protocol(Protocol))

@only_with_typing_Protocol
def test_is_protocol_with_typing(self):
self.assertFalse(is_protocol(typing.Protocol))

Expand Down Expand Up @@ -3681,7 +3661,6 @@ class NewGeneric[T](TypedDict):
if hasattr(typing, "TypedDict"):
self.assertIs(is_typeddict(typing.TypedDict), False)

@skipUnless(TYPING_3_8_0, "Python 3.8+ required")
def test_is_typeddict_against_typeddict_from_typing(self):
Point = typing.TypedDict('Point', {'x': int, 'y': int})

Expand Down Expand Up @@ -3844,7 +3823,7 @@ class WithImplicitAny(B):
def test_non_generic_subscript(self):
# For backward compatibility, subscription works
# on arbitrary TypedDict types.
# (But we don't attempt to backport this misfeature onto 3.7 and 3.8.)
# (But we don't attempt to backport this misfeature onto 3.8.)
class TD(TypedDict):
a: T
A = TD[int]
Expand Down Expand Up @@ -4034,17 +4013,8 @@ class C:
classvar: Annotated[ClassVar[int], "a decoration"] = 4
const: Annotated[Final[int], "Const"] = 4

if sys.version_info[:2] >= (3, 7):
self.assertEqual(get_type_hints(C, globals())["classvar"], ClassVar[int])
self.assertEqual(get_type_hints(C, globals())["const"], Final[int])
else:
self.assertEqual(
get_type_hints(C, globals())["classvar"],
Annotated[ClassVar[int], "a decoration"]
)
self.assertEqual(
get_type_hints(C, globals())["const"], Annotated[Final[int], "Const"]
)
self.assertEqual(get_type_hints(C, globals())["classvar"], ClassVar[int])
self.assertEqual(get_type_hints(C, globals())["const"], Final[int])

def test_cannot_subclass(self):
with self.assertRaisesRegex(TypeError, "Cannot subclass .*Annotated"):
Expand Down Expand Up @@ -5069,11 +5039,8 @@ def test_typing_extensions_defers_when_possible(self):
'dataclass_transform',
'overload',
'ParamSpec',
'Text',
'TypeVar',
'TypeVarTuple',
'TYPE_CHECKING',
'Final',
'get_type_hints',
}
if sys.version_info < (3, 10):
Expand Down Expand Up @@ -5189,13 +5156,6 @@ class NonDefaultAfterDefault(NamedTuple):
x: int = 3
y: int

@skipUnless(
(
TYPING_3_8_0
or hasattr(CoolEmployeeWithDefault, '_field_defaults')
),
'"_field_defaults" attribute was added in a micro version of 3.7'
)
def test_field_defaults(self):
self.assertEqual(CoolEmployeeWithDefault._field_defaults, dict(cool=0))

Expand Down Expand Up @@ -5296,7 +5256,7 @@ class Group(NamedTuple):
self.assertEqual(a, (1, [2]))

@skipIf(TYPING_3_9_0, "Test isn't relevant to 3.9+")
def test_non_generic_subscript_error_message_py38_minus(self):
def test_non_generic_subscript_error_message_py38(self):
class Group(NamedTuple):
key: T
group: List[T]
Expand Down Expand Up @@ -5389,10 +5349,7 @@ class CNT(NamedTuple):
self.assertEqual(struct._fields, ())
self.assertEqual(struct.__annotations__, {})
self.assertIsInstance(struct(), struct)
# Attribute was added in a micro version of 3.7
# and is tested more fully elsewhere
if hasattr(struct, "_field_defaults"):
self.assertEqual(struct._field_defaults, {})
self.assertEqual(struct._field_defaults, {})

def test_namedtuple_errors(self):
with self.assertRaises(TypeError):
Expand Down Expand Up @@ -5429,15 +5386,6 @@ def test_copy_and_pickle(self):
def test_docstring(self):
self.assertIsInstance(NamedTuple.__doc__, str)

@skipUnless(TYPING_3_8_0, "NamedTuple had a bad signature on <=3.7")
def test_signature_is_same_as_typing_NamedTuple(self):
self.assertEqual(inspect.signature(NamedTuple), inspect.signature(typing.NamedTuple))
Comment on lines -5432 to -5434
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I deleted this test, as it no longer makes sense for us to have the same signature as typing.NamedTuple on <3.13, following #240


@skipIf(TYPING_3_8_0, "tests are only relevant to <=3.7")
def test_signature_on_37(self):
self.assertIsInstance(inspect.signature(NamedTuple), inspect.Signature)
self.assertFalse(hasattr(NamedTuple, "__text_signature__"))

@skipUnless(TYPING_3_9_0, "NamedTuple was a class on 3.8 and lower")
def test_same_as_typing_NamedTuple_39_plus(self):
self.assertEqual(
Expand Down Expand Up @@ -5592,7 +5540,7 @@ def test_bound_errors(self):
r"Bound must be a type\. Got \(1, 2\)\."):
TypeVar('X', bound=(1, 2))

# Technically we could run it on later versions of 3.7 and 3.8,
# Technically we could run it on later versions of 3.8,
# but that's not worth the effort.
@skipUnless(TYPING_3_9_0, "Fix was not backported")
def test_missing__name__(self):
Expand Down
Loading