@@ -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,268 @@ 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 : None ), 2 )
4309+
4310+ with self .assertWarns (FutureWarning ):
4311+ C (1 ) # does not raise
4312+ with self .assertWarns (FutureWarning ):
4313+ self .assertEqual (self .signature (C ),
4314+ ((('a' , ..., ..., "positional_or_keyword" ),),
4315+ ...))
4316+
4317+ with self .subTest ('partialmethod' ):
4318+ class C :
4319+ @identity_wrapper
4320+ def _init (self , x , a ):
4321+ self .a = (x , a )
4322+ __init__ = functools .partialmethod (_init , 2 )
4323+
4324+ self .assertEqual (C (1 ).a , (2 , 1 ))
4325+ self .assertEqual (self .signature (C ),
4326+ ((('a' , ..., ..., "positional_or_keyword" ),),
4327+ ...))
4328+
4329+ with self .subTest ('descriptor' ):
4330+ class C :
4331+ @custom_descriptor
4332+ @identity_wrapper
4333+ def __init__ (self , a ):
4334+ pass
4335+
4336+ C (1 ) # does not raise
4337+ self .assertEqual (self .signature (C ),
4338+ ((('a' , ..., ..., "positional_or_keyword" ),),
4339+ ...))
4340+ self .assertEqual (self .signature (C .__init__ ),
4341+ ((('self' , ..., ..., "positional_or_keyword" ),
4342+ ('a' , ..., ..., "positional_or_keyword" )),
4343+ ...))
4344+
4345+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4346+ varargs_signature )
4347+ self .assertEqual (self .signature (C .__new__ , follow_wrapped = False ),
4348+ varargs_signature )
4349+
4350+ def test_signature_on_class_with_wrapped_new (self ):
4351+ with self .subTest ('FunctionType' ):
4352+ class C :
4353+ @identity_wrapper
4354+ def __new__ (cls , a ):
4355+ return a
4356+
4357+ self .assertEqual (C (1 ), 1 )
4358+ self .assertEqual (self .signature (C ),
4359+ ((('a' , ..., ..., "positional_or_keyword" ),),
4360+ ...))
4361+
4362+ with self .subTest ('classmethod' ):
4363+ class C :
4364+ @classmethod
4365+ @identity_wrapper
4366+ def __new__ (cls , cls2 , a ):
4367+ return a
4368+
4369+ self .assertEqual (C (1 ), 1 )
4370+ self .assertEqual (self .signature (C ),
4371+ ((('a' , ..., ..., "positional_or_keyword" ),),
4372+ ...))
4373+
4374+ with self .subTest ('staticmethod' ):
4375+ class C :
4376+ @staticmethod
4377+ @identity_wrapper
4378+ def __new__ (cls , a ):
4379+ return a
4380+
4381+ self .assertEqual (C (1 ), 1 )
4382+ self .assertEqual (self .signature (C ),
4383+ ((('a' , ..., ..., "positional_or_keyword" ),),
4384+ ...))
4385+
4386+ with self .subTest ('MethodType' ):
4387+ class A :
4388+ @identity_wrapper
4389+ def call (self , cls , a ):
4390+ return a
4391+ class C :
4392+ __new__ = A ().call
4393+
4394+ self .assertEqual (C (1 ), 1 )
4395+ self .assertEqual (self .signature (C ),
4396+ ((('a' , ..., ..., "positional_or_keyword" ),),
4397+ ...))
4398+
4399+ with self .subTest ('partial' ):
4400+ class C :
4401+ __new__ = functools .partial (identity_wrapper (lambda x , cls , a : (x , a )), 2 )
4402+
4403+ self .assertEqual (C (1 ), (2 , 1 ))
4404+ self .assertEqual (self .signature (C ),
4405+ ((('a' , ..., ..., "positional_or_keyword" ),),
4406+ ...))
4407+
4408+ with self .subTest ('partialmethod' ):
4409+ class C :
4410+ __new__ = functools .partialmethod (identity_wrapper (lambda cls , x , a : (x , a )), 2 )
4411+
4412+ self .assertEqual (C (1 ), (2 , 1 ))
4413+ self .assertEqual (self .signature (C ),
4414+ ((('a' , ..., ..., "positional_or_keyword" ),),
4415+ ...))
4416+
4417+ with self .subTest ('descriptor' ):
4418+ class C :
4419+ @custom_descriptor
4420+ @identity_wrapper
4421+ def __new__ (cls , a ):
4422+ return a
4423+
4424+ self .assertEqual (C (1 ), 1 )
4425+ self .assertEqual (self .signature (C ),
4426+ ((('a' , ..., ..., "positional_or_keyword" ),),
4427+ ...))
4428+ self .assertEqual (self .signature (C .__new__ ),
4429+ ((('cls' , ..., ..., "positional_or_keyword" ),
4430+ ('a' , ..., ..., "positional_or_keyword" )),
4431+ ...))
41834432
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 )
4433+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4434+ varargs_signature )
4435+ self .assertEqual (self .signature (C .__new__ , follow_wrapped = False ),
4436+ varargs_signature )
41904437
41914438 def test_signature_on_class_with_init (self ):
41924439 class C :
0 commit comments