Search code examples
pythondecoratorintrospection

Passing a python class constant to a decorator without self


I'm using the python ratelimit library and it uses a decorator to handle rate limiting of a function. I have a class constant I'd like to pass into the decorator but of course self wont work.

Is there a way to reference the UNIVERSALIS_MAX_CALLS_PER_SECOND constant within the decorator? Or, is there a clean, more appropriate way I should handle this?

Edit: I'm seeking to avoid globals. What I was hoping for was some python introspection maybe?

class Universalis():
    # FIXME: hard-coded North America
    API_ENDPOINT = "http://universalis.app/api/v2/North-America/"
    UNIVERSALIS_MAX_CALLS_PER_SECOND = 13 # 25 max
    UNIVERSALIS_MAX_CONNECTIONS = 6 # 8 max
    LISTINGS_PER_API_CALL = 500 # Universalis no max.

    @sleep_and_retry
    @limits(calls=self.UNIVERSALIS_MAX_CALLS_PER_SECOND, period=1)
    def fetch_and_process_item_listings(self, item_ids_querystring):
        # magic...

Solution

  • At the time limit is called, you have access to the name as an ordinary variable. Just drop the self..

    class Universalis:
        API_ENDPOINT = "http://universalis.app/api/v2/North-America/"
        UNIVERSALIS_MAX_CALLS_PER_SECOND = 13
        UNIVERSALIS_MAX_CONNECTIONS = 6
        LISTINGS_PER_API_CALL = 500
    
        @sleep_and_retry
        @limits(calls=UNIVERSALIS_MAX_CALLS_PER_SECOND, period=1)
        def fetch_and_process_item_listings(self, item_ids_querystring):
            # magic...
    

    Here's a simple example that shows the "class attribute" used as a regular variable.

    def d(n):
        print(n)
        def _(f):
            return f
        return _
    
    
    class Foo:
        X = 5
        @d(X)
        def method(self):
            pass
    

    When foo is defined, the decorator will print the value of Foo.X to standard output, since n receives the value of the variable X that will be used to define the class attribute.