Skip to content

Commit b57805e

Browse files
committed
Add miscellaneous tests
1 parent 4bd67c5 commit b57805e

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

src/test_typing_extensions.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2254,6 +2254,52 @@ def test_asynccontextmanager_type_params(self):
22542254
cm2 = typing_extensions.AsyncContextManager[int, None]
22552255
self.assertEqual(get_args(cm2), (int, NoneType))
22562256

2257+
def test_setattr(self):
2258+
if hasattr(typing_extensions, "_SpecialGenericAlias"):
2259+
mod = typing_extensions
2260+
else:
2261+
mod = typing
2262+
class Foo:
2263+
_name = "Foo"
2264+
Alias = mod._SpecialGenericAlias(Foo, 1)
2265+
2266+
# Attribute assignment on generic alias sets attribute on origin
2267+
Alias.foo = 1
2268+
self.assertEqual(Alias.foo, 1)
2269+
self.assertEqual(Foo.foo, 1)
2270+
2271+
# Except for dunders...
2272+
Alias.__dunder__ = 2
2273+
self.assertEqual(Alias.__dunder__, 2)
2274+
with self.assertRaises(AttributeError):
2275+
Foo.__dunder__
2276+
2277+
# ...and certain known attributes
2278+
Alias._name = "NewName"
2279+
self.assertEqual(Alias._name, "NewName")
2280+
self.assertEqual(Foo._name, "Foo")
2281+
2282+
def test_invalid_specialization(self):
2283+
if hasattr(typing_extensions, "_SpecialGenericAlias"):
2284+
mod = typing_extensions
2285+
else:
2286+
mod = typing
2287+
class Foo: ...
2288+
Alias = mod._SpecialGenericAlias(Foo, 2)
2289+
2290+
msg = re.escape("Too few arguments for typing.Foo; actual 1, expected 2")
2291+
with self.assertRaisesRegex(TypeError, msg):
2292+
Alias[int]
2293+
2294+
msg = re.escape("Too many arguments for typing.Foo; actual 3, expected 2")
2295+
with self.assertRaisesRegex(TypeError, msg):
2296+
Alias[int, int, int]
2297+
2298+
Alias0 = mod._SpecialGenericAlias(Foo, 0)
2299+
msg = re.escape("typing.Foo is not a generic class")
2300+
with self.assertRaisesRegex(TypeError, msg):
2301+
Alias0[int]
2302+
22572303

22582304
class TypeTests(BaseTestCase):
22592305

@@ -2379,6 +2425,16 @@ def test_error_message_when_subclassing(self):
23792425
class ProUserId(UserId):
23802426
...
23812427

2428+
def test_module_with_incomplete_sys(self):
2429+
def does_not_exist(*args):
2430+
raise AttributeError
2431+
with (
2432+
patch("sys._getframemodulename", does_not_exist, create=True),
2433+
patch("sys._getframe", does_not_exist, create=True),
2434+
):
2435+
X = NewType("X", int)
2436+
self.assertEqual(X.__module__, None)
2437+
23822438

23832439
class Coordinate(Protocol):
23842440
x: int
@@ -5499,6 +5555,25 @@ def foobar(x: List['X']): ...
54995555
get_type_hints(foobar, globals(), locals(), include_extras=True),
55005556
{'x': List[Annotated[int, (1, 10)]]}
55015557
)
5558+
def foobar2(x: list['X']): ...
5559+
if sys.version_info >= (3, 11):
5560+
self.assertEqual(
5561+
get_type_hints(foobar2, globals(), locals()),
5562+
{'x': list[int]}
5563+
)
5564+
self.assertEqual(
5565+
get_type_hints(foobar2, globals(), locals(), include_extras=True),
5566+
{'x': list[Annotated[int, (1, 10)]]}
5567+
)
5568+
else: # TODO: evaluate nested forward refs in Python < 3.11
5569+
self.assertEqual(
5570+
get_type_hints(foobar2, globals(), locals()),
5571+
{'x': list['X']}
5572+
)
5573+
self.assertEqual(
5574+
get_type_hints(foobar2, globals(), locals(), include_extras=True),
5575+
{'x': list['X']}
5576+
)
55025577
BA = Tuple[Annotated[T, (1, 0)], ...]
55035578
def barfoo(x: BA): ...
55045579
self.assertEqual(get_type_hints(barfoo, globals(), locals())['x'], Tuple[T, ...])
@@ -5973,6 +6048,15 @@ def run():
59736048
# The actual test:
59746049
self.assertEqual(result1, result2)
59756050

6051+
def test_subclass(self):
6052+
if sys.version_info >= (3, 10):
6053+
with self.assertRaises(TypeError):
6054+
class MyParamSpec(ParamSpec):
6055+
pass
6056+
else:
6057+
class MyParamSpec(ParamSpec): # Does not raise
6058+
pass
6059+
59766060

59776061
class ConcatenateTests(BaseTestCase):
59786062
def test_basics(self):
@@ -6382,6 +6466,14 @@ def test_pickle(self):
63826466
pickled = pickle.dumps(Self, protocol=proto)
63836467
self.assertIs(Self, pickle.loads(pickled))
63846468

6469+
@skipUnless(TYPING_3_10_0, "PEP 604 has yet to be")
6470+
def test_or(self):
6471+
self.assertEqual(Self | int, Union[Self, int])
6472+
self.assertEqual(int | Self, Union[int, Self])
6473+
6474+
self.assertEqual(get_args(Self | int), (Self, int))
6475+
self.assertEqual(get_args(int | Self), (int, Self))
6476+
63856477

63866478
class UnpackTests(BaseTestCase):
63876479
def test_basic_plain(self):
@@ -7749,6 +7841,45 @@ def test_immutable(self):
77497841
type(NoDefault).foo
77507842

77517843

7844+
class NoExtraItemsTests(BaseTestCase):
7845+
def test_pickling(self):
7846+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
7847+
s = pickle.dumps(NoExtraItems, proto)
7848+
loaded = pickle.loads(s)
7849+
self.assertIs(NoExtraItems, loaded)
7850+
7851+
def test_doc(self):
7852+
self.assertIsInstance(NoExtraItems.__doc__, str)
7853+
7854+
def test_constructor(self):
7855+
self.assertIs(NoExtraItems, type(NoExtraItems)())
7856+
with self.assertRaises(TypeError):
7857+
type(NoExtraItems)(1)
7858+
7859+
def test_repr(self):
7860+
if hasattr(typing, 'NoExtraItems'):
7861+
mod_name = 'typing'
7862+
else:
7863+
mod_name = "typing_extensions"
7864+
self.assertEqual(repr(NoExtraItems), f"{mod_name}.NoExtraItems")
7865+
7866+
def test_no_call(self):
7867+
with self.assertRaises(TypeError):
7868+
NoExtraItems()
7869+
7870+
def test_immutable(self):
7871+
with self.assertRaises(AttributeError):
7872+
NoExtraItems.foo = 'bar'
7873+
with self.assertRaises(AttributeError):
7874+
NoExtraItems.foo
7875+
7876+
# TypeError is consistent with the behavior of NoneType
7877+
with self.assertRaises(TypeError):
7878+
type(NoExtraItems).foo = 3
7879+
with self.assertRaises(AttributeError):
7880+
type(NoExtraItems).foo
7881+
7882+
77527883
class TypeVarInferVarianceTests(BaseTestCase):
77537884
def test_typevar(self):
77547885
T = typing_extensions.TypeVar('T')

0 commit comments

Comments
 (0)