From 17fba08b4c2004401d7f41a007773b2944da5659 Mon Sep 17 00:00:00 2001 From: AlexWaygood Date: Mon, 17 Apr 2023 15:37:49 -0600 Subject: [PATCH 1/6] Fix tests on conda builds --- pyproject.toml | 2 +- src/_ann_module.py | 60 +++++++++++++++++++++++++++++++++++ src/_ann_module2.py | 36 +++++++++++++++++++++ src/_ann_module3.py | 18 +++++++++++ src/test_typing_extensions.py | 54 ++++++++++++++++--------------- 5 files changed, 144 insertions(+), 26 deletions(-) create mode 100644 src/_ann_module.py create mode 100644 src/_ann_module2.py create mode 100644 src/_ann_module3.py diff --git a/pyproject.toml b/pyproject.toml index 67d81a17..908fd734 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 = [] diff --git a/src/_ann_module.py b/src/_ann_module.py new file mode 100644 index 00000000..0567d6de --- /dev/null +++ b/src/_ann_module.py @@ -0,0 +1,60 @@ + + +""" +The module for testing variable annotations. +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 diff --git a/src/_ann_module2.py b/src/_ann_module2.py new file mode 100644 index 00000000..76cf5b3a --- /dev/null +++ b/src/_ann_module2.py @@ -0,0 +1,36 @@ +""" +Some correct syntax for variable annotation here. +More examples are in test_grammar and test_parser. +""" + +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() diff --git a/src/_ann_module3.py b/src/_ann_module3.py new file mode 100644 index 00000000..eccd7be2 --- /dev/null +++ b/src/_ann_module3.py @@ -0,0 +1,18 @@ +""" +Correct syntax for variable annotation that should fail at runtime +in a certain manner. More examples are in test_grammar and test_parser. +""" + +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 diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index 0dbc3301..eef7c3fd 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -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 @@ -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. @@ -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), "") + + @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"" + ) def test_instantiation(self): with self.assertRaises(TypeError): @@ -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)}) @@ -974,7 +978,7 @@ 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 @@ -982,8 +986,8 @@ 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()), From b1db9df0661772521b3e65d1883a342e172e773b Mon Sep 17 00:00:00 2001 From: AlexWaygood Date: Mon, 17 Apr 2023 15:39:35 -0600 Subject: [PATCH 2/6] Fix lint --- .flake8 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.flake8 b/.flake8 index 03237510..ec18c675 100644 --- a/.flake8 +++ b/.flake8 @@ -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 From 93a2217d3dbcf301e18cc35927727aec00a3f7f9 Mon Sep 17 00:00:00 2001 From: AlexWaygood Date: Mon, 17 Apr 2023 15:52:28 -0600 Subject: [PATCH 3/6] Improve docstrings --- src/_ann_module.py | 1 + src/_ann_module2.py | 3 ++- src/_ann_module3.py | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/_ann_module.py b/src/_ann_module.py index 0567d6de..212ad736 100644 --- a/src/_ann_module.py +++ b/src/_ann_module.py @@ -2,6 +2,7 @@ """ 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) """ diff --git a/src/_ann_module2.py b/src/_ann_module2.py index 76cf5b3a..e46485a5 100644 --- a/src/_ann_module2.py +++ b/src/_ann_module2.py @@ -1,6 +1,7 @@ """ Some correct syntax for variable annotation here. -More examples are in test_grammar and test_parser. +This file is for testing purposes, +and is vendored from Lib/test/ann_module2.py in CPython. """ from typing import no_type_check, ClassVar diff --git a/src/_ann_module3.py b/src/_ann_module3.py index eccd7be2..111eefa5 100644 --- a/src/_ann_module3.py +++ b/src/_ann_module3.py @@ -1,6 +1,6 @@ """ -Correct syntax for variable annotation that should fail at runtime -in a certain manner. More examples are in test_grammar and test_parser. +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(): From a6351b450d03c51ede67303161f15155cc5ada30 Mon Sep 17 00:00:00 2001 From: AlexWaygood Date: Sun, 23 Apr 2023 00:08:43 -0600 Subject: [PATCH 4/6] no new files --- .flake8 | 2 - pyproject.toml | 2 +- src/_ann_module.py | 61 ------------- src/_ann_module2.py | 37 -------- src/_ann_module3.py | 18 ---- src/test_typing_extensions.py | 157 +++++++++++++++++++++++++++++----- 6 files changed, 138 insertions(+), 139 deletions(-) delete mode 100644 src/_ann_module.py delete mode 100644 src/_ann_module2.py delete mode 100644 src/_ann_module3.py diff --git a/.flake8 b/.flake8 index ec18c675..03237510 100644 --- a/.flake8 +++ b/.flake8 @@ -15,6 +15,4 @@ 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 diff --git a/pyproject.toml b/pyproject.toml index 908fd734..67d81a17 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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", "*/_ann_module*.py"] +include = ["CHANGELOG.md", "README.md", "tox.ini", "*/*test*.py"] exclude = [] diff --git a/src/_ann_module.py b/src/_ann_module.py deleted file mode 100644 index 212ad736..00000000 --- a/src/_ann_module.py +++ /dev/null @@ -1,61 +0,0 @@ - - -""" -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 diff --git a/src/_ann_module2.py b/src/_ann_module2.py deleted file mode 100644 index e46485a5..00000000 --- a/src/_ann_module2.py +++ /dev/null @@ -1,37 +0,0 @@ -""" -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() diff --git a/src/_ann_module3.py b/src/_ann_module3.py deleted file mode 100644 index 111eefa5..00000000 --- a/src/_ann_module3.py +++ /dev/null @@ -1,18 +0,0 @@ -""" -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 diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index eef7c3fd..fad32f19 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -8,10 +8,13 @@ import collections.abc import copy from functools import lru_cache +import importlib import inspect import pickle import subprocess +import tempfile import types +from pathlib import Path from unittest import TestCase, main, skipUnless, skipIf from unittest.mock import patch import typing @@ -22,9 +25,6 @@ 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 @@ -50,6 +50,112 @@ # versions, but not all HAS_FORWARD_MODULE = "module" in inspect.signature(typing._type_check).parameters +ANN_MODULE_SOURCE = '''\ +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 +''' + +ANN_MODULE_2_SOURCE = '''\ +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() +''' + +ANN_MODULE_3_SOURCE = '''\ +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 +''' + class BaseTestCase(TestCase): def assertIsSubclass(self, cls, class_or_tuple, msg=None): @@ -950,24 +1056,35 @@ class AnnotatedMovie(TypedDict): class GetTypeHintTests(BaseTestCase): + @classmethod + def setUpClass(cls): + with tempfile.TemporaryDirectory() as tempdir: + sys.path.append(tempdir) + Path(tempdir, "ann_module.py").write_text(ANN_MODULE_SOURCE) + Path(tempdir, "ann_module2.py").write_text(ANN_MODULE_2_SOURCE) + Path(tempdir, "ann_module3.py").write_text(ANN_MODULE_3_SOURCE) + cls.ann_module = importlib.import_module(f"ann_module") + cls.ann_module2 = importlib.import_module(f"ann_module2") + cls.ann_module3 = importlib.import_module(f"ann_module3") + def test_get_type_hints_modules(self): ann_module_type_hints = {1: 2, 'f': Tuple[int, int], 'x': int, 'y': str} - self.assertEqual(gth(_ann_module), ann_module_type_hints) - self.assertEqual(gth(_ann_module2), {}) - self.assertEqual(gth(_ann_module3), {}) + self.assertEqual(gth(self.ann_module), ann_module_type_hints) + self.assertEqual(gth(self.ann_module2), {}) + self.assertEqual(gth(self.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(self.ann_module.C, self.ann_module.__dict__), + {'y': Optional[self.ann_module.C]}) + self.assertIsInstance(gth(self.ann_module.j_class), dict) + self.assertEqual(gth(self.ann_module.M), {'123': 123, 'o': type}) + self.assertEqual(gth(self.ann_module.D), + {'j': str, 'k': str, 'y': Optional[self.ann_module.C]}) + self.assertEqual(gth(self.ann_module.Y), {'z': int}) + self.assertEqual(gth(self.ann_module.h_class), + {'y': Optional[self.ann_module.C]}) + self.assertEqual(gth(self.ann_module.S), {'x': str, 'y': str}) + self.assertEqual(gth(self.ann_module.foo), {'x': int}) self.assertEqual(gth(NoneAndForward, globals()), {'parent': NoneAndForward, 'meaning': type(None)}) @@ -978,7 +1095,7 @@ 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(self.ann_module2.NTC.meth), {}) class ABase(Generic[T]): def meth(x: int): ... @no_type_check @@ -986,8 +1103,8 @@ 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(self.ann_module2.CV, self.ann_module2.__dict__), + {'var': ClassVar[self.ann_module2.CV]}) self.assertEqual(gth(B, globals()), {'y': int, 'x': ClassVar[Optional[B]], 'b': int}) self.assertEqual(gth(CSub, globals()), From 2d16b8e47351c31cc038d9e665ea8b1f3a590bf6 Mon Sep 17 00:00:00 2001 From: AlexWaygood Date: Sun, 23 Apr 2023 00:10:52 -0600 Subject: [PATCH 5/6] f --- src/test_typing_extensions.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index fad32f19..05f3ac0e 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -1063,9 +1063,9 @@ def setUpClass(cls): Path(tempdir, "ann_module.py").write_text(ANN_MODULE_SOURCE) Path(tempdir, "ann_module2.py").write_text(ANN_MODULE_2_SOURCE) Path(tempdir, "ann_module3.py").write_text(ANN_MODULE_3_SOURCE) - cls.ann_module = importlib.import_module(f"ann_module") - cls.ann_module2 = importlib.import_module(f"ann_module2") - cls.ann_module3 = importlib.import_module(f"ann_module3") + cls.ann_module = importlib.import_module("ann_module") + cls.ann_module2 = importlib.import_module("ann_module2") + cls.ann_module3 = importlib.import_module("ann_module3") def test_get_type_hints_modules(self): ann_module_type_hints = {1: 2, 'f': Tuple[int, int], 'x': int, 'y': str} From 2a39095e3ede7af1ccfda74f1e4cc7493683dba5 Mon Sep 17 00:00:00 2001 From: AlexWaygood Date: Sun, 23 Apr 2023 11:26:24 -0600 Subject: [PATCH 6/6] Side effects are probably bad --- src/test_typing_extensions.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index 05f3ac0e..425355fa 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -1066,6 +1066,13 @@ def setUpClass(cls): cls.ann_module = importlib.import_module("ann_module") cls.ann_module2 = importlib.import_module("ann_module2") cls.ann_module3 = importlib.import_module("ann_module3") + sys.path.pop() + + @classmethod + def tearDownClass(cls): + for modname in "ann_module", "ann_module2", "ann_module3": + delattr(cls, modname) + del sys.modules[modname] def test_get_type_hints_modules(self): ann_module_type_hints = {1: 2, 'f': Tuple[int, int], 'x': int, 'y': str}