Python `cache` decorator only when DEBUG is False

Viewed 17

I am trying to make a decorator that when DEBUG == True, it does not cache, but when DEBUG == False, then it does cache.

This is what I came up with. It works in the case when DEBUG == False. The issue is when DEBUG == True:

from functools import lru_cache

DEBUG = True

def prod_lru_cache(*args, **kwargs):
    def no_decorator(func):
        return func

    if DEBUG:
        return no_decorator
    else:
        return prod_lru_cache(*args, **kwargs)

The issue is that lru_cache can take an optional argument maxsize.

If it takes no arguments, then I think the above is fine, e.g. We get back the original function as required when DEBUG == False:

DEBUG = False

@prod_lru_cache
def foo():
   print('foo')

# prod_lru_cache(foo) -> (return no_decorator) -> (return foo) -> foo

However if it does take an argument, then it does no work:

DEBUG = False

@prod_lru_cache(maxsize=7)
def foo():
   print('foo')

# prod_lru_cache(maxsize=7)(foo) -> (return no_decorator)(foo) -> (foo)foo -> ????

How does one handle both scenarios? I can't think of a way to distinguish between the passed in user function, and an arg (which in some cases could be a callable), in this example it should always be an int, but I would like to apply the same concept to other decorators.

A hack solution I came up with is:

def prod_cache(*args, **kwargs):
    def no_decorator(f):
        return f

    if settings.DEBUG:
        return args[0] if args and callable(args[0]) else no_decorator
    else:
        return cache(*args, **kwargs)

But it is not generic in that what if I wish to make a decorator with an arg that is a callable, then I can't apply the same logic.

0 Answers
Related