예제 #1
0
파일: tools.py 프로젝트: vic4key/asynq
    def decorator(fn):
        cache = LRUCache(maxsize)
        argspec = inspect2.getfullargspec(get_original_fn(fn))
        arg_names = argspec.args[1:] + argspec.kwonlyargs  # remove self
        async_fun = fn.asynq
        kwargs_defaults = get_kwargs_defaults(argspec)

        cache_key = key_fn
        if cache_key is None:

            def cache_key(args, kwargs):
                return get_args_tuple(args, kwargs, arg_names, kwargs_defaults)

        @asynq()
        @functools.wraps(fn)
        def wrapper(*args, **kwargs):
            key = cache_key(args, kwargs)
            try:
                result(cache[key])
                return
            except KeyError:
                value = yield async_fun(*args, **kwargs)
                cache[key] = value
                result(value)
                return

        return wrapper
예제 #2
0
def memoize(fun):
    """Memoizes return values of the decorated function.

    Similar to l0cache, but the cache persists for the duration of the process, unless clear_cache()
    is called on the function.

    """
    argspec = inspect2.getfullargspec(fun)
    arg_names = argspec.args + argspec.kwonlyargs
    kwargs_defaults = get_kwargs_defaults(argspec)

    def cache_key(args, kwargs):
        return get_args_tuple(args, kwargs, arg_names, kwargs_defaults)

    @functools.wraps(fun)
    def new_fun(*args, **kwargs):
        k = cache_key(args, kwargs)
        if k not in new_fun.__cache:
            new_fun.__cache[k] = fun(*args, **kwargs)
        return new_fun.__cache[k]

    def clear_cache():
        """Removes all cached values for this function."""
        new_fun.__cache.clear()

    new_fun.__cache = {}
    new_fun.clear_cache = clear_cache
    return new_fun
예제 #3
0
    def cache_fun(fun):
        argspec = inspect2.getfullargspec(fun)
        arg_names = argspec.args[1:] + argspec.kwonlyargs  # remove self
        kwargs_defaults = get_kwargs_defaults(argspec)
        cache = {}

        def cache_key(args, kwargs):
            return get_args_tuple(args, kwargs, arg_names, kwargs_defaults)

        def clear_cache(instance_key, ref):
            del cache[instance_key]

        @functools.wraps(fun)
        def new_fun(self, *args, **kwargs):
            instance_key = id(self)
            if instance_key not in cache:
                ref = weakref.ref(self,
                                  functools.partial(clear_cache, instance_key))
                cache[instance_key] = (ref, {})
            instance_cache = cache[instance_key][1]

            k = cache_key(args, kwargs)
            if k not in instance_cache:
                instance_cache[k] = fun(self, *args, **kwargs)
            return instance_cache[k]

        # just so unit tests can check that this is cleaned up correctly
        new_fun.__cached_per_instance_cache__ = cache
        return new_fun
예제 #4
0
파일: caching.py 프로젝트: jasonz1112/qcore
    def decorator(fn):
        cache = LRUCache(maxsize)
        argspec = inspect2.getfullargspec(fn)
        arg_names = argspec.args[1:] + argspec.kwonlyargs  # remove self
        kwargs_defaults = get_kwargs_defaults(argspec)

        cache_key = key_fn
        if cache_key is None:

            def cache_key(args, kwargs):
                return get_args_tuple(args, kwargs, arg_names, kwargs_defaults)

        @functools.wraps(fn)
        def wrapper(*args, **kwargs):
            key = cache_key(args, kwargs)
            try:
                return cache[key]
            except KeyError:
                value = fn(*args, **kwargs)
                cache[key] = value
                return value

        wrapper.clear = cache.clear

        return wrapper
예제 #5
0
파일: tools.py 프로젝트: vic4key/asynq
    def decorator(fun):
        _keygetter = keygetter
        if _keygetter is None:
            original_fn = get_original_fn(fun)
            argspec = inspect2.getfullargspec(original_fn)
            arg_names = argspec.args + argspec.kwonlyargs
            kwargs_defaults = get_kwargs_defaults(argspec)
            _keygetter = lambda args, kwargs: get_args_tuple(
                args, kwargs, arg_names, kwargs_defaults)

        return decorate(DeduplicateDecorator, fun.task_cls, _keygetter)(fun)
