Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitccbfd9b

Browse files
brianschubertAlexWaygoodDaraan
authored
Add some miscellaneous tests (#659)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>Co-authored-by: Daraan <github.blurry@9ox.net>
1 parent944a351 commitccbfd9b

File tree

3 files changed

+144
-23
lines changed

3 files changed

+144
-23
lines changed

‎CHANGELOG.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
#Unreleased
2+
3+
- Raise`TypeError` when attempting to subclass`typing_extensions.ParamSpec` on
4+
Python 3.9. The`typing` implementation has always raised an error, and the
5+
`typing_extensions` implementation has raised an error on Python 3.10+ since
6+
`typing_extensions` v4.6.0. Patch by Brian Schubert.
7+
18
#Release 4.15.0 (August 25, 2025)
29

310
No user-facing changes since 4.15.0rc1.

‎src/test_typing_extensions.py‎

Lines changed: 129 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,14 @@ def test_pickle(self):
531531
pickled=pickle.dumps(self.bottom_type,protocol=proto)
532532
self.assertIs(self.bottom_type,pickle.loads(pickled))
533533

534+
@skipUnless(TYPING_3_10_0,"PEP 604 has yet to be")
535+
deftest_or(self):
536+
self.assertEqual(self.bottom_type|int,Union[self.bottom_type,int])
537+
self.assertEqual(int|self.bottom_type,Union[int,self.bottom_type])
538+
539+
self.assertEqual(get_args(self.bottom_type|int), (self.bottom_type,int))
540+
self.assertEqual(get_args(int|self.bottom_type), (int,self.bottom_type))
541+
534542

535543
classNoReturnTests(BottomTypeTestsMixin,BaseTestCase):
536544
bottom_type=NoReturn
@@ -2210,6 +2218,39 @@ def test_or_and_ror(self):
22102218
Union[typing_extensions.Generator,typing.Deque]
22112219
)
22122220

2221+
deftest_setattr(self):
2222+
origin=collections.abc.Generator
2223+
alias=typing_extensions.Generator
2224+
original_name=alias._name
2225+
2226+
defcleanup():
2227+
forobjinorigin,alias:
2228+
forattrin'foo','__dunder__':
2229+
try:
2230+
delattr(obj,attr)
2231+
exceptException:
2232+
pass
2233+
try:
2234+
alias._name=original_name
2235+
exceptException:
2236+
pass
2237+
2238+
self.addCleanup(cleanup)
2239+
2240+
# Attribute assignment on generic alias sets attribute on origin
2241+
alias.foo=1
2242+
self.assertEqual(alias.foo,1)
2243+
self.assertEqual(origin.foo,1)
2244+
# Except for dunders...
2245+
alias.__dunder__=2
2246+
self.assertEqual(alias.__dunder__,2)
2247+
self.assertRaises(AttributeError,lambda:origin.__dunder__)
2248+
2249+
# ...and certain known attributes
2250+
alias._name="NewName"
2251+
self.assertEqual(alias._name,"NewName")
2252+
self.assertRaises(AttributeError,lambda:origin._name)
2253+
22132254

22142255
classOtherABCTests(BaseTestCase):
22152256

@@ -2379,6 +2420,16 @@ def test_error_message_when_subclassing(self):
23792420
classProUserId(UserId):
23802421
...
23812422

2423+
deftest_module_with_incomplete_sys(self):
2424+
defdoes_not_exist(*args):
2425+
raiseAttributeError
2426+
with (
2427+
patch("sys._getframemodulename",does_not_exist,create=True),
2428+
patch("sys._getframe",does_not_exist,create=True),
2429+
):
2430+
X=NewType("X",int)
2431+
self.assertEqual(X.__module__,None)
2432+
23822433

23832434
classCoordinate(Protocol):
23842435
x:int
@@ -5297,6 +5348,17 @@ class A(TypedDict):
52975348
deftest_dunder_dict(self):
52985349
self.assertIsInstance(TypedDict.__dict__,dict)
52995350

5351+
@skipUnless(TYPING_3_10_0,"PEP 604 has yet to be")
5352+
deftest_or(self):
5353+
classTD(TypedDict):
5354+
a:int
5355+
5356+
self.assertEqual(TD|int,Union[TD,int])
5357+
self.assertEqual(int|TD,Union[int,TD])
5358+
5359+
self.assertEqual(get_args(TD|int), (TD,int))
5360+
self.assertEqual(get_args(int|TD), (int,TD))
5361+
53005362
classAnnotatedTests(BaseTestCase):
53015363

53025364
deftest_repr(self):
@@ -5519,6 +5581,19 @@ def barfoo3(x: BA2): ...
55195581
BA2
55205582
)
55215583

5584+
@skipUnless(TYPING_3_11_0,"TODO: evaluate nested forward refs in Python < 3.11")
5585+
deftest_get_type_hints_genericalias(self):
5586+
deffoobar(x:list['X']): ...
5587+
X=Annotated[int, (1,10)]
5588+
self.assertEqual(
5589+
get_type_hints(foobar,globals(),locals()),
5590+
{'x':list[int]}
5591+
)
5592+
self.assertEqual(
5593+
get_type_hints(foobar,globals(),locals(),include_extras=True),
5594+
{'x':list[Annotated[int, (1,10)]]}
5595+
)
5596+
55225597
deftest_get_type_hints_refs(self):
55235598

55245599
Const=Annotated[T,"Const"]
@@ -5973,6 +6048,11 @@ def run():
59736048
# The actual test:
59746049
self.assertEqual(result1,result2)
59756050

6051+
deftest_subclass(self):
6052+
withself.assertRaises(TypeError):
6053+
classMyParamSpec(ParamSpec):
6054+
pass
6055+
59766056

59776057
classConcatenateTests(BaseTestCase):
59786058
deftest_basics(self):
@@ -6335,6 +6415,14 @@ def test_pickle(self):
63356415
pickled=pickle.dumps(LiteralString,protocol=proto)
63366416
self.assertIs(LiteralString,pickle.loads(pickled))
63376417

6418+
@skipUnless(TYPING_3_10_0,"PEP 604 has yet to be")
6419+
deftest_or(self):
6420+
self.assertEqual(LiteralString|int,Union[LiteralString,int])
6421+
self.assertEqual(int|LiteralString,Union[int,LiteralString])
6422+
6423+
self.assertEqual(get_args(LiteralString|int), (LiteralString,int))
6424+
self.assertEqual(get_args(int|LiteralString), (int,LiteralString))
6425+
63386426

63396427
classSelfTests(BaseTestCase):
63406428
deftest_basics(self):
@@ -6382,6 +6470,14 @@ def test_pickle(self):
63826470
pickled=pickle.dumps(Self,protocol=proto)
63836471
self.assertIs(Self,pickle.loads(pickled))
63846472

6473+
@skipUnless(TYPING_3_10_0,"PEP 604 has yet to be")
6474+
deftest_or(self):
6475+
self.assertEqual(Self|int,Union[Self,int])
6476+
self.assertEqual(int|Self,Union[int,Self])
6477+
6478+
self.assertEqual(get_args(Self|int), (Self,int))
6479+
self.assertEqual(get_args(int|Self), (int,Self))
6480+
63856481

63866482
classUnpackTests(BaseTestCase):
63876483
deftest_basic_plain(self):
@@ -7711,42 +7807,61 @@ class A(Generic[T, P, U]): ...
77117807
self.assertEqual(A[float, [range],int].__args__, (float, (range,),int))
77127808

77137809

7714-
classNoDefaultTests(BaseTestCase):
7810+
classSentinelTestsMixin:
77157811
@skip_if_py313_beta_1
77167812
deftest_pickling(self):
77177813
forprotoinrange(pickle.HIGHEST_PROTOCOL+1):
7718-
s=pickle.dumps(NoDefault,proto)
7814+
s=pickle.dumps(self.sentinel_type,proto)
77197815
loaded=pickle.loads(s)
7720-
self.assertIs(NoDefault,loaded)
7816+
self.assertIs(self.sentinel_type,loaded)
77217817

77227818
@skip_if_py313_beta_1
77237819
deftest_doc(self):
7724-
self.assertIsInstance(NoDefault.__doc__,str)
7820+
self.assertIsInstance(self.sentinel_type.__doc__,str)
77257821

77267822
deftest_constructor(self):
7727-
self.assertIs(NoDefault,type(NoDefault)())
7823+
self.assertIs(self.sentinel_type,type(self.sentinel_type)())
77287824
withself.assertRaises(TypeError):
7729-
type(NoDefault)(1)
7730-
7731-
deftest_repr(self):
7732-
self.assertRegex(repr(NoDefault),r'typing(_extensions)?\.NoDefault')
7825+
type(self.sentinel_type)(1)
77337826

77347827
deftest_no_call(self):
77357828
withself.assertRaises(TypeError):
7736-
NoDefault()
7829+
self.sentinel_type()
77377830

77387831
@skip_if_py313_beta_1
77397832
deftest_immutable(self):
77407833
withself.assertRaises(AttributeError):
7741-
NoDefault.foo='bar'
7834+
self.sentinel_type.foo='bar'
77427835
withself.assertRaises(AttributeError):
7743-
NoDefault.foo
7836+
self.sentinel_type.foo
77447837

77457838
# TypeError is consistent with the behavior of NoneType
77467839
withself.assertRaises(TypeError):
7747-
type(NoDefault).foo=3
7840+
type(self.sentinel_type).foo=3
77487841
withself.assertRaises(AttributeError):
7749-
type(NoDefault).foo
7842+
type(self.sentinel_type).foo
7843+
7844+
7845+
classNoDefaultTests(SentinelTestsMixin,BaseTestCase):
7846+
sentinel_type=NoDefault
7847+
7848+
deftest_repr(self):
7849+
ifhasattr(typing,'NoDefault'):
7850+
mod_name='typing'
7851+
else:
7852+
mod_name="typing_extensions"
7853+
self.assertEqual(repr(NoDefault),f"{mod_name}.NoDefault")
7854+
7855+
7856+
classNoExtraItemsTests(SentinelTestsMixin,BaseTestCase):
7857+
sentinel_type=NoExtraItems
7858+
7859+
deftest_repr(self):
7860+
ifhasattr(typing,'NoExtraItems'):
7861+
mod_name='typing'
7862+
else:
7863+
mod_name="typing_extensions"
7864+
self.assertEqual(repr(NoExtraItems),f"{mod_name}.NoExtraItems")
77507865

77517866

77527867
classTypeVarInferVarianceTests(BaseTestCase):

‎src/typing_extensions.py‎

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,9 @@ def _is_dunder(attr):
555555

556556

557557
class_SpecialGenericAlias(typing._SpecialGenericAlias,_root=True):
558-
def__init__(self,origin,nparams,*,inst=True,name=None,defaults=()):
558+
def__init__(self,origin,nparams,*,defaults,inst=True,name=None):
559+
assertnparams>0,"`nparams` must be a positive integer"
560+
assertdefaults,"Must always specify a non-empty sequence for `defaults`"
559561
super().__init__(origin,nparams,inst=inst,name=name)
560562
self._defaults=defaults
561563

@@ -573,20 +575,14 @@ def __getitem__(self, params):
573575
msg="Parameters to generic types must be types."
574576
params=tuple(typing._type_check(p,msg)forpinparams)
575577
if (
576-
self._defaults
577-
andlen(params)<self._nparams
578+
len(params)<self._nparams
578579
andlen(params)+len(self._defaults)>=self._nparams
579580
):
580581
params= (*params,*self._defaults[len(params)-self._nparams:])
581582
actual_len=len(params)
582583

583584
ifactual_len!=self._nparams:
584-
ifself._defaults:
585-
expected=f"at least{self._nparams-len(self._defaults)}"
586-
else:
587-
expected=str(self._nparams)
588-
ifnotself._nparams:
589-
raiseTypeError(f"{self} is not a generic class")
585+
expected=f"at least{self._nparams-len(self._defaults)}"
590586
raiseTypeError(
591587
f"Too{'many'ifactual_len>self._nparamselse'few'}"
592588
f" arguments for{self};"
@@ -1960,6 +1956,9 @@ def __reduce__(self):
19601956
def__call__(self,*args,**kwargs):
19611957
pass
19621958

1959+
def__init_subclass__(cls)->None:
1960+
raiseTypeError(f"type '{__name__}.ParamSpec' is not an acceptable base type")
1961+
19631962

19641963
# 3.9
19651964
ifnothasattr(typing,'Concatenate'):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp