@@ -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
@@ -4068,44 +4091,266 @@ def __init__(self, b):
40684091 ('bar' , 2 , ..., "keyword_only" )),
40694092 ...))
40704093
4071- def test_signature_on_class_with_decorated_new (self ):
4072- def identity (func ):
4073- @functools .wraps (func )
4074- def wrapped (* args , ** kwargs ):
4075- return func (* args , ** kwargs )
4076- return wrapped
4077-
4078- class Foo :
4079- @identity
4080- def __new__ (cls , a , b ):
4094+ def test_signature_on_class_with_wrapped_metaclass_call (self ):
4095+ class CM (type ):
4096+ @identity_wrapper
4097+ def __call__ (cls , a ):
4098+ pass
4099+ class C (metaclass = CM ):
4100+ def __init__ (self , b ):
40814101 pass
40824102
4083- self .assertEqual (self .signature (Foo ),
4084- ((('a' , ..., ..., "positional_or_keyword" ),
4085- ('b' , ..., ..., "positional_or_keyword" )),
4103+ self .assertEqual (self .signature (C ),
4104+ ((('a' , ..., ..., "positional_or_keyword" ),),
40864105 ...))
40874106
4088- self .assertEqual (self .signature (Foo .__new__ ),
4089- ((('cls' , ..., ..., "positional_or_keyword" ),
4090- ('a' , ..., ..., "positional_or_keyword" ),
4091- ('b' , ..., ..., "positional_or_keyword" )),
4092- ...))
4107+ with self .subTest ('classmethod' ):
4108+ class CM (type ):
4109+ @classmethod
4110+ @identity_wrapper
4111+ def __call__ (cls , a ):
4112+ return a
4113+ class C (metaclass = CM ):
4114+ def __init__ (self , b ):
4115+ pass
40934116
4094- class Bar :
4095- __new__ = identity (object .__new__ )
4117+ self .assertEqual (C (1 ), 1 )
4118+ self .assertEqual (self .signature (C ),
4119+ ((('a' , ..., ..., "positional_or_keyword" ),),
4120+ ...))
40964121
4097- varargs_signature = (
4098- (('args' , ..., ..., 'var_positional' ),
4099- ('kwargs' , ..., ..., 'var_keyword' )),
4100- ...,
4101- )
4122+ with self .subTest ('staticmethod' ):
4123+ class CM (type ):
4124+ @staticmethod
4125+ @identity_wrapper
4126+ def __call__ (a ):
4127+ return a
4128+ class C (metaclass = CM ):
4129+ def __init__ (self , b ):
4130+ pass
4131+
4132+ self .assertEqual (C (1 ), 1 )
4133+ self .assertEqual (self .signature (C ),
4134+ ((('a' , ..., ..., "positional_or_keyword" ),),
4135+ ...))
4136+
4137+ with self .subTest ('MethodType' ):
4138+ class A :
4139+ @identity_wrapper
4140+ def call (self , a ):
4141+ return a
4142+ class CM (type ):
4143+ __call__ = A ().call
4144+ class C (metaclass = CM ):
4145+ def __init__ (self , b ):
4146+ pass
4147+
4148+ self .assertEqual (C (1 ), 1 )
4149+ self .assertEqual (self .signature (C ),
4150+ ((('a' , ..., ..., "positional_or_keyword" ),),
4151+ ...))
4152+
4153+ with self .subTest ('descriptor' ):
4154+ class CM (type ):
4155+ @custom_descriptor
4156+ @identity_wrapper
4157+ def __call__ (self , a ):
4158+ return a
4159+ class C (metaclass = CM ):
4160+ def __init__ (self , b ):
4161+ pass
4162+
4163+ self .assertEqual (C (1 ), 1 )
4164+ self .assertEqual (self .signature (C ),
4165+ ((('a' , ..., ..., "positional_or_keyword" ),),
4166+ ...))
4167+ self .assertEqual (self .signature (C .__call__ ),
4168+ ((('a' , ..., ..., "positional_or_keyword" ),),
4169+ ...))
4170+
4171+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4172+ varargs_signature )
4173+ self .assertEqual (self .signature (C .__call__ , follow_wrapped = False ),
4174+ varargs_signature )
4175+
4176+ def test_signature_on_class_with_wrapped_init (self ):
4177+ class C :
4178+ @identity_wrapper
4179+ def __init__ (self , b ):
4180+ pass
4181+
4182+ C (1 ) # does not raise
4183+ self .assertEqual (self .signature (C ),
4184+ ((('b' , ..., ..., "positional_or_keyword" ),),
4185+ ...))
4186+
4187+ with self .subTest ('classmethod' ):
4188+ class C :
4189+ @classmethod
4190+ @identity_wrapper
4191+ def __init__ (cls , b ):
4192+ pass
4193+
4194+ C (1 ) # does not raise
4195+ self .assertEqual (self .signature (C ),
4196+ ((('b' , ..., ..., "positional_or_keyword" ),),
4197+ ...))
4198+
4199+ with self .subTest ('staticmethod' ):
4200+ class C :
4201+ @staticmethod
4202+ @identity_wrapper
4203+ def __init__ (b ):
4204+ pass
4205+
4206+ C (1 ) # does not raise
4207+ self .assertEqual (self .signature (C ),
4208+ ((('b' , ..., ..., "positional_or_keyword" ),),
4209+ ...))
4210+
4211+ with self .subTest ('MethodType' ):
4212+ class A :
4213+ @identity_wrapper
4214+ def call (self , a ):
4215+ pass
4216+
4217+ class C :
4218+ __init__ = A ().call
4219+
4220+ C (1 ) # does not raise
4221+ self .assertEqual (self .signature (C ),
4222+ ((('a' , ..., ..., "positional_or_keyword" ),),
4223+ ...))
4224+
4225+ with self .subTest ('partial' ):
4226+ class C :
4227+ __init__ = functools .partial (identity_wrapper (lambda x , a , b : None ), 2 )
4228+
4229+ C (1 ) # does not raise
4230+ self .assertEqual (self .signature (C ),
4231+ ((('b' , ..., ..., "positional_or_keyword" ),),
4232+ ...))
4233+
4234+ with self .subTest ('partialmethod' ):
4235+ class C :
4236+ @identity_wrapper
4237+ def _init (self , x , a ):
4238+ self .a = (x , a )
4239+ __init__ = functools .partialmethod (_init , 2 )
4240+
4241+ self .assertEqual (C (1 ).a , (2 , 1 ))
4242+ self .assertEqual (self .signature (C ),
4243+ ((('a' , ..., ..., "positional_or_keyword" ),),
4244+ ...))
4245+
4246+ with self .subTest ('descriptor' ):
4247+ class C :
4248+ @custom_descriptor
4249+ @identity_wrapper
4250+ def __init__ (self , a ):
4251+ pass
4252+
4253+ C (1 ) # does not raise
4254+ self .assertEqual (self .signature (C ),
4255+ ((('a' , ..., ..., "positional_or_keyword" ),),
4256+ ...))
4257+ self .assertEqual (self .signature (C .__init__ ),
4258+ ((('self' , ..., ..., "positional_or_keyword" ),
4259+ ('a' , ..., ..., "positional_or_keyword" )),
4260+ ...))
4261+
4262+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4263+ varargs_signature )
4264+ self .assertEqual (self .signature (C .__new__ , follow_wrapped = False ),
4265+ varargs_signature )
4266+
4267+ def test_signature_on_class_with_wrapped_new (self ):
4268+ with self .subTest ('FunctionType' ):
4269+ class C :
4270+ @identity_wrapper
4271+ def __new__ (cls , a ):
4272+ return a
4273+
4274+ self .assertEqual (C (1 ), 1 )
4275+ self .assertEqual (self .signature (C ),
4276+ ((('a' , ..., ..., "positional_or_keyword" ),),
4277+ ...))
4278+
4279+ with self .subTest ('classmethod' ):
4280+ class C :
4281+ @classmethod
4282+ @identity_wrapper
4283+ def __new__ (cls , cls2 , a ):
4284+ return a
4285+
4286+ self .assertEqual (C (1 ), 1 )
4287+ self .assertEqual (self .signature (C ),
4288+ ((('a' , ..., ..., "positional_or_keyword" ),),
4289+ ...))
4290+
4291+ with self .subTest ('staticmethod' ):
4292+ class C :
4293+ @staticmethod
4294+ @identity_wrapper
4295+ def __new__ (cls , a ):
4296+ return a
4297+
4298+ self .assertEqual (C (1 ), 1 )
4299+ self .assertEqual (self .signature (C ),
4300+ ((('a' , ..., ..., "positional_or_keyword" ),),
4301+ ...))
4302+
4303+ with self .subTest ('MethodType' ):
4304+ class A :
4305+ @identity_wrapper
4306+ def call (self , cls , a ):
4307+ return a
4308+ class C :
4309+ __new__ = A ().call
4310+
4311+ self .assertEqual (C (1 ), 1 )
4312+ self .assertEqual (self .signature (C ),
4313+ ((('a' , ..., ..., "positional_or_keyword" ),),
4314+ ...))
4315+
4316+ with self .subTest ('partial' ):
4317+ class C :
4318+ __new__ = functools .partial (identity_wrapper (lambda x , cls , a : (x , a )), 2 )
4319+
4320+ self .assertEqual (C (1 ), (2 , 1 ))
4321+ self .assertEqual (self .signature (C ),
4322+ ((('a' , ..., ..., "positional_or_keyword" ),),
4323+ ...))
4324+
4325+ with self .subTest ('partialmethod' ):
4326+ class C :
4327+ __new__ = functools .partialmethod (identity_wrapper (lambda cls , x , a : (x , a )), 2 )
4328+
4329+ self .assertEqual (C (1 ), (2 , 1 ))
4330+ self .assertEqual (self .signature (C ),
4331+ ((('a' , ..., ..., "positional_or_keyword" ),),
4332+ ...))
4333+
4334+ with self .subTest ('descriptor' ):
4335+ class C :
4336+ @custom_descriptor
4337+ @identity_wrapper
4338+ def __new__ (cls , a ):
4339+ return a
4340+
4341+ self .assertEqual (C (1 ), 1 )
4342+ self .assertEqual (self .signature (C ),
4343+ ((('a' , ..., ..., "positional_or_keyword" ),),
4344+ ...))
4345+ self .assertEqual (self .signature (C .__new__ ),
4346+ ((('cls' , ..., ..., "positional_or_keyword" ),
4347+ ('a' , ..., ..., "positional_or_keyword" )),
4348+ ...))
41024349
4103- self .assertEqual (self .signature (Bar ), ((), ...))
4104- self .assertEqual (self .signature (Bar .__new__ ), varargs_signature )
4105- self .assertEqual (self .signature (Bar , follow_wrapped = False ),
4106- varargs_signature )
4107- self .assertEqual (self .signature (Bar .__new__ , follow_wrapped = False ),
4108- varargs_signature )
4350+ self .assertEqual (self .signature (C , follow_wrapped = False ),
4351+ varargs_signature )
4352+ self .assertEqual (self .signature (C .__new__ , follow_wrapped = False ),
4353+ varargs_signature )
41094354
41104355 def test_signature_on_class_with_init (self ):
41114356 class C :
0 commit comments