[python] Class method decorator with self arguments?

I know this is an old question, but this solution has not been mentioned yet, hopefully it may help someone even today, after 8 years.

So, what about wrapping a wrapper? Let's assume one cannot change the decorator neither decorate those methods in init (they may be @property decorated or whatever). There is always a possibility to create custom, class-specific decorator that will capture self and subsequently call the original decorator, passing runtime attribute to it.

Here is a working example (f-strings require python 3.6):

import functools

# imagine this is at some different place and cannot be changed
def check_authorization(some_attr, url):
        def decorator(func):
                @functools.wraps(func)
                def wrapper(*args, **kwargs):
                        print(f"checking authorization for '{url}'...")
                        return func(*args, **kwargs)
                return wrapper
        return decorator

# another dummy function to make the example work
def do_work():
        print("work is done...")

###################
# wrapped wrapper #
###################
def custom_check_authorization(some_attr):
        def decorator(func):
                # assuming this will be used only on this particular class
                @functools.wraps(func)
                def wrapper(self, *args, **kwargs):
                        # get url
                        url = self.url
                        # decorate function with original decorator, pass url
                        return check_authorization(some_attr, url)(func)(self, *args, **kwargs)
                return wrapper
        return decorator
        
#############################
# original example, updated #
#############################
class Client(object):
        def __init__(self, url):
                self.url = url
    
        @custom_check_authorization("some_attr")
        def get(self):
                do_work()

# create object
client = Client(r"https://stackoverflow.com/questions/11731136/class-method-decorator-with-self-arguments")

# call decorated function
client.get()

output:

checking authorisation for 'https://stackoverflow.com/questions/11731136/class-method-decorator-with-self-arguments'...
work is done...