예제 #6
0
    def cache_fun(fun):
        argspec = inspect2.getfullargspec(fun)
        arg_names = argspec.args + argspec.kwonlyargs
        kwargs_defaults = get_kwargs_defaults(argspec)

        def cache_key(args, kwargs):
            return repr(
                get_args_tuple(args, kwargs, arg_names, kwargs_defaults))

        @functools.wraps(fun)
        def new_fun(*args, **kwargs):
            k = cache_key(args, kwargs)
            current_time = int(time.time())

            # k is not in the cache; perform the function and cache the result.
            if k not in new_fun.__cache or k not in new_fun.__cache_times:
                new_fun.__cache[k] = fun(*args, **kwargs)
                new_fun.__cache_times[k] = current_time
                return new_fun.__cache[k]

            # k is in the cache at this point. Check if the ttl has expired;
            # if so, recompute the value and cache it.
            cache_time = new_fun.__cache_times[k]
            if current_time - cache_time > ttl_secs:
                new_fun.__cache[k] = fun(*args, **kwargs)
                new_fun.__cache_times[k] = current_time

            # finally, return the cached result.
            return new_fun.__cache[k]

        def clear_cache():
            """Removes all cached values for this function."""
            new_fun.__cache.clear()
            new_fun.__cache_times.clear()

        def dirty(*args, **kwargs):
            """Dirties the function for a given set of arguments."""
            k = cache_key(args, kwargs)
            new_fun.__cache.pop(k, None)
            new_fun.__cache_times.pop(k, None)

        new_fun.__cache = {}
        new_fun.__cache_times = {}
        new_fun.clear_cache = clear_cache
        new_fun.dirty = dirty
        return new_fun
예제 #7
0
    def key(self, args=None):
        """
        Returns the key that will uniquely identify
        a function even when it is overloaded

        :param args: the function
        :return: tuple of function specs
        """

        if args is None:
            args = getfullargspec(self.fn).args

        return tuple([
            self.fn.__module__,
            self.fn.__class__,
            self.fn.__name__,
            len(args or []),
        ])
예제 #8
0
파일: tools.py 프로젝트: saipanindra/asynq
    def cache_fun(fun):
        argspec = inspect2.getfullargspec(get_original_fn(fun))
        arg_names = argspec.args[1:] + argspec.kwonlyargs  # remove self
        async_fun = fun.asynq
        kwargs_defaults = get_kwargs_defaults(argspec)
        cache = {}

        def cache_key(args, kwargs):
            return get_args_tuple(args, kwargs, arg_names, kwargs_defaults)

        def clear_cache(instance_key, ref):
            del cache[instance_key]

        @async_proxy()
        @functools.wraps(fun)
        def new_fun(self, *args, **kwargs):
            instance_key = id(self)
            if instance_key not in cache:
                ref = weakref.ref(self,
                                  functools.partial(clear_cache, instance_key))
                cache[instance_key] = (ref, {})
            instance_cache = cache[instance_key][1]

            k = cache_key(args, kwargs)
            try:
                return ConstFuture(instance_cache[k])
            except KeyError:

                def callback(task):
                    instance_cache[k] = task.value()

                task = async_fun(self, *args, **kwargs)
                task.on_computed.subscribe(callback)
                return task

        # just so unit tests can check that this is cleaned up correctly
        new_fun.__acached_per_instance_cache__ = cache
        return new_fun
예제 #9
0
파일: tools.py 프로젝트: vic4key/asynq
    def cache_fun(fun):
        argspec = inspect2.getfullargspec(get_original_fn(fun))
        arg_names = argspec.args[1:] + argspec.kwonlyargs  # remove self
        async_fun = fun.asynq
        kwargs_defaults = get_kwargs_defaults(argspec)
        cache = {}

        def cache_key(args, kwargs):
            return get_args_tuple(args, kwargs, arg_names, kwargs_defaults)

        def clear_cache(instance_key, ref):
            del cache[instance_key]

        @asynq()
        @functools.wraps(fun)
        def new_fun(self, *args, **kwargs):
            instance_key = id(self)
            if instance_key not in cache:
                ref = weakref.ref(self,
                                  functools.partial(clear_cache, instance_key))
                cache[instance_key] = (ref, {})
            instance_cache = cache[instance_key][1]

            k = cache_key(args, kwargs)
            try:
                result(instance_cache[k])
                return
            except KeyError:
                value = yield async_fun(self, *args, **kwargs)
                instance_cache[k] = value
                result(value)
                return

        # just so unit tests can check that this is cleaned up correctly
        new_fun.__acached_per_instance_cache__ = cache
        return new_fun