@@ -515,7 +515,9 @@ def decorate(
515515 user_function : Optional [CallableTV ] = None ,
516516 / ,
517517 serializer : Optional [SerializerSetterValueT ] = None ,
518- ** keywords ,
518+ ignore_positional_args : Optional [Sequence [int ]] = None ,
519+ ignore_keyword_args : Optional [Sequence [str ]] = None ,
520+ ** options ,
519521 ) -> CallableTV :
520522 """Decorate the given function with caching.
521523
@@ -524,9 +526,22 @@ def decorate(
524526
525527 serializer: serialize/deserialize name or function pair for return value of what decorated.
526528
527- If defined, it overrides the first element of :attr:`serializer`.
529+ It accepts either:
530+ - A string key mapping to predefined serializers (like "yaml" or "json")
531+ - A tuple of (`serialize_func`, `deserialize_func`) functions
532+
533+ If defined, it overrides the :attr:`serializer` property of the cache instance.
534+
535+
536+ ignore_positional_args: A list of positional argument indices to exclude from cache key generation.
537+
538+ These arguments will be filtered out before cache operations.
528539
529- **keywords: Additional options passed to :meth:`exec`, they will encoded to json, then pass to redis lua script.
540+ ignore_keyword_args: A list of keyword argument names to exclude from cache key generation.
541+
542+ These parameters will be filtered out before cache operations.
543+
544+ **options: Additional options passed to :meth:`exec`, they will encoded to json, then pass to redis lua script.
530545
531546 This method is equivalent to :attr:`__call__`.
532547
@@ -585,25 +600,44 @@ def my_func(a, b):
585600 elif serializer is not None :
586601 serialize_func , deserialize_func = serializer
587602
588- def decorator (f : CallableTV ):
589- @wraps (f )
590- def wrapper (* args , ** kwargs ):
591- return self .exec (f , args , kwargs , serialize_func , deserialize_func , ** keywords )
592-
593- @wraps (f )
594- async def awrapper (* args , ** kwargs ):
595- return await self .aexec (f , args , kwargs , serialize_func , deserialize_func , ** keywords )
596-
597- if not callable (f ):
603+ if ignore_positional_args is None :
604+ ignore_positional_args = []
605+ if ignore_keyword_args is None :
606+ ignore_keyword_args = []
607+
608+ def decorator (user_func : CallableTV ):
609+ @wraps (user_func )
610+ def wrapper (* user_args , ** user_kwargs ):
611+ return self .exec (
612+ user_func ,
613+ [x for i , x in enumerate (user_args ) if i not in ignore_positional_args ],
614+ {k : v for k , v in user_kwargs .items () if k not in ignore_keyword_args },
615+ serialize_func ,
616+ deserialize_func ,
617+ ** options ,
618+ )
619+
620+ @wraps (user_func )
621+ async def awrapper (* user_args , ** user_kwargs ):
622+ return await self .aexec (
623+ user_func ,
624+ [x for i , x in enumerate (user_args ) if i not in ignore_positional_args ],
625+ {k : v for k , v in user_kwargs .items () if k not in ignore_keyword_args },
626+ serialize_func ,
627+ deserialize_func ,
628+ ** options ,
629+ )
630+
631+ if not callable (user_func ):
598632 raise TypeError ("Can not decorate a non-callable object." )
599633 if self .asynchronous :
600- if not iscoroutinefunction (f ):
634+ if not iscoroutinefunction (user_func ):
601635 raise TypeError (
602636 "The decorated function or method must be a coroutine when using an asynchronous redis client."
603637 )
604638 return cast (CallableTV , awrapper )
605639 else :
606- if iscoroutinefunction (f ):
640+ if iscoroutinefunction (user_func ):
607641 raise TypeError (
608642 "The decorated function or method cannot be a coroutine when using a asynchronous redis client."
609643 )
0 commit comments