From 20f9485b5e9c13b0860f68cd71bb406a9fdea778 Mon Sep 17 00:00:00 2001 From: Mike Orlov Date: Thu, 16 Apr 2020 17:48:02 +0300 Subject: [PATCH] code objects analysis replaced with inspect --- aiocache/decorators.py | 14 ++++++-------- tests/acceptance/test_decorators.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/aiocache/decorators.py b/aiocache/decorators.py index 9b87e6c7..4663424e 100644 --- a/aiocache/decorators.py +++ b/aiocache/decorators.py @@ -207,13 +207,11 @@ def _get_cache(cache=Cache.MEMORY, serializer=None, plugins=None, **cache_kwargs def _get_args_dict(func, args, kwargs): - defaults = { - arg_name: arg.default - for arg_name, arg in inspect.signature(func).parameters.items() - if arg.default is not inspect._empty # TODO: bug prone.. - } - args_names = func.__code__.co_varnames[: func.__code__.co_argcount] - return {**defaults, **dict(zip(args_names, args)), **kwargs} + signature = inspect.signature(func) + incoming_args = signature.bind(*args, **kwargs) + incoming_args.apply_defaults() + incoming_args = dict(incoming_args.arguments) + return incoming_args class multi_cached: @@ -341,7 +339,7 @@ def get_cache_keys(self, f, args, kwargs): keys = args_dict[self.keys_from_attr] or [] keys = [self.key_builder(key, f, *args, **kwargs) for key in keys] - args_names = f.__code__.co_varnames[: f.__code__.co_argcount] + args_names = list(inspect.signature(f).parameters.keys()) new_args = list(args) keys_index = -1 if self.keys_from_attr in args_names and self.keys_from_attr not in kwargs: diff --git a/tests/acceptance/test_decorators.py b/tests/acceptance/test_decorators.py index 188ab12b..18800d5e 100644 --- a/tests/acceptance/test_decorators.py +++ b/tests/acceptance/test_decorators.py @@ -1,4 +1,6 @@ import asyncio +import functools + import pytest import random @@ -157,3 +159,20 @@ async def fn(keys): await fn([pytest.KEY]) assert await cache.exists(pytest.KEY) is True + + @pytest.mark.asyncio + async def test_decorator_over_decorator(self, cache): + def dummy_d(fn): + @functools.wraps(fn) + async def wrapper(*args, **kwargs): + return await fn(*args, **kwargs) + + return wrapper + + @multi_cached("keys") + @dummy_d + async def fn(keys): + return {pytest.KEY: 1} + + await fn([pytest.KEY]) + assert await cache.exists(pytest.KEY) is True