def getargspec(func): # type: (Any) -> Any """Like inspect.getargspec but supports functools.partial as well.""" if inspect.ismethod(func): func = func.__func__ parts = 0, () # type: Tuple[int, Tuple[unicode, ...]] if type(func) is partial: keywords = func.keywords if keywords is None: keywords = {} parts = len(func.args), keywords.keys() func = func.func if not inspect.isfunction(func): raise TypeError('%r is not a Python function' % func) args, varargs, varkw = inspect.getargs(func.__code__) # type: ignore func_defaults = func.__defaults__ if func_defaults is None: func_defaults = [] else: func_defaults = list(func_defaults) if parts[0]: args = args[parts[0]:] if parts[1]: for arg in parts[1]: i = args.index(arg) - len(args) del args[i] try: del func_defaults[i] except IndexError: pass return inspect.ArgSpec(args, varargs, varkw, func_defaults)
def getargspec_permissive(func): """ find in https://github.com/neithere/argh/blob/master/argh/compat.py An `inspect.getargspec` with a relaxed sanity check to support Cython. Motivation: A Cython-compiled function is *not* an instance of Python's types.FunctionType. That is the sanity check the standard Py2 library uses in `inspect.getargspec()`. So, an exception is raised when calling `argh.dispatch_command(cythonCompiledFunc)`. However, the CyFunctions do have perfectly usable `.func_code` and `.func_defaults` which is all `inspect.getargspec` needs. This function just copies `inspect.getargspec()` from the standard library but relaxes the test to a more duck-typing one of having both `.func_code` and `.func_defaults` attributes. """ if inspect.ismethod(func): func = func.im_func # Py2 Stdlib uses isfunction(func) which is too strict for Cython-compiled # functions though such have perfectly usable func_code, func_defaults. if not (hasattr(func, "func_code") and hasattr(func, "func_defaults")): raise TypeError('{!r} missing func_code or func_defaults'.format(func)) args, varargs, varkw = inspect.getargs(func.func_code) return inspect.ArgSpec(args, varargs, varkw, func.func_defaults)
def getfullargspec(func): # Python 3: Use get_signature instead. assert sys.version_info < (3, ), 'This method should not be used in Python 3' try: return _original_getfullargspec(func) except TypeError: if isinstance(func, type): argspec = getfullargspec(func.__init__) del argspec.args[0] return argspec elif callable(func): try: return _original_getfullargspec(func.__call__) except TypeError: # Return an ArgSpec with at least one positional argument, # and any number of other (positional or keyword) arguments # whose name won't match any real argument. # Arguments with the %unknown% prefix will be ignored in the type # checking code. if _use_full_argspec: return inspect.FullArgSpec(['_'], '__unknown__varargs', '__unknown__keywords', (), [], {}, {}) else: # Python 2 return inspect.ArgSpec(['_'], '__unknown__varargs', '__unknown__keywords', ()) else: raise
def getargspec(func): if isinstance(func, types.FunctionType) or isinstance( func, types.MethodType): return inspect.getargspec(func) else: # no signature introspection is available for this type return inspect.ArgSpec(None, 'args', 'kwargs', None)
def getargspec(func): args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = inspect.getfullargspec( func) if kwonlyargs or ann: raise ValueError( "Function has keyword-only parameters or annotations" ", use getfullargspec() API which can support them") return inspect.ArgSpec(args, varargs, varkw, defaults)
def test_copy_argspec_validates_arguments(): with pytest.raises(ValueError): copy_argspec( u'hello_world', inspect.ArgSpec(args=[u'a b'], varargs=None, keywords=None, defaults=None))
def test_function_signature(self): f = self._get_f('0.1.0') expected = inspect.ArgSpec(args=['x', 'y'], varargs=None, keywords=None, defaults=(42, )) self.assertEqual(inspect.getargspec(f), expected) self.assertEqual(f.__name__, 'f')
def patched_inspect_getargspec( function: types.FunctionType) -> inspect.ArgSpec: spec = inspect.getfullargspec(function) return inspect.ArgSpec(args=spec.args, varargs=spec.varargs, keywords=spec.varkw, defaults=spec.defaults or ())
def arg_spec_from_dict(arg_spec_dict): defaults = arg_spec_dict['defaults'] if defaults is not None: defaults = tuple(defaults) return inspect.ArgSpec(arg_spec_dict['args'], arg_spec_dict['varargs'], arg_spec_dict['keywords'], defaults)
def test_getargspec_py3_only(): spec = inspect.ArgSpec(args=['a', 'b'], varargs='args', keywords=None, defaults=None) assert_eq(spec, qcore.inspection.getargspec(fun_with_annotations)) with AssertRaises(ValueError): qcore.inspection.getargspec(fun_with_kwonly_args)
def test_function_signature(self): f = self._get_f('0.1.0') # Py2: update this to use inspect.signature when we drop Python 2 # inspect.getargspec is deprecated and won't exist in 3.6 expected = inspect.ArgSpec( args=['x', 'y'], varargs=None, keywords=None, defaults=(42,)) self.assertEqual(inspect.getargspec(f), expected) self.assertEqual(f.__name__, 'f')
def _getargspec_workaround(*args, **kw): try: return _original_getargspec(*args, **kw) except TypeError, e: if str(e).startswith('arg is not a Python function'): return inspect.ArgSpec([], None, None, None) else: raise
def getargspec(f): full_argspec = inspect.getfullargspec(f) return inspect.ArgSpec( args=full_argspec.args, varargs=full_argspec.varargs, keywords=full_argspec.varkw, defaults=full_argspec.defaults, )
def getargspec_py2(obj): doc_str = obj.__doc__ args_str = '' args = [] varargs = None keywords = None defaults = [] if doc_str: lines = doc_str.split('\n') if lines: func_descr = lines[0] s = func_descr.replace(obj.__name__, '') idx1 = s.find('(') idx2 = s.find(')', idx1) if idx1 != -1 and idx2 != -1 and (idx2 > idx1 + 1): args_str = s[idx1 + 1:idx2] if args_str == '': return inspect.ArgSpec(args=args, varargs=varargs, keywords=keywords, defaults=tuple(defaults)) args_list = args_str.split(",") for arg in args_list: arg = arg.replace(" ", "") idx = arg.find("=") if idx != -1: default = arg[idx + 1:] defaults.append(default) arg = arg[:idx] if arg.startswith("**"): keywords = arg elif arg.startswith("*"): varargs = arg else: args.append(arg) return inspect.ArgSpec(args=args, varargs=varargs, keywords=keywords, defaults=tuple(defaults))
def test_copy_argspec_validates_function_name(): with pytest.raises(ValueError): copy_argspec( u'hello world', inspect.ArgSpec(args=[u'a', u'b'], varargs=None, keywords=None, defaults=None))
def args(self): """Return original function argument spec skipping self. Returns: ``inspect.ArgSpec``. """ spec = inspect.getargspec(self._func) return inspect.ArgSpec(spec.args[1:], *spec[1:])
def format_args(self): if self.object.args: argspec = inspect.ArgSpec(self.object.args, None, None, None) else: return None if argspec[0] and argspec[0][0] in ('obj', ): del argspec[0][0] return inspect.formatargspec(*argspec)
def test_healthy_argspec(language): expected_argspec = inspect.ArgSpec( args=['repo_cmd_runner', 'language_version'], varargs=None, keywords=None, defaults=None, ) argspec = inspect.getargspec(languages[language].healthy) assert argspec == expected_argspec
def test_get_default_version_argspec(language): expected_argspec = inspect.ArgSpec( args=[], varargs=None, keywords=None, defaults=None, ) argspec = inspect.getargspec(languages[language].get_default_version) assert argspec == expected_argspec
def format_args(self): if self.object.args: argspec = inspect.ArgSpec(self.object.args, None, None, None) else: return None args = inspect.formatargspec(*argspec) # escape backslashes for reST args = args.replace('\\', '\\\\') return args
def test_get_defun_argspec_with_untyped_non_eager_defun(self): # In a non-eager defun with no input signature, the same restrictions as in # a typed defun apply. self.assertEqual( func_utils.get_argspec(function.Defun()(lambda x, y, *z: None)), inspect.ArgSpec(args=['x', 'y'], varargs='z', keywords=None, defaults=None))
def test_run_hook_argpsec(language): expected_argspec = inspect.ArgSpec( args=['repo_cmd_runner', 'hook', 'file_args'], varargs=None, keywords=None, defaults=None, ) argspec = inspect.getargspec(languages[language].run_hook) assert argspec == expected_argspec
def test_install_environment_argspec(language): expected_argspec = inspect.ArgSpec( args=['repo_cmd_runner', 'version', 'additional_dependencies'], varargs=None, keywords=None, defaults=('default', ()), ) argspec = inspect.getargspec(languages[language].install_environment) assert argspec == expected_argspec
def getargspec(obj): """ Get the names and default values of a callable's arguments A tuple of four things is returned: (args, varargs, varkw, defaults). - args is a list of the argument names (it may contain nested lists). - varargs and varkw are the names of the * and ** arguments or None. - defaults is a tuple of default argument values or None if there are no default arguments; if this tuple has n elements, they correspond to the last n elements listed in args. Unlike inspect.getargspec(), can return argument specification for functions, methods, callable objects, and classes. Does not support builtin functions or methods. """ if not callable(obj): raise TypeError, "%s is not callable" % type(obj) try: if inspect.isfunction(obj): return inspect.getargspec(obj) elif hasattr(obj, 'im_func'): # For methods or classmethods drop the first # argument from the returned list because # python supplies that automatically for us. # Note that this differs from what # inspect.getargspec() returns for methods. # NB: We use im_func so we work with # instancemethod objects also. spec = inspect.getargspec(obj.im_func) return inspect.ArgSpec(spec.args[:1], spec.varargs, spec.keywords, spec.defaults) elif inspect.isclass(obj): return getargspec(obj.__init__) elif isinstance(obj, object): # We already know the instance is callable, # so it must have a __call__ method defined. # Return the arguments it expects. return getargspec(obj.__call__) except NotImplementedError: # If a nested call to our own getargspec() # raises NotImplementedError, re-raise the # exception with the real object type to make # the error message more meaningful (the caller # only knows what they passed us; they shouldn't # care what aspect(s) of that object we actually # examined). pass raise NotImplementedError, \ "do not know how to get argument list for %s" % \ type(obj)
def test_copy_argspec_works_with_conflicts(): def accepts_everything(*args, **kwargs): pass copy_argspec('hello', inspect.ArgSpec( args=('f',), varargs=None, keywords=None, defaults=None ))(accepts_everything)(1) copy_argspec('hello', inspect.ArgSpec( args=(), varargs='f', keywords=None, defaults=None ))(accepts_everything)(1) copy_argspec('hello', inspect.ArgSpec( args=(), varargs=None, keywords='f', defaults=None ))(accepts_everything)() copy_argspec('hello', inspect.ArgSpec( args=('f', 'f_3'), varargs='f_1', keywords='f_2', defaults=None ))(accepts_everything)(1, 2)
def test_function_signature(self): f = self._get_f('0.1.0', until='0.1.4', reason='You should now use skbio.g().') expected = inspect.ArgSpec(args=['x', 'y'], varargs=None, keywords=None, defaults=(42, )) self.assertEqual(inspect.getargspec(f), expected) self.assertEqual(f.__name__, 'f')
def test_get_defun_argspec_with_typed_non_eager_defun(self): # In a non-eager defun with a defined input signature, **kwargs or default # values are not allowed, but *args are, and the input signature may # overlap with *args. self.assertEqual( function_utils.get_argspec( function.Defun(tf.int32, tf.bool, tf.float32, tf.float32)(lambda x, y, *z: None)), inspect.ArgSpec( args=['x', 'y'], varargs='z', keywords=None, defaults=None))
def arglist_retrieve_java(method): name = method.__name__ if hasattr(method, "argslist"): # uses only the first args list... args = [x.__name__ for x in method.argslist[0].args] else: methods = eval("method.__self__.class.getDeclaredMethods()") methods_by_name = [m for m in methods if m.getName() == name] assert len(methods_by_name) == 1, "expected only a single method by name %s" % name meta = methods_by_name[0] args = [str(par.getType().__name__ + " " + par.getName()) for par in meta.getParameters()] return inspect.ArgSpec(args, None, None, None)
def getargspec(func): """Variation of inspect.getargspec that works for (non-cpdef) Cythonized functions.""" if inspect.ismethod(func): func = func.im_func # Cythonized functions have a .func_code, but don't pass inspect.isfunction() try: code = func.__code__ except AttributeError: raise TypeError('{!r} is not a Python function'.format(func)) args, varargs, varkw = inspect.getargs(code) return inspect.ArgSpec(args, varargs, varkw, func.__defaults__)
def patterns(func): empty_argspec = inspect.ArgSpec(args=[], varargs=None, keywords=None, defaults=None) assert inspect.getargspec(func) == empty_argspec, 'Pattern function should not have arguments' # TODO: make it not as weird and dirty func.__globals__['Mismatch'] = Mismatch tree = get_ast(func) print("\n"+codegen.to_source(tree)+"\n") transform_function(tree.body[0]) print("\n"+codegen.to_source(tree)+"\n") return compile_func(func, tree)