Doubledown
Doubledown

Reputation: 468

Python decorator that dynamically sets cache based on function parameter

I am currently using pyfscache to create a cache in a custom directory and limit the length of storage. Here is my current code:

Import pyfscache
Import pandas as pd

def cache_one_day(func):
    years = 0
    days = 1
    cache = pyfscache.FSCache(CACHE_DIRECTORY, years=years, days=1)
    return cache(func)

@cache_one_day
def get_data(year):
    columns = [str(year), str(year + 1), str(year + 2)]
    data = [1, 2, 3]
    df = pd.DataFrame(data, columns=columns)
    return df

I would additionally like to change the cache time limit based on the year parameter for get_data. So for example, if the year is 2017 I want to refresh the data often and set the days = 1 (as shown). But if the year is 2015, I already know the data will not change and I'd prefer to create an archive where the years = 99.

I know I can write an if statement in the get_data function but this isn't the only function I want to use this logic on. Therefore, I'd rather use something else. I already looked into class decorators and tiered decorators and tried to write each, but I get errors. For example, this code:

class my_decorator(object):

    def __init__(self, view_func):
        self._years = 0
        self._seconds = 0
        self.view_func = view_func
        wraps(view_func)(self)

    def __call__(self, request, *args, **kwargs):
        if request == 2017:
            self._seconds = 1
        else:
            self._years = 1
        cache = pyfscache.FSCache(CACHE_DIRECTORY, years=self._years,
                                  seconds=self._seconds)
        return cache(self.view_func(request, *args, **kwargs))

returns 'DataFrame' object has no attribute 'name'

Any guidance?

Upvotes: 1

Views: 874

Answers (1)

Maurice Meyer
Maurice Meyer

Reputation: 18136

You could use a wrapper function in your decorator function to split function and arguments:

def cache_one_day(fn):
    def wrapper(*args, **kw):
        # args[0] --> years (2017)
        # cache =  ...
        return fn(*args,**kw)
    return wrapper

@cache_one_day
def get_data(year):
    columns = [str(year), str(year + 1), str(year + 2)]
    data = [1, 2, 3]
    df = pd.DataFrame(data, columns=columns)
    return df

get_data(2017)

Upvotes: 1

Related Questions