@@ -148,6 +148,29 @@ def meth_self_o(self, object, /): pass
148148def meth_type_noargs (type , / ): pass
149149def meth_type_o (type , object , / ): pass
150150
151+ # Decorator decorator that returns a simple wrapped function
152+ def identity_wrapper (func ):
153+ @functools .wraps (func )
154+ def wrapped (* args , ** kwargs ):
155+ return func (* args , ** kwargs )
156+ return wrapped
157+
158+ # Original signature of the simple wrapped function returned by
159+ # identity_wrapper().
160+ varargs_signature = (
161+ (('args' , ..., ..., 'var_positional' ),
162+ ('kwargs' , ..., ..., 'var_keyword' )),
163+ ...,
164+ )
165+
166+ # Decorator decorator that returns a simple descriptor
167+ class custom_descriptor :
168+ def __init__ (self , func ):
169+ self .func = func
170+
171+ def __get__ (self , instance , owner ):
172+ return self .func .__get__ (instance , owner )
173+
151174
152175class TestPredicates (IsTestBase ):
153176
@@ -4021,44 +4044,266 @@ def __init__(self, b):
40214044 ('bar' , 2 , ..., "keyword_only" )),
40224045 ...))
40234046
4024- def test_signature_on_class_with_decorated_new (self ):
4025- def identity (func ):
4026- @functools .wraps (func )
4027- def wrapped (* args , ** kwargs ):
4028- return func (* args , ** kwargs )
4029- return wrapped
4030-
4031- class Foo :
4032- @identity
4033- def __new__ (cls , a , b ):
4047+ def test_signature_on_class_with_wrapped_metaclass_call (self ):
4048+ class CM (type ):
4049+ @identity_wrapper
4050+ def __call__ (cls , a ):
4051+ pass
4052+ class C (metaclass = CM ):
4053+ def __init__ (self , b ):
40344054 pass
40354055
4036- self .assertEqual (self .signature (Foo ),
4037- ((('a' , ..., ..., "positional_or_keyword" ),
4038- ('b' , ..., ..., "positional_or_keyword" )),
4056+ self .assertEqual (self .signature (C ),
4057+ ((('a' , ..., ..., "positional_or_keyword" ),),
40394058 ...))
40404059
4041- self .assertEqual (self .signature (Foo .__new__ ),
4042- ((('cls' , ..., ..., "positional_or_keyword" ),
4043- ('a' , ..., ..., "positional_or_keyword" ),
4044- ('b' , ..., ..., "positional_or_keyword" )),
4045- ...))
4060+ with self .subTest ('classmethod' ):
4061+ class CM (type ):
4062+ @classmethod
4063+ @identity_wrapper
4064+ def __call__ (cls , a ):
4065+ return a
4066+ class C (metaclass = CM ):
4067+ def __init__ (self , b ):
4068+ pass
40464069
4047- class Bar :
4048- __new__ = identity (object .__new__ )
4070+ self .assertEqual (C (1 ), 1 )
4071+ self .assertEqual (self .signature (C ),
4072+ ((('a' , ..., ..., "positional_or_keyword" ),),
4073+ ...))
40494074
4050- varargs_signature = (
4051- (('args' , ..., ..., 'var_positional' ),
4052- ('kwargs' , ..., ..., 'var_keyword' )),
4053- ...,
4054- )
4075+ with self .subTest ('staticmethod' ):
4076+ class CM (type ):
4077+ @staticmethod
4078+ @identity_wrapper
4079+ def __call__ (a ):
4080+ return a
4081+ class C (metaclass = CM ):
4082+ def __init__ (self , b ):
4083+ pass
4084+
4085+ self .assertEqual (C (1 ), 1 )
4086+ self .assertEqual (self .signature (C ),
4087+ ((('a' , ..., ..., "positional_or_keyword" ),),
4088+ ...))
4089+
4090+ with self .subTest ('MethodType' ):
4091+ class A :
4092+ @identity_wrapper
4093+ def call (self , a ):
4094+ return a
4095+ class CM (type ):
4096+ __call__ = A ().call
4097+ class C (metaclass = CM ):
4098+ def __init__ (self , b ):
4099+ pass
4100+
4101+ self .assertEqual (C (1 ), 1 )
4102+ self .assertEqual (self .signature (C ),
4103+ ((('a' , ..., ..., "positional_or_keyword" ),),
4104+ ...))
4105+
4106+ with self .subTest ('descriptor' ):
4107+ class CM (type ):
4108+ @custom_descriptor
4109+ @identity_wrapper
4110+ def __call__ (self , a ):
4111+ return a
4112+ class C (metaclass = CM ):
4113+ def __init__ (self , b ):
4114+ pass
4115+
4116+ self .assertEqual (C (1 ), 1 )
4117+ self .assertEqual (self .signature (C ),
4118+ ((('a' , ..., ..., "positional_or_keyword" ),),
4119+ ...))
4120+ self .assertEqual (self .signature (C .__call__ ),
4121+ ((('a' , ..., ..., "positional_or_keyword" ),),
4122+ ...))
4123+
4124+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4125+ varargs_signature )
4126+ self .assertEqual (self .signature (C .__call__ , follow_wrapped = False ),
4127+ varargs_signature )
4128+
4129+ def test_signature_on_class_with_wrapped_init (self ):
4130+ class C :
4131+ @identity_wrapper
4132+ def __init__ (self , b ):
4133+ pass
4134+
4135+ C (1 ) # does not raise
4136+ self .assertEqual (self .signature (C ),
4137+ ((('b' , ..., ..., "positional_or_keyword" ),),
4138+ ...))
4139+
4140+ with self .subTest ('classmethod' ):
4141+ class C :
4142+ @classmethod
4143+ @identity_wrapper
4144+ def __init__ (cls , b ):
4145+ pass
4146+
4147+ C (1 ) # does not raise
4148+ self .assertEqual (self .signature (C ),
4149+ ((('b' , ..., ..., "positional_or_keyword" ),),
4150+ ...))
4151+
4152+ with self .subTest ('staticmethod' ):
4153+ class C :
4154+ @staticmethod
4155+ @identity_wrapper
4156+ def __init__ (b ):
4157+ pass
4158+
4159+ C (1 ) # does not raise
4160+ self .assertEqual (self .signature (C ),
4161+ ((('b' , ..., ..., "positional_or_keyword" ),),
4162+ ...))
4163+
4164+ with self .subTest ('MethodType' ):
4165+ class A :
4166+ @identity_wrapper
4167+ def call (self , a ):
4168+ pass
4169+
4170+ class C :
4171+ __init__ = A ().call
4172+
4173+ C (1 ) # does not raise
4174+ self .assertEqual (self .signature (C ),
4175+ ((('a' , ..., ..., "positional_or_keyword" ),),
4176+ ...))
4177+
4178+ with self .subTest ('partial' ):
4179+ class C :
4180+ __init__ = functools .partial (identity_wrapper (lambda x , a , b : None ), 2 )
4181+
4182+ C (1 ) # does not raise
4183+ self .assertEqual (self .signature (C ),
4184+ ((('b' , ..., ..., "positional_or_keyword" ),),
4185+ ...))
4186+
4187+ with self .subTest ('partialmethod' ):
4188+ class C :
4189+ @identity_wrapper
4190+ def _init (self , x , a ):
4191+ self .a = (x , a )
4192+ __init__ = functools .partialmethod (_init , 2 )
4193+
4194+ self .assertEqual (C (1 ).a , (2 , 1 ))
4195+ self .assertEqual (self .signature (C ),
4196+ ((('a' , ..., ..., "positional_or_keyword" ),),
4197+ ...))
4198+
4199+ with self .subTest ('descriptor' ):
4200+ class C :
4201+ @custom_descriptor
4202+ @identity_wrapper
4203+ def __init__ (self , a ):
4204+ pass
4205+
4206+ C (1 ) # does not raise
4207+ self .assertEqual (self .signature (C ),
4208+ ((('a' , ..., ..., "positional_or_keyword" ),),
4209+ ...))
4210+ self .assertEqual (self .signature (C .__init__ ),
4211+ ((('self' , ..., ..., "positional_or_keyword" ),
4212+ ('a' , ..., ..., "positional_or_keyword" )),
4213+ ...))
4214+
4215+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4216+ varargs_signature )
4217+ self .assertEqual (self .signature (C .__new__ , follow_wrapped = False ),
4218+ varargs_signature )
4219+
4220+ def test_signature_on_class_with_wrapped_new (self ):
4221+ with self .subTest ('FunctionType' ):
4222+ class C :
4223+ @identity_wrapper
4224+ def __new__ (cls , a ):
4225+ return a
4226+
4227+ self .assertEqual (C (1 ), 1 )
4228+ self .assertEqual (self .signature (C ),
4229+ ((('a' , ..., ..., "positional_or_keyword" ),),
4230+ ...))
4231+
4232+ with self .subTest ('classmethod' ):
4233+ class C :
4234+ @classmethod
4235+ @identity_wrapper
4236+ def __new__ (cls , cls2 , a ):
4237+ return a
4238+
4239+ self .assertEqual (C (1 ), 1 )
4240+ self .assertEqual (self .signature (C ),
4241+ ((('a' , ..., ..., "positional_or_keyword" ),),
4242+ ...))
4243+
4244+ with self .subTest ('staticmethod' ):
4245+ class C :
4246+ @staticmethod
4247+ @identity_wrapper
4248+ def __new__ (cls , a ):
4249+ return a
4250+
4251+ self .assertEqual (C (1 ), 1 )
4252+ self .assertEqual (self .signature (C ),
4253+ ((('a' , ..., ..., "positional_or_keyword" ),),
4254+ ...))
4255+
4256+ with self .subTest ('MethodType' ):
4257+ class A :
4258+ @identity_wrapper
4259+ def call (self , cls , a ):
4260+ return a
4261+ class C :
4262+ __new__ = A ().call
4263+
4264+ self .assertEqual (C (1 ), 1 )
4265+ self .assertEqual (self .signature (C ),
4266+ ((('a' , ..., ..., "positional_or_keyword" ),),
4267+ ...))
4268+
4269+ with self .subTest ('partial' ):
4270+ class C :
4271+ __new__ = functools .partial (identity_wrapper (lambda x , cls , a : (x , a )), 2 )
4272+
4273+ self .assertEqual (C (1 ), (2 , 1 ))
4274+ self .assertEqual (self .signature (C ),
4275+ ((('a' , ..., ..., "positional_or_keyword" ),),
4276+ ...))
4277+
4278+ with self .subTest ('partialmethod' ):
4279+ class C :
4280+ __new__ = functools .partialmethod (identity_wrapper (lambda cls , x , a : (x , a )), 2 )
4281+
4282+ self .assertEqual (C (1 ), (2 , 1 ))
4283+ self .assertEqual (self .signature (C ),
4284+ ((('a' , ..., ..., "positional_or_keyword" ),),
4285+ ...))
4286+
4287+ with self .subTest ('descriptor' ):
4288+ class C :
4289+ @custom_descriptor
4290+ @identity_wrapper
4291+ def __new__ (cls , a ):
4292+ return a
4293+
4294+ self .assertEqual (C (1 ), 1 )
4295+ self .assertEqual (self .signature (C ),
4296+ ((('a' , ..., ..., "positional_or_keyword" ),),
4297+ ...))
4298+ self .assertEqual (self .signature (C .__new__ ),
4299+ ((('cls' , ..., ..., "positional_or_keyword" ),
4300+ ('a' , ..., ..., "positional_or_keyword" )),
4301+ ...))
40554302
4056- self .assertEqual (self .signature (Bar ), ((), ...))
4057- self .assertEqual (self .signature (Bar .__new__ ), varargs_signature )
4058- self .assertEqual (self .signature (Bar , follow_wrapped = False ),
4059- varargs_signature )
4060- self .assertEqual (self .signature (Bar .__new__ , follow_wrapped = False ),
4061- varargs_signature )
4303+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4304+ varargs_signature )
4305+ self .assertEqual (self .signature (C .__new__ , follow_wrapped = False ),
4306+ varargs_signature )
40624307
40634308 def test_signature_on_class_with_init (self ):
40644309 class C :
0 commit comments