class-based class decorator

Albert-Jan Roskam fomcl at yahoo.com
Tue Jan 13 03:25:32 EST 2015





----- Original Message -----
> From: Jean-Michel Pichavant <jeanmichel at sequans.com>
> To: Albert-Jan Roskam <fomcl at yahoo.com>
> Cc: Python <python-list at python.org>
> Sent: Monday, January 12, 2015 4:20 PM
> Subject: Re: class-based class decorator
> 
> ----- Original Message -----
>>  From: "Albert-Jan Roskam" <fomcl at yahoo.com.dmarc.invalid>
> 
>>  import functools
>>  import inspect
>>  import warnings
>> 
>>  warnings.simplefilter("always")
>> 
>>  class check_deprecated_args(object):
>> 
>>      def __init__(self, deprecated_params, msg=None):
>>          self.deprecated_params = deprecated_params
>>          self.msg = msg
>> 
>>      def __call__(self, func):
>>          @functools.wraps(func)
>>          def inner(*args, **kwargs):
>>              argspec = inspect.getargspec(func)
>>              default_signature = dict(zip(argspec.args[1:],
>>              argspec.defaults))
>>              callargs = inspect.getcallargs(func, *args, **kwargs)
>>              deprecated_calls = [(p, a) for p, a in callargs.items()
>>              if
>>                                   p in self.deprecated_params and
>>                                   a != default_signature[p]]
>>              for (param, arg) in deprecated_calls:
>>                  msg = "you're using obsolete parameters in %s:
>>                  [%s:%s]"
>>                  msg = msg % (func.__name__, param, arg)
>>                  msg = msg + " " + self.msg if self.msg else msg
>>                  warnings.warn(msg, DeprecationWarning, stacklevel=2)
>>              return func(*args, **kwargs)
>>          functools.update_wrapper(inner, func)
>>          return inner
>> 
>>  if __name__ == "__main__":
>>      class Foo(object):
>> 
>>          @check_deprecated_args(["old", "older"], 
> "use 'brand_new'
>>          param instead")
>>          def __init__(self, old="old", older="ancient"):
>>              print "hello"
>> 
>>          @check_deprecated_args(deprecated_params=["old", 
> "older"])
>>          def bar(self, old="default"):
>>              print "world"
>> 
>>      f = Foo(old="old", older="dino era")
>>      f.bar("gnarly")
>> 
>>      help(f)  # now the signature is *args, **kwargs, which makes my
>>      Sphinx documentation less readable!
>> 
>>  Best wishes,
>>  Albert-Jan
> 
> I don't really understand how you successfuly manage positional parameters, 
> since the caller may not name them.
> I'm asking because if your intend to check only the keyword parameters, 
> there's a much simplier solution.
> 
> JM


Hi,

Can you give an example of where/how my code would fail? I do not intend to use *args and **kwargs, if that is what you mean. I am interested in hearing a simpler approach, especially if it would also solve the messed-up-signature problem that I mentioned.

Thank you!

Albert-Jan



More information about the Python-list mailing list