Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ exclude =
# tests have more relaxed formatting rules
# and its own specific config in .flake8-tests
src/test_typing_extensions.py,
# these are just data files
src/_ann_module*.py,
noqa_require_code = true
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,5 @@ name = "Guido van Rossum, Jukka Lehtosalo, Łukasz Langa, Michael Lee"
email = "levkivskyi@gmail.com"

[tool.flit.sdist]
include = ["CHANGELOG.md", "README.md", "tox.ini", "*/*test*.py"]
include = ["CHANGELOG.md", "README.md", "tox.ini", "*/*test*.py", "*/_ann_module*.py"]
exclude = []
61 changes: 61 additions & 0 deletions src/_ann_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@


"""
The module for testing variable annotations.
Vendored from Lib/test/ann_module.py in CPython.
Empty lines above are for good reason (testing for correct line numbers)
"""

from typing import Optional
from functools import wraps

__annotations__[1] = 2

class C:

x = 5; y: Optional['C'] = None

from typing import Tuple
x: int = 5; y: str = x; f: Tuple[int, int]

class M(type):

__annotations__['123'] = 123
o: type = object

(pars): bool = True

class D(C):
j: str = 'hi'; k: str= 'bye'

from types import new_class
h_class = new_class('H', (C,))
j_class = new_class('J')

class F():
z: int = 5
def __init__(self, x):
pass

class Y(F):
def __init__(self):
super(F, self).__init__(123)

class Meta(type):
def __new__(meta, name, bases, namespace):
return super().__new__(meta, name, bases, namespace)

class S(metaclass = Meta):
x: str = 'something'
y: str = 'something else'

def foo(x: int = 10):
def bar(y: List[str]):
x: str = 'yes'
bar()

