X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=decorator_utils.py;h=76faec6f7be2e8d52f3ed9c7e05e1dc6048d666b;hb=b10d30a46e601c9ee1f843241f2d69a1f90f7a94;hp=03e7c880433fad5d359a2bb3acc29a4266204e65;hpb=e0973abee4c917127169795a56fd9c5c5412913c;p=python_utils.git diff --git a/decorator_utils.py b/decorator_utils.py index 03e7c88..76faec6 100644 --- a/decorator_utils.py +++ b/decorator_utils.py @@ -5,6 +5,7 @@ import datetime import enum import functools +import inspect import logging import math import multiprocessing @@ -17,8 +18,10 @@ import traceback from typing import Callable, Optional import warnings +# This module is commonly used by others in here and should avoid +# taking any unnecessary dependencies back on them. import exceptions -import thread_utils + logger = logging.getLogger(__name__) @@ -189,7 +192,7 @@ def retry_predicate( tries: int, *, predicate: Callable[..., bool], - delay_sec: float = 3, + delay_sec: float = 3.0, backoff: float = 2.0, ): """Retries a function or method up to a certain number of times @@ -199,10 +202,10 @@ def retry_predicate( delay_sec sets the initial delay period in seconds. backoff is a multiplied (must be >1) used to modify the delay. predicate is a function that will be passed the retval of the - decorated function and must return True to stop or False to - retry. + decorated function and must return True to stop or False to + retry. """ - if backoff < 1: + if backoff < 1.0: msg = f"backoff must be greater than or equal to 1, got {backoff}" logger.critical(msg) raise ValueError(msg) @@ -222,9 +225,11 @@ def retry_predicate( @functools.wraps(f) def f_retry(*args, **kwargs): mtries, mdelay = tries, delay_sec # make mutable + logger.debug(f'deco_retry: will make up to {mtries} attempts...') retval = f(*args, **kwargs) while mtries > 0: if predicate(retval) is True: + logger.debug('Predicate succeeded, deco_retry is done.') return retval logger.debug("Predicate failed, sleeping and retrying.") mtries -= 1 @@ -335,7 +340,7 @@ def _target(queue, function, *args, **kwargs): """ try: queue.put((True, function(*args, **kwargs))) - except: + except Exception: queue.put((False, sys.exc_info()[1])) @@ -426,6 +431,7 @@ def timeout( parameter. The function is wrapped and returned to the caller. """ if use_signals is None: + import thread_utils use_signals = thread_utils.is_current_thread_main_thread() def decorate(function): @@ -517,3 +523,19 @@ def call_with_sample_rate(sample_rate: float) -> Callable: ) return _call_with_sample_rate return decorator + + +def decorate_matching_methods_with(decorator, acl=None): + """Apply decorator to all methods in a class whose names begin with + prefix. If prefix is None (default), decorate all methods in the + class. + """ + def decorate_the_class(cls): + for name, m in inspect.getmembers(cls, inspect.isfunction): + if acl is None: + setattr(cls, name, decorator(m)) + else: + if acl(name): + setattr(cls, name, decorator(m)) + return cls + return decorate_the_class