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 decorate(fn): spec = inspect_getfullargspec(fn) metadata = dict(target='target', fn='fn') metadata.update(format_argspec_plus(spec, grouped=False)) has_keywords = bool(spec[2]) if not has_keywords: metadata['args'] += ", **kw" metadata['apply_kw'] += ", **kw" def go(*arg, **kw): names = set(kw).difference(spec[0]) for oldname, newname in translations: if oldname in kw: kw[newname] = kw.pop(oldname) names.discard(oldname) warnings.warn( "Argument '%s' is now named '%s' for function '%s'" % (oldname, newname, fn.__name__)) if not has_keywords and names: raise TypeError("Unknown arguments: %s" % ", ".join(names)) return fn(*arg, **kw) code = 'lambda %(args)s: %(target)s(%(apply_kw)s)' % ( metadata) decorated = eval(code, {"target": go}) decorated.__defaults__ = getattr(fn, '__func__', fn).__defaults__ return update_wrapper(decorated, fn)
def decorate(fn): spec = inspect_getfullargspec(fn) metadata = dict(target='target', fn='fn') metadata.update(format_argspec_plus(spec, grouped=False)) has_keywords = bool(spec[2]) if not has_keywords: metadata['args'] += ", **kw" metadata['apply_kw'] += ", **kw" def go(*arg, **kw): names = set(kw).difference(spec[0]) for oldname, newname in translations: if oldname in kw: kw[newname] = kw.pop(oldname) names.discard(oldname) warnings.warn( "Argument '%s' is now named '%s' for function '%s'" % (oldname, newname, fn.__name__)) if not has_keywords and names: raise TypeError("Unknown arguments: %s" % ", ".join(names)) return fn(*arg, **kw) code = 'lambda %(args)s: %(target)s(%(apply_kw)s)' % ( metadata) decorated = eval(code, {"target": go}) decorated.__defaults__ = getattr(fn, '__func__', fn).__defaults__ update_wrapper(decorated, fn) if hasattr(decorated, '__wrapped__'): # update_wrapper in py3k applies __wrapped__, which causes # inspect.getargspec() to ignore the extra arguments on our # wrapper as of Python 3.4. We need this for the # "module class proxy" thing though, so just del the __wrapped__ # for now. See #175 as well as bugs.python.org/issue17482 del decorated.__wrapped__ return decorated
def visit_lambda(self, lambda_, **kw): func = lambda_.func spec = inspect_getfullargspec(func) if spec.varargs: raise exc.CompileError('Lambdas with *args are not supported') try: # ArgSpec in SA>=1.3.0b2 keywords = spec.keywords except AttributeError: # FullArgSpec in SA>=1.3.0b2 keywords = spec.varkw if keywords: raise exc.CompileError('Lambdas with **kwargs are not supported') text = ', '.join(spec.args) + ' -> ' args = [literal_column(arg) for arg in spec.args] text += self.process(func(*args), **kw) return text
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, " "))