def decorate(fn, add_positional_parameters=()): spec = inspect_getfullargspec(fn) if add_positional_parameters: spec.args.extend(add_positional_parameters) metadata = dict( __target_fn="__target_fn", __orig_fn="__orig_fn", name=fn.__name__ ) metadata.update(format_argspec_plus(spec, grouped=False)) code = ( """\ def %(name)s(%(args)s): return %(__target_fn)s(%(__orig_fn)s, %(apply_kw)s) """ % metadata ) decorated = _exec_code_in_env( code, {"__target_fn": target, "__orig_fn": fn}, fn.__name__ ) if not add_positional_parameters: decorated.__defaults__ = getattr(fn, "__func__", fn).__defaults__ decorated.__wrapped__ = fn return update_wrapper(decorated, fn) else: # this is the pytest hacky part. don't do a full update wrapper # because pytest is really being sneaky about finding the args # for the wrapped function decorated.__module__ = fn.__module__ decorated.__name__ = fn.__name__ if hasattr(fn, "pytestmark"): decorated.pytestmark = fn.pytestmark return decorated
def instrument(buf: TextIO, name: str, clslevel: bool = False) -> None: fn = getattr(target_cls, name) overloads = _grab_overloads(fn) for overload in overloads: buf.write(overload) spec = compat.inspect_getfullargspec(fn) iscoroutine = inspect.iscoroutinefunction(fn) if spec.defaults or spec.kwonlydefaults: elem = list(spec) if spec.defaults: new_defaults = tuple( _repr_sym("util.EMPTY_DICT" ) if df is util.EMPTY_DICT else df for df in spec.defaults) elem[3] = new_defaults if spec.kwonlydefaults: new_kwonlydefaults = { name: _repr_sym("util.EMPTY_DICT") if df is util.EMPTY_DICT else df for name, df in spec.kwonlydefaults.items() } elem[5] = new_kwonlydefaults spec = compat.FullArgSpec(*elem) caller_argspec = format_argspec_plus(spec, grouped=False) metadata = { "name": fn.__name__, "async": "async " if iscoroutine else "", "await": "await " if iscoroutine else "", "apply_pos_proxied": caller_argspec["apply_pos_proxied"], "target_cls_name": target_cls.__name__, "apply_kw_proxied": caller_argspec["apply_kw_proxied"], "grouped_args": caller_argspec["grouped_args"], "self_arg": caller_argspec["self_arg"], "doc": textwrap.indent( inject_docstring_text( fn.__doc__, textwrap.indent( ".. container:: class_bases\n\n" f" Proxied for the {target_cls_sphinx_name} " "class on \n" f" behalf of the {proxy_cls_sphinx_name} " "class.", " ", ), 1, ), " ", ).lstrip(), } if clslevel: code = ( "@classmethod\n" "%(async)sdef %(name)s%(grouped_args)s:\n" ' r"""%(doc)s\n """ # noqa: E501\n\n' " return %(await)s%(target_cls_name)s.%(name)s(%(apply_kw_proxied)s)\n\n" # noqa: E501 % metadata) else: code = ( "%(async)sdef %(name)s%(grouped_args)s:\n" ' r"""%(doc)s\n """ # noqa: E501\n\n' " return %(await)s%(self_arg)s._proxied.%(name)s(%(apply_kw_proxied)s)\n\n" # noqa: E501 % metadata) buf.write(textwrap.indent(code, " "))