def dec(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
37 changes: 37 additions & 0 deletions src/_ann_module2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
Some correct syntax for variable annotation here.
This file is for testing purposes,
and is vendored from Lib/test/ann_module2.py in CPython.
"""

from typing import no_type_check, ClassVar

i: int = 1
j: int
x: float = i/10

def f():
class C: ...
return C()

f().new_attr: object = object()

class C:
def __init__(self, x: int) -> None:
self.x = x

c = C(5)
c.new_attr: int = 10

__annotations__ = {}


@no_type_check
class NTC:
def meth(self, param: complex) -> None:
...

class CV:
var: ClassVar['CV']

CV.var = CV()
18 changes: 18 additions & 0 deletions src/_ann_module3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""
Correct syntax for variable annotation that should fail at runtime in a certain manner.
This file is for testing purposes, and is vendored from Lib/test/ann_module3.py in CPython.
"""

def f_bad_ann():
__annotations__[1] = 2

class C_OK:
def __init__(self, x: int) -> None:
self.x: no_such_name = x # This one is OK as proposed by Guido

class D_bad_ann:
def __init__(self, x: int) -> None:
sfel.y: int = 0

def g_bad_ann():
no_such_name.attr: int = 0
54 changes: 29 additions & 25 deletions src/test_typing_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@
import types
from unittest import TestCase, main, skipUnless, skipIf
from unittest.mock import patch
from test import ann_module, ann_module2, ann_module3
import typing
from typing import TypeVar, Optional, Union, AnyStr
from typing import T, KT, VT # Not in __all__.
from typing import Tuple, List, Dict, Iterable, Iterator, Callable
from typing import Generic
from typing import no_type_check
import warnings

import _ann_module
import _ann_module2
import _ann_module3
import typing_extensions
from typing_extensions import NoReturn, Any, ClassVar, Final, IntVar, Literal, Type, NewType, TypedDict, Self
from typing_extensions import TypeAlias, ParamSpec, Concatenate, ParamSpecArgs, ParamSpecKwargs, TypeGuard
Expand All @@ -32,7 +36,6 @@
from typing_extensions import NamedTuple
from typing_extensions import override, deprecated, Buffer
from _typed_dict_test_helper import Foo, FooGeneric
import warnings

# Flags used to mark tests that only apply after a specific
# version of the typing module.
Expand Down Expand Up @@ -384,8 +387,13 @@ def test_repr(self):
else:
mod_name = 'typing_extensions'
self.assertEqual(repr(Any), f"{mod_name}.Any")
if sys.version_info < (3, 11): # skip for now on 3.11+ see python/cpython#95987
self.assertEqual(repr(self.SubclassesAny), "<class 'test_typing_extensions.AnyTests.SubclassesAny'>")

@skipIf(sys.version_info[:3] == (3, 11, 0), "A bug was fixed in 3.11.1")
def test_repr_on_Any_subclass(self):
self.assertEqual(
repr(self.SubclassesAny),
f"<class '{self.SubclassesAny.__module__}.AnyTests.SubclassesAny'>"
)

def test_instantiation(self):
with self.assertRaises(TypeError):
Expand Down Expand Up @@ -944,26 +952,22 @@ class AnnotatedMovie(TypedDict):
class GetTypeHintTests(BaseTestCase):
def test_get_type_hints_modules(self):
ann_module_type_hints = {1: 2, 'f': Tuple[int, int], 'x': int, 'y': str}
if (TYPING_3_11_0
or (TYPING_3_10_0 and sys.version_info.releaselevel in {'candidate', 'final'})):
# More tests were added in 3.10rc1.
ann_module_type_hints['u'] = int | float
self.assertEqual(gth(ann_module), ann_module_type_hints)
self.assertEqual(gth(ann_module2), {})
self.assertEqual(gth(ann_module3), {})
self.assertEqual(gth(_ann_module), ann_module_type_hints)
self.assertEqual(gth(_ann_module2), {})
self.assertEqual(gth(_ann_module3), {})

def test_get_type_hints_classes(self):
self.assertEqual(gth(ann_module.C, ann_module.__dict__),
{'y': Optional[ann_module.C]})
self.assertIsInstance(gth(ann_module.j_class), dict)
self.assertEqual(gth(ann_module.M), {'123': 123, 'o': type})
self.assertEqual(gth(ann_module.D),
{'j': str, 'k': str, 'y': Optional[ann_module.C]})
self.assertEqual(gth(ann_module.Y), {'z': int})
self.assertEqual(gth(ann_module.h_class),
{'y': Optional[ann_module.C]})
self.assertEqual(gth(ann_module.S), {'x': str, 'y': str})
self.assertEqual(gth(ann_module.foo), {'x': int})
self.assertEqual(gth(_ann_module.C, _ann_module.__dict__),
{'y': Optional[_ann_module.C]})
self.assertIsInstance(gth(_ann_module.j_class), dict)
self.assertEqual(gth(_ann_module.M), {'123': 123, 'o': type})
self.assertEqual(gth(_ann_module.D),
{'j': str, 'k': str, 'y': Optional[_ann_module.C]})
self.assertEqual(gth(_ann_module.Y), {'z': int})
self.assertEqual(gth(_ann_module.h_class),
{'y': Optional[_ann_module.C]})
self.assertEqual(gth(_ann_module.S), {'x': str, 'y': str})
self.assertEqual(gth(_ann_module.foo), {'x': int})
self.assertEqual(gth(NoneAndForward, globals()),
{'parent': NoneAndForward, 'meaning': type(None)})

Expand All @@ -974,16 +978,16 @@ class Inn:
def __init__(self, x: 'not a type'): ...
self.assertTrue(NoTpCheck.__no_type_check__)
self.assertTrue(NoTpCheck.Inn.__init__.__no_type_check__)
self.assertEqual(gth(ann_module2.NTC.meth), {})
self.assertEqual(gth(_ann_module2.NTC.meth), {})
class ABase(Generic[T]):
def meth(x: int): ...
@no_type_check
class Der(ABase): ...
self.assertEqual(gth(ABase.meth), {'x': int})

def test_get_type_hints_ClassVar(self):
self.assertEqual(gth(ann_module2.CV, ann_module2.__dict__),
{'var': ClassVar[ann_module2.CV]})
self.assertEqual(gth(_ann_module2.CV, _ann_module2.__dict__),
{'var': ClassVar[_ann_module2.CV]})
self.assertEqual(gth(B, globals()),
{'y': int, 'x': ClassVar[Optional[B]], 'b': int})
self.assertEqual(gth(CSub, globals()),
Expand Down