def wraps(wrapped): """A functools.wraps helper that handles partial objects on Python 2.""" # https://github.com/google/pytype/issues/322 if isinstance(wrapped, functools.partial): # pytype: disable=wrong-arg-types return six.wraps(wrapped, assigned=_PARTIAL_VALID_ASSIGNMENTS) else: return six.wraps(wrapped)
def _wraps(wrapped): """ A helper that handles functions not having all attributes in Python 2. """ if isinstance(wrapped, functools.partial) or not hasattr(wrapped, "__name__"): return six.wraps(wrapped, assigned=_SAFE_VALID_ASSIGNMENTS) else: return six.wraps(wrapped)
def test_wraps_raises_on_missing_updated_field_on_wrapper(): """Ensure six.wraps doesn't ignore missing attrs wrapper. Because that's what happens in Py3's functools.update_wrapper. """ def wrapped(): pass def wrapper(): pass with pytest.raises(AttributeError, match='has no attribute.*xyzzy'): six.wraps(wrapped, [], ['xyzzy'])(wrapper)
def lazy_wrapper(init): def lazy_init(*args, **kwargs): self = args[0] self.allocation_args = (getattr(self, 'allocation_args', []) + allocation) self.initialization_args = (getattr(self, 'initialization_args', []) + initialization) kwargs = dict_union(args_to_kwargs(args, init), kwargs) for allocation_arg in allocation: kwargs.setdefault(allocation_arg, NoneAllocation) for initialization_arg in initialization: kwargs.setdefault(initialization_arg, NoneInitialization) return init(**kwargs) wraps(init)(lazy_init) return lazy_init
def inner(f): def wrapped(*args, **kw): try: return f(*args, **kw) except Exception as e: # Save exception since it can be clobbered during processing # below before we can re-raise exc_info = sys.exc_info() if notifier: payload = dict(args=args, exception=e) payload.update(kw) # Use a temp vars so we don't shadow # our outer definitions. temp_level = level if not temp_level: temp_level = notifier.ERROR temp_type = event_type if not temp_type: # If f has multiple decorators, they must use # six.wraps to ensure the name is # propagated. temp_type = f.__name__ notifier.notify(publisher_id, temp_type, temp_level, payload) # re-raise original exception since it may have been clobbered raise exc_info[0], exc_info[1], exc_info[2] return six.wraps(f)(wrapped)
def inner(f): def wrapped(self, context, *args, **kw): # Don't store self or context in the payload, it now seems to # contain confidential information. try: return f(self, context, *args, **kw) except Exception as e: with excutils.save_and_reraise_exception(): if notifier or get_notifier: payload = dict(exception=e) call_dict = safe_utils.getcallargs(f, context, *args, **kw) cleansed = _cleanse_dict(call_dict) payload.update({'args': cleansed}) # If f has multiple decorators, they must use # six.wraps to ensure the name is # propagated. event_type = f.__name__ (notifier or get_notifier()).error(context, event_type, payload) return six.wraps(f)(wrapped)
def f(g, assign, update): def w(): return 42 w.glue = {"foo": "bar"} w.xyzzy = {"qux": "quux"} return six.wraps(g, assign, update)(w)
def inner(f): def wrapped(*args, **kw): try: return f(*args, **kw) except Exception as e: # Save exception since it can be clobbered during processing # below before we can re-raise exc_info = sys.exc_info() if notifier: payload = dict(args=args, exception=e) payload.update(kw) # Use a temp vars so we don't shadow # our outer definitions. temp_level = level if not temp_level: temp_level = notifier.ERROR temp_type = event_type if not temp_type: # If f has multiple decorators, they must use # six.wraps to ensure the name is # propagated. temp_type = f.__name__ notifier.notify(publisher_id, temp_type, temp_level, payload) # re-raise original exception since it may have been clobbered raise_(exc_info[0], exc_info[1], exc_info[2]) return six.wraps(f)(wrapped)
def optimizer_decorator(func): decorated_func = func ########################### jit Optimisation ################################# if jit_type and jit_type.lower() == "numba": decorated_func = numba_jit(**jit_config)(decorated_func) ########################### Cache Optimisation ################################# if cache_type and cache_type.lower() == "hermes": decorated_func = hermescache(**cache_config)(decorated_func) decorated_func.__defaults__ = func.__defaults__ # Hermes omits __defaults__ in resulting Cached fn object ########################### Optimisation Profiling ################################# if profile_type and profile_type.lower() == "time": def timeProfile_decorater(infunc): def timeProfiler(*args,**kwargs): start_time = time.time() return_val = infunc(*args, **kwargs) end_time = time.time() logger.info("{} : Excecution wall time : {}".format(func.__name__,(end_time-start_time))) return return_val return timeProfiler decorated_func = timeProfile_decorater(decorated_func) if decorated_func != func: decorated_func = wraps(func)(decorated_func) return decorated_func
def inner(f): def wrapped(self, context, *args, **kw): # Don't store self or context in the payload, it now seems to # contain confidential information. try: return f(self, context, *args, **kw) except Exception as e: with excutils.save_and_reraise_exception(): if notifier or get_notifier: payload = dict(exception=e) call_dict = inspect.getcallargs(f, self, context, *args, **kw) cleansed = _cleanse_dict(call_dict) payload.update({'args': cleansed}) # If f has multiple decorators, they must use # six.wraps to ensure the name is # propagated. event_type = f.__name__ (notifier or get_notifier()).error(context, event_type, payload) return six.wraps(f)(wrapped)
def command_aware_wraps(f): """ Decorator passing the command attribute of the wrapped function to the wrapper This needs to be used by decorators that are trying to wrap clicmd decorated command functions. """ additional = () if hasattr(f, 'command'): additional = ('command', ) return six.wraps(f, assigned=functools.WRAPPER_ASSIGNMENTS + additional)
def __call__(self, func): self.name = self.name if self.name else func.__name__ def _wrapper(*args, **kwargs): self._start() try: func_return = func(*args, **kwargs) finally: self._finish() return func_return return wraps(func)(_wrapper)
def wraps(fn): """Do the same as six.wraps but only copy attributes that exist. For example, object instances don't have __name__ attribute, so six.wraps fails. This is fixed in Python 3 (https://bugs.python.org/issue3445), but didn't get backported to six. Also, see https://github.com/benjaminp/six/issues/250. """ def filter_hasattr(obj, attrs): return tuple(a for a in attrs if hasattr(obj, a)) return six.wraps( fn, assigned=filter_hasattr(fn, WRAPPER_ASSIGNMENTS), updated=filter_hasattr(fn, WRAPPER_UPDATES))
def with_color(func): """Decorator which adds --color option if available.""" if pygments is None: def decorator(*args, **kwargs): kwargs["color"] = None return func(*args, **kwargs) else: decorator = click.option( "--color", default=None, type=click.Choice(["light", "dark"]), help=("Colorize output. By default no color is used. " "Parameter means colorscheme of the terminal"))(func) decorator = six.wraps(func)(decorator) return decorator
def wrap_method( func, default_retry=None, default_timeout=None, metadata=USE_DEFAULT_METADATA): """Wrap an RPC method with common behavior. This applies common error wrapping, retry, and timeout behavior a function. The wrapped function will take optional ``retry`` and ``timeout`` arguments. For example:: import google.api.core.gapic_v1.method from google.api.core import retry from google.api.core import timeout # The original RPC method. def get_topic(name, timeout=None): request = publisher_v2.GetTopicRequest(name=name) return publisher_stub.GetTopic(request, timeout=timeout) default_retry = retry.Retry(deadline=60) default_timeout = timeout.Timeout(deadline=60) wrapped_get_topic = google.api.core.gapic_v1.method.wrap_method( get_topic, default_retry) # Execute get_topic with default retry and timeout: response = wrapped_get_topic() # Execute get_topic without doing any retying but with the default # timeout: response = wrapped_get_topic(retry=None) # Execute get_topic but only retry on 5xx errors: my_retry = retry.Retry(retry.if_exception_type( exceptions.InternalServerError)) response = wrapped_get_topic(retry=my_retry) The way this works is by late-wrapping the given function with the retry and timeout decorators. Essentially, when ``wrapped_get_topic()`` is called: * ``get_topic()`` is first wrapped with the ``timeout`` into ``get_topic_with_timeout``. * ``get_topic_with_timeout`` is wrapped with the ``retry`` into ``get_topic_with_timeout_and_retry()``. * The final ``get_topic_with_timeout_and_retry`` is called passing through the ``args`` and ``kwargs``. The callstack is therefore:: method.__call__() -> Retry.__call__() -> Timeout.__call__() -> wrap_errors() -> get_topic() Note that if ``timeout`` or ``retry`` is ``None``, then they are not applied to the function. For example, ``wrapped_get_topic(timeout=None, retry=None)`` is more or less equivalent to just calling ``get_topic`` but with error re-mapping. Args: func (Callable[Any]): The function to wrap. It should accept an optional ``timeout`` argument. If ``metadata`` is not ``None``, it should accept a ``metadata`` argument. default_retry (Optional[google.api.core.Retry]): The default retry strategy. If ``None``, the method will not retry by default. default_timeout (Optional[google.api.core.Timeout]): The default timeout strategy. Can also be specified as an int or float. If ``None``, the method will not have timeout specified by default. metadata (Optional(Mapping[str, str])): A dict of metadata keys and values. This will be augmented with common ``x-google-api-client`` metadata. If ``None``, metadata will not be passed to the function at all, if :attr:`USE_DEFAULT_METADATA` (the default) then only the common metadata will be provided. Returns: Callable: A new callable that takes optional ``retry`` and ``timeout`` arguments and applies the common error mapping, retry, timeout, and metadata behavior to the low-level RPC method. """ func = grpc_helpers.wrap_errors(func) if metadata is USE_DEFAULT_METADATA: metadata = {} if metadata is not None: metadata = _prepare_metadata(metadata) return six.wraps(func)( _GapicCallable(func, default_retry, default_timeout, metadata))
def f(g, assign, update): def w(): return 42 w.glue = {'foo': 'bar'} return six.wraps(g, assign, update)(w)
def wraps(wrapped): """A functools.wraps helper that handles partial objects on Python 2.""" if isinstance(wrapped, functools.partial): return six.wraps(wrapped, assigned=_PARTIAL_VALID_ASSIGNMENTS) else: return six.wraps(wrapped)
def f(g, assign, update): def w(): return 42 w.glue = {"foo" : "bar"} return six.wraps(g, assign, update)(w)
def f(g, assign, update): def w(): return 42 w.glue = {'foo' : 'bar'} return six.wraps(g, assign, update)(w)