@@ -151,6 +151,29 @@ def meth_self_o(self, object, /): pass
151151def meth_type_noargs (type , / ): pass
152152def meth_type_o (type , object , / ): pass
153153
154+ # Decorator decorator that returns a simple wrapped function
155+ def identity_wrapper (func ):
156+ @functools .wraps (func )
157+ def wrapped (* args , ** kwargs ):
158+ return func (* args , ** kwargs )
159+ return wrapped
160+
161+ # Original signature of the simple wrapped function returned by
162+ # identity_wrapper().
163+ varargs_signature = (
164+ (('args' , ..., ..., 'var_positional' ),
165+ ('kwargs' , ..., ..., 'var_keyword' )),
166+ ...,
167+ )
168+
169+ # Decorator decorator that returns a simple descriptor
170+ class custom_descriptor :
171+ def __init__ (self , func ):
172+ self .func = func
173+
174+ def __get__ (self , instance , owner ):
175+ return self .func .__get__ (instance , owner )
176+
154177
155178class TestPredicates (IsTestBase ):
156179
@@ -4149,44 +4172,266 @@ def __init__(self, b):
41494172 ('bar' , 2 , ..., "keyword_only" )),
41504173 ...))
41514174
4152- def test_signature_on_class_with_decorated_new (self ):
4153- def identity (func ):
4154- @functools .wraps (func )
4155- def wrapped (* args , ** kwargs ):
4156- return func (* args , ** kwargs )
4157- return wrapped
4158-
4159- class Foo :
4160- @identity
4161- def __new__ (cls , a , b ):
4175+ def test_signature_on_class_with_wrapped_metaclass_call (self ):
4176+ class CM (type ):
4177+ @identity_wrapper
4178+ def __call__ (cls , a ):
4179+ pass
4180+ class C (metaclass = CM ):
4181+ def __init__ (self , b ):
41624182 pass
41634183
4164- self .assertEqual (self .signature (Foo ),
4165- ((('a' , ..., ..., "positional_or_keyword" ),
4166- ('b' , ..., ..., "positional_or_keyword" )),
4184+ self .assertEqual (self .signature (C ),
4185+ ((('a' , ..., ..., "positional_or_keyword" ),),
41674186 ...))
41684187
4169- self .assertEqual (self .signature (Foo .__new__ ),
4170- ((('cls' , ..., ..., "positional_or_keyword" ),
4171- ('a' , ..., ..., "positional_or_keyword" ),
4172- ('b' , ..., ..., "positional_or_keyword" )),
4173- ...))
4188+ with self .subTest ('classmethod' ):
4189+ class CM (type ):
4190+ @classmethod
4191+ @identity_wrapper
4192+ def __call__ (cls , a ):
4193+ return a
4194+ class C (metaclass = CM ):
4195+ def __init__ (self , b ):
4196+ pass
41744197
4175- class Bar :
4176- __new__ = identity (object .__new__ )
4198+ self .assertEqual (C (1 ), 1 )
4199+ self .assertEqual (self .signature (C ),
4200+ ((('a' , ..., ..., "positional_or_keyword" ),),
4201+ ...))
41774202
4178- varargs_signature = (
4179- (('args' , ..., ..., 'var_positional' ),
4180- ('kwargs' , ..., ..., 'var_keyword' )),
4181- ...,
4182- )
4203+ with self .subTest ('staticmethod' ):
4204+ class CM (type ):
4205+ @staticmethod
4206+ @identity_wrapper
4207+ def __call__ (a ):
4208+ return a
4209+ class C (metaclass = CM ):
4210+ def __init__ (self , b ):
4211+ pass
4212+
4213+ self .assertEqual (C (1 ), 1 )
4214+ self .assertEqual (self .signature (C ),
4215+ ((('a' , ..., ..., "positional_or_keyword" ),),
4216+ ...))
4217+
4218+ with self .subTest ('MethodType' ):
4219+ class A :
4220+ @identity_wrapper
4221+ def call (self , a ):
4222+ return a
4223+ class CM (type ):
4224+ __call__ = A ().call
4225+ class C (metaclass = CM ):
4226+ def __init__ (self , b ):
4227+ pass
4228+
4229+ self .assertEqual (C (1 ), 1 )
4230+ self .assertEqual (self .signature (C ),
4231+ ((('a' , ..., ..., "positional_or_keyword" ),),
4232+ ...))
4233+
4234+ with self .subTest ('descriptor' ):
4235+ class CM (type ):
4236+ @custom_descriptor
4237+ @identity_wrapper
4238+ def __call__ (self , a ):
4239+ return a
4240+ class C (metaclass = CM ):
4241+ def __init__ (self , b ):
4242+ pass
4243+
4244+ self .assertEqual (C (1 ), 1 )
4245+ self .assertEqual (self .signature (C ),
4246+ ((('a' , ..., ..., "positional_or_keyword" ),),
4247+ ...))
4248+ self .assertEqual (self .signature (C .__call__ ),
4249+ ((('a' , ..., ..., "positional_or_keyword" ),),
4250+ ...))
4251+
4252+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4253+ varargs_signature )
4254+ self .assertEqual (self .signature (C .__call__ , follow_wrapped = False ),
4255+ varargs_signature )
4256+
4257+ def test_signature_on_class_with_wrapped_init (self ):
4258+ class C :
4259+ @identity_wrapper
4260+ def __init__ (self , b ):
4261+ pass
4262+
4263+ C (1 ) # does not raise
4264+ self .assertEqual (self .signature (C ),
4265+ ((('b' , ..., ..., "positional_or_keyword" ),),
4266+ ...))
4267+
4268+ with self .subTest ('classmethod' ):
4269+ class C :
4270+ @classmethod
4271+ @identity_wrapper
4272+ def __init__ (cls , b ):
4273+ pass
4274+
4275+ C (1 ) # does not raise
4276+ self .assertEqual (self .signature (C ),
4277+ ((('b' , ..., ..., "positional_or_keyword" ),),
4278+ ...))
4279+
4280+ with self .subTest ('staticmethod' ):
4281+ class C :
4282+ @staticmethod
4283+ @identity_wrapper
4284+ def __init__ (b ):
4285+ pass
4286+
4287+ C (1 ) # does not raise
4288+ self .assertEqual (self .signature (C ),
4289+ ((('b' , ..., ..., "positional_or_keyword" ),),
4290+ ...))
4291+
4292+ with self .subTest ('MethodType' ):
4293+ class A :
4294+ @identity_wrapper
4295+ def call (self , a ):
4296+ pass
4297+
4298+ class C :
4299+ __init__ = A ().call
4300+
4301+ C (1 ) # does not raise
4302+ self .assertEqual (self .signature (C ),
4303+ ((('a' , ..., ..., "positional_or_keyword" ),),
4304+ ...))
4305+
4306+ with self .subTest ('partial' ):
4307+ class C :
4308+ __init__ = functools .partial (identity_wrapper (lambda x , a , b : None ), 2 )
4309+
4310+ C (1 ) # does not raise
4311+ self .assertEqual (self .signature (C ),
4312+ ((('b' , ..., ..., "positional_or_keyword" ),),
4313+ ...))
4314+
4315+ with self .subTest ('partialmethod' ):
4316+ class C :
4317+ @identity_wrapper
4318+ def _init (self , x , a ):
4319+ self .a = (x , a )
4320+ __init__ = functools .partialmethod (_init , 2 )
4321+
4322+ self .assertEqual (C (1 ).a , (2 , 1 ))
4323+ self .assertEqual (self .signature (C ),
4324+ ((('a' , ..., ..., "positional_or_keyword" ),),
4325+ ...))
4326+
4327+ with self .subTest ('descriptor' ):
4328+ class C :
4329+ @custom_descriptor
4330+ @identity_wrapper
4331+ def __init__ (self , a ):
4332+ pass
4333+
4334+ C (1 ) # does not raise
4335+ self .assertEqual (self .signature (C ),
4336+ ((('a' , ..., ..., "positional_or_keyword" ),),
4337+ ...))
4338+ self .assertEqual (self .signature (C .__init__ ),
4339+ ((('self' , ..., ..., "positional_or_keyword" ),
4340+ ('a' , ..., ..., "positional_or_keyword" )),
4341+ ...))
4342+
4343+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4344+ varargs_signature )
4345+ self .assertEqual (self .signature (C .__new__ , follow_wrapped = False ),
4346+ varargs_signature )
4347+
4348+ def test_signature_on_class_with_wrapped_new (self ):
4349+ with self .subTest ('FunctionType' ):
4350+ class C :
4351+ @identity_wrapper
4352+ def __new__ (cls , a ):
4353+ return a
4354+
4355+ self .assertEqual (C (1 ), 1 )
4356+ self .assertEqual (self .signature (C ),
4357+ ((('a' , ..., ..., "positional_or_keyword" ),),
4358+ ...))
4359+
4360+ with self .subTest ('classmethod' ):
4361+ class C :
4362+ @classmethod
4363+ @identity_wrapper
4364+ def __new__ (cls , cls2 , a ):
4365+ return a
4366+
4367+ self .assertEqual (C (1 ), 1 )
4368+ self .assertEqual (self .signature (C ),
4369+ ((('a' , ..., ..., "positional_or_keyword" ),),
4370+ ...))
4371+
4372+ with self .subTest ('staticmethod' ):
4373+ class C :
4374+ @staticmethod
4375+ @identity_wrapper
4376+ def __new__ (cls , a ):
4377+ return a
4378+
4379+ self .assertEqual (C (1 ), 1 )
4380+ self .assertEqual (self .signature (C ),
4381+ ((('a' , ..., ..., "positional_or_keyword" ),),
4382+ ...))
4383+
4384+ with self .subTest ('MethodType' ):
4385+ class A :
4386+ @identity_wrapper
4387+ def call (self , cls , a ):
4388+ return a
4389+ class C :
4390+ __new__ = A ().call
4391+
4392+ self .assertEqual (C (1 ), 1 )
4393+ self .assertEqual (self .signature (C ),
4394+ ((('a' , ..., ..., "positional_or_keyword" ),),
4395+ ...))
4396+
4397+ with self .subTest ('partial' ):
4398+ class C :
4399+ __new__ = functools .partial (identity_wrapper (lambda x , cls , a : (x , a )), 2 )
4400+
4401+ self .assertEqual (C (1 ), (2 , 1 ))
4402+ self .assertEqual (self .signature (C ),
4403+ ((('a' , ..., ..., "positional_or_keyword" ),),
4404+ ...))
4405+
4406+ with self .subTest ('partialmethod' ):
4407+ class C :
4408+ __new__ = functools .partialmethod (identity_wrapper (lambda cls , x , a : (x , a )), 2 )
4409+
4410+ self .assertEqual (C (1 ), (2 , 1 ))
4411+ self .assertEqual (self .signature (C ),
4412+ ((('a' , ..., ..., "positional_or_keyword" ),),
4413+ ...))
4414+
4415+ with self .subTest ('descriptor' ):
4416+ class C :
4417+ @custom_descriptor
4418+ @identity_wrapper
4419+ def __new__ (cls , a ):
4420+ return a
4421+
4422+ self .assertEqual (C (1 ), 1 )
4423+ self .assertEqual (self .signature (C ),
4424+ ((('a' , ..., ..., "positional_or_keyword" ),),
4425+ ...))
4426+ self .assertEqual (self .signature (C .__new__ ),
4427+ ((('cls' , ..., ..., "positional_or_keyword" ),
4428+ ('a' , ..., ..., "positional_or_keyword" )),
4429+ ...))
41834430
4184- self .assertEqual (self .signature (Bar ), ((), ...))
4185- self .assertEqual (self .signature (Bar .__new__ ), varargs_signature )
4186- self .assertEqual (self .signature (Bar , follow_wrapped = False ),
4187- varargs_signature )
4188- self .assertEqual (self .signature (Bar .__new__ , follow_wrapped = False ),
4189- varargs_signature )
4431+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4432+ varargs_signature )
4433+ self .assertEqual (self .signature (C .__new__ , follow_wrapped = False ),
4434+ varargs_signature )
41904435
41914436 def test_signature_on_class_with_init (self ):
41924437 class C :
0 commit comments