0

I have problem solving this question, I have the following class:

class test:

    @auth
    def method1(self, x):
        return x

    @auth
    def method2(self, x, y):
        return x+y

    def method3(self, z):
        return z

I applied the decorator in both methods, follow:

class auth:

    def __init__(self, f):
        self.f = f

    def __call__(self, *args, **kwargs):
        self.f(*args, **kwargs)

So far no problem, however I need (NEED) to use the following code:

def run():
    klass = globals()["test"]()

    method1 = getattr(klass, "method1")
    print(method1.__code__.co_varnames)
    # should print (self, x)

    method2 = getattr(klass, "method2")
    print(method2.__code__.co_varnames)
    # should print (self, x, y)

    method3 = getattr(klass, "method3")
    print(method3.__code__.co_varnames)
    # i get (self, z) < without decorator

But I get now:

 AttributeError: 'auth' object has no attribute '__code__'

What makes sense if we think that the signature of method "method1 and method2" is now "auth".

So how do I get the arguments with or without decorators. I started reading about the "inspect" but there are many reports about being slow.

Jonny
  • 408
  • 4
  • 12
  • You could use something like `method1.f.__code__.co_varnames`. But in general the code that you "need" to use is going to need to be aware of/cooperative with the decorator code (i.e., it needs to know where to look to find the function arguments). – BrenBarn Jun 12 '17 at 19:03

2 Answers2

1

The "original" method is stored in the f attribute of the auth object. Instead of method1.__code__.co_varnames use method1.f.__code__.co_varnames

Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
  • love you bro! it's possible to know if a method has decorator or not ? (just a small question) – Jonny Jun 12 '17 at 19:01
  • I'm not sure, but [this](https://stackoverflow.com/questions/19314405/how-to-detect-is-decorator-has-been-applied-to-method-or-function) might be somewhere to start – Patrick Haugh Jun 12 '17 at 19:04
  • thanks, i can use __code__ != None instead inspect.getargspec like the link, but anyway thanks man. – Jonny Jun 12 '17 at 19:06
1

Annotations just contain an object and are not the object itsself, it is an object of class auth and not function. To access the function itsself, you can write methodN.f.__code__.co_varnames or assign a copy of the __dict__ object of the function to the auth-object in __init__ itsself.

class auth:

    def __init__(self, f):
        self.__dict__.update(f.__dict__)
        # now the initialisations
        self.f = f

    def __call__(self, *args, **kwargs):
        self.f(*args, **kwargs)

Edit: You should initialize the members/call super after updating the dict, because f could be overriden by the update, eg. you define another decorator-class and it has also a member f.

cmdLP
  • 1,658
  • 9
  • 19