def getfuncargnames(function, startindex=None): # XXX merge with main.py's varnames # assert not isclass(function) realfunction = function while hasattr(realfunction, "__wrapped__"): realfunction = realfunction.__wrapped__ if startindex is None: startindex = inspect.ismethod(function) and 1 or 0 if realfunction != function: startindex += num_mock_patch_args(function) function = realfunction if isinstance(function, functools.partial): argnames = inspect.getargs(_pytest._code.getrawcode(function.func))[0] partial = function argnames = argnames[len(partial.args) :] if partial.keywords: for kw in partial.keywords: argnames.remove(kw) else: argnames = inspect.getargs(_pytest._code.getrawcode(function))[0] defaults = getattr(function, "func_defaults", getattr(function, "__defaults__", None)) or () numdefaults = len(defaults) if numdefaults: return tuple(argnames[startindex:-numdefaults]) return tuple(argnames[startindex:])
def logged_function(self, *args, **kwargs): ref_args = inspect.getargs(func.func_code).args report = '' ref_args = inspect.getargs(func.func_code).args for i, k in enumerate(ref_args): if k == 'self': continue try: v = args[i - 1] except IndexError: if k in kwargs: v = kwargs[k] else: v = None report += '{0}:{1} '.format(k, str(v) [:100].encode('utf-8').replace('\n', ' ')) self.logger.log( log_level, '@{0} `{1}` Starting with args: {2}'.format(func_type, name, report)) try: data = func(self, *args, **kwargs) except (Exception, KeyboardInterrupt) as e: self.logger.error('@{0} `{1}` Failed with error: {2} and args: {3}\n{4}'.format( func_type, name, e, report, traceback.format_exc() )) raise e self.logger.log( log_level, '@{0} `{1}` Succeded with args: {2}'.format(func_type, name, report)) return data
def sage_getargspec(obj): r""" Return the names and default values of a function's arguments. INPUT: ``obj``, a function OUTPUT: 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 an n-tuple of the default values of the last n arguments. EXAMPLES:: sage: from sagenb.misc.sageinspect import sage_getargspec sage: sage_getargspec(identity_matrix) (['ring', 'n', 'sparse'], None, None, (0, False)) sage: sage_getargspec(Poset) (['data', 'element_labels', 'cover_relations'], None, None, (None, None, False)) sage: sage_getargspec(factor) (['n', 'proof', 'int_', 'algorithm', 'verbose'], None, 'kwds', (None, False, 'pari', 0)) AUTHORS: - William Stein: a modified version of inspect.getargspec from the Python Standard Library, which was taken from IPython for use in FEMhub. - Extensions by Nick Alexander """ if not callable(obj): raise TypeError, "obj is not a code object" if inspect.isfunction(obj): func_obj = obj elif inspect.ismethod(obj): func_obj = obj.im_func elif isclassinstance(obj): return sage_getargspec(obj.__class__.__call__) elif inspect.isclass(obj): return sage_getargspec(obj.__call__) else: # Perhaps it is binary and defined in a Cython file source = sage_getsource(obj, is_binary=True) if source: return _sage_getargspec_cython(source) else: func_obj = obj # Otherwise we're (hopefully!) plain Python, so use inspect try: args, varargs, varkw = inspect.getargs(func_obj.func_code) except AttributeError: args, varargs, varkw = inspect.getargs(func_obj) try: defaults = func_obj.func_defaults except AttributeError: defaults = tuple([]) return args, varargs, varkw, defaults
def _wrapper_for_partition_function(data): # TODO:PERFORMANCE: This could be a performance issue. We may need to use the underlying metadata or # cache the checks for better performance. arg_names, args_arg_name, kws_arg_name = inspect.getargs(data.__code__) has_memory = "memory" in arg_names has_device = "device" in arg_names if kws_arg_name is not None or (has_memory and has_device): @functools.wraps(data) def wrapper(*args, memory, device): return memory(data(*args, memory=memory, device=device)) elif has_memory: # noinspection PyUnusedLocal @functools.wraps(data) def wrapper(*args, memory, device): return memory(data(*args, memory=memory)) elif has_device: @functools.wraps(data) def wrapper(*args, memory, device): return memory(data(*args, device=device)) else: # noinspection PyUnusedLocal @functools.wraps(data) def wrapper(*args, memory, device): return memory(data(*args)) return wrapper
def getArgumentError(self): if not inspect.isfunction(self._func): # We can only check for argument errors with Python functions return None argcount = len(self._args) args, vararg, kwarg = inspect.getargs(self._func.func_code) defaults = self._func.func_defaults or () # Don't count the context parameter in argument count maxargs = len(args) - 1 minargs = maxargs - len(defaults) if argcount > maxargs and not vararg: if maxargs == 0: return RuntimeException(RuntimeException.ARGCOUNT_NONE, self._name, argcount) elif defaults: return RuntimeException(RuntimeException.ARGCOUNT_ATMOST, self._name, maxargs, argcount) else: return RuntimeException(RuntimeException.ARGCOUNT_EXACT, self._name, maxargs, argcount) elif argcount < minargs: if defaults or vararg: return RuntimeException(RuntimeException.ARGCOUNT_ATLEAST, self._name, minargs, argcount) else: return RuntimeException(RuntimeException.ARGCOUNT_EXACT, self._name, minargs, argcount) # Not an error with arg counts for this function, use current error return None
def wrapped(**kwargs): new_args = [None] * (len(args) + 1) missing_args = inspect.getargs(fun.func_code).args for (idx, missing_arg) in enumerate(missing_args): if missing_arg in kwargs: new_args[idx] = kwargs[missing_arg] del kwargs[missing_arg] if kwargs: raise ArakoonInvalidArguments(fun.func_name, list(kwargs.iteritems())) i = 0 error_key_values = [] for arg, arg_type in zip(new_args[1:], args): if not validate(arg, arg_type): error_key_values.append( (fun.func_code.co_varnames[i + 1], new_args[i])) i += 1 if error_key_values: raise ArakoonInvalidArguments(fun.func_name, error_key_values) return fun(*new_args)
def simple_vectorize(fn,num_outputs=1,output_type=object,doc=''): """ Simplify creation of numpy.vectorize(fn) objects where all outputs have the same typecode. """ from numpy import vectorize,sctype2char # This function exists because I cannot figure out how I am # supposed to stop vectorize() calling fn one extra time at the # start. (It's supposed to call an extra time at the start to # determine the output types UNLESS the output types are # specified.) vfn = vectorize(fn,doc=doc) # stop vectorize calling fn an extra time at the start # (works for our current numpy (1.1.1)) vfn.nout=num_outputs # number of outputs of fn output_typecode = sctype2char(output_type) vfn.otypes=output_typecode*num_outputs # typecodes of outputs of fn import inspect try: fn_code = fn.func_code if hasattr(fn,'func_code') else fn.__call__.func_code except: raise TypeError("Couldn't find code of %s"%fn) fn_args = inspect.getargs(fn_code)[0] extra = 1 if fn_args[0]=='self' else 0 vfn.lastcallargs=len(fn_args)-extra # num args of fn return vfn
def validate_signature_inner(*args, **kwargs): _ = args new_args = [None] * (len(signature_args) + 1) missing_args = inspect.getargs(fun.func_code).args for (idx, missing_arg) in enumerate(missing_args): if missing_arg in kwargs: new_args[idx] = kwargs[missing_arg] del kwargs[missing_arg] if kwargs: raise ArakoonInvalidArguments(fun.func_name, list(kwargs.iteritems())) i = 0 error_key_values = [] for arg, arg_type in zip(new_args[1:], signature_args): if not validate(arg, arg_type): error_key_values.append( (fun.func_code.co_varnames[i + 1], new_args[i])) i += 1 if error_key_values: raise ArakoonInvalidArguments(fun.func_name, error_key_values) return fun(*new_args)
def MAKE_FUNCTION(decompiler, argc): defaults = [] flags = 0 if sys.version_info >= (3, 6): qualname = decompiler.stack.pop() tos = decompiler.stack.pop() if argc & 0x08: func_closure = decompiler.stack.pop() if argc & 0x04: annotations = decompiler.stack.pop() if argc & 0x02: kwonly_defaults = decompiler.stack.pop() if argc & 0x01: defaults = decompiler.stack.pop() throw(DecompileError) else: if not PY2: qualname = decompiler.stack.pop() tos = decompiler.stack.pop() if argc: defaults = [decompiler.stack.pop() for i in range(argc)] defaults.reverse() codeobject = tos.value func_decompiler = Decompiler(codeobject) # decompiler.names.update(decompiler.names) ??? if codeobject.co_varnames[:1] == ('.0', ): return func_decompiler.ast # generator argnames, varargs, keywords = inspect.getargs(codeobject) if varargs: argnames.append(varargs) flags |= inspect.CO_VARARGS if keywords: argnames.append(keywords) flags |= inspect.CO_VARKEYWORDS return ast.Lambda(argnames, defaults, flags, func_decompiler.ast)
def callback(self, callbackName, args): """ 根据回调链调用已经绑定的所有回调函数,该函数主要提供给监听简称使用 参数: callbackName 回调函数名称 args 用于传递给回调函数的参数(字典结构) 返回值: 无 """ self.__callbackLock.acquire() try: if callbackName not in self.__callbackDict.keys(): return for callbackUuid in self.__callbackDict[callbackName]: funcToCall = self.__callbackUuidDict[callbackUuid]['funcToCall'] try: argsToCall = copy.copy(args) # 如果方法的参数格式是**kwargs,可以把响应函数的名称加到参数列表中 argsInfo = inspect.getargs(funcToCall.func_code) c1 = len(argsInfo.args) == 0 c2 = argsInfo.varargs == None c3 = argsInfo.keywords != None if c1 and c2 and c3: argsToCall['ResponseMethod'] = callbackName funcToCall(**argsToCall) except Exception as e: print e finally: self.__callbackLock.release()
def trace_function(self, func): # type: (FunctionType) -> FunctionType new_func = super(BirdsEye, self).trace_function(func) code_info = self._code_infos.get(new_func.__code__) if code_info: return new_func lines, start_lineno = inspect.getsourcelines( func) # type: List[Text], int end_lineno = start_lineno + len(lines) name = safe_qualname(func) source_file = inspect.getsourcefile(func) if source_file.startswith('<ipython-input'): filename = IPYTHON_FILE_PATH else: filename = os.path.abspath(source_file) nodes = list( self._nodes_of_interest(new_func.traced_file, start_lineno, end_lineno)) html_body = self._nodes_html(nodes, start_lineno, end_lineno, new_func.traced_file) data = json.dumps(dict( node_loops={ node._tree_index: [n._tree_index for n in node._loops] for node, _ in nodes if node._loops }), sort_keys=True) db_func = self._db_func(data, filename, html_body, name, start_lineno) arg_info = inspect.getargs(new_func.__code__) arg_names = list(chain(flatten_list(arg_info[0]), arg_info[1:])) # type: List[str] self._code_infos[new_func.__code__] = CodeInfo(db_func, new_func.traced_file, arg_names) return new_func
def getargtxt(obj, one_arg_per_line=True): """Get the names and default values of a function's arguments""" sep = ', ' if inspect.isfunction(obj) or inspect.isbuiltin(obj): func_obj = obj elif inspect.ismethod(obj): func_obj = obj.im_func elif inspect.isclass(obj) and hasattr(obj, '__init__'): func_obj = getattr(obj, '__init__') else: return None if not hasattr(func_obj, 'func_code'): # Builtin: try to extract info from getdoc return getargfromdoc(func_obj) args, _, _ = inspect.getargs(func_obj.func_code) if not args: return getargfromdoc(obj) defaults = func_obj.func_defaults if defaults is not None: for index, default in enumerate(defaults): args[index + len(args) - len(defaults)] += '=' + repr(default) textlist = None for i_arg, arg in enumerate(args): if textlist is None: textlist = [''] textlist[-1] += arg if i_arg < len(args) - 1: textlist[-1] += sep if len(textlist[-1]) >= 32 or one_arg_per_line: textlist.append('') if inspect.isclass(obj) or inspect.ismethod(obj): if len(textlist) == 1: return None textlist.remove('self' + sep) return textlist
def _requests_to_follow(self, response): if not isinstance(response, HtmlResponse): return meta = {k:v for k,v in response.meta.iteritems() if k.isupper()} seen = set() for n, rule in enumerate(self._rules): # HACK 1 if rule.match and not re.search(rule.match, response.url): continue links = [l for l in rule.link_extractor.extract_links(response) if l not in seen] if links and rule.process_links: links = rule.process_links(links) seen = seen.union(links) for link in links: r = Request(url=link.url, callback=self._response_downloaded) r.meta.update(rule=n, link_text=link.text) r.meta.update(meta) # HACK 2 fun = rule.process_request if not hasattr(fun, 'nargs'): fun.nargs = len(inspect.getargs(fun.func_code).args) if fun.nargs==1: yield fun(r) elif fun.nargs==2: yield fun(r, response) else: raise Exception('too many arguments')
def reorder(func: Callable, reordered_args: tuple) -> Callable: """ Reorders arguments to a function according to tuple of integers :param func: function of n-arity :param reordered_args: a tuple of unique integers :return: function of n-arity with reordered args """ name = func.__name__ args_spec = inspect.getargs(func.__code__) num_positional_args = len(args_spec.args) if len(reordered_args) > num_positional_args: raise ChainSmokeFunctoolsError( "functools.reorder received too many args in the reordered_args tuple; " "make sure the length of the tuple matches the number of positional arguments in {func_name}".format( func_name=name)) if len(reordered_args) < num_positional_args: raise ChainSmokeFunctoolsError( "functools.reorder received too few args in the reordered_args tuple; " "make sure the length of the tuple matches the number of positional arguments in {func_name}".format( func_name=name)) def reorder_inner(*args, **kwargs): correct_order = sorted(zip(args, reordered_args), key=lambda x: x[1]) correct_args = (arg[0] for arg in correct_order) return func(*correct_args, **kwargs) return reorder_inner
def get_params(self, deep=True): """Get the parameters (if any) of the given feature function. Parameters ---------- deep : bool (default: True) If True, the method will get the parameters of the transformer. (See :class:`~sklearn.preprocessing.FunctionTransformer`). """ func_to_inspect = _get_python_func(self.func) # Get code object from the function if hasattr(func_to_inspect, 'func_code'): func_code = func_to_inspect.func_code else: func_code = func_to_inspect.__code__ args, _, _ = getargs(func_code) # Get defaults from the function if hasattr(func_to_inspect, 'defaults'): defaults = func_to_inspect.func_defaults else: defaults = func_to_inspect.__defaults__ if defaults is None: return dict() else: n_defaults = len(defaults) func_params = { key: value for key, value in zip(args[-n_defaults:], defaults) } if self.params is not None: func_params.update(self.params) return func_params
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__) 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) # type: ignore del args[i] try: del func_defaults[i] except IndexError: pass return inspect.ArgSpec(args, varargs, varkw, func_defaults) # type: ignore
def interpindirect2app(unbound_meth, unwrap_spec=None): base_cls = unbound_meth.im_class func = unbound_meth.im_func args = inspect.getargs(func.func_code) if args.varargs or args.keywords: raise TypeError("Varargs and keywords not supported in unwrap_spec") argspec = ', '.join([arg for arg in args.args[1:]]) func_code = py.code.Source(""" def f(self, %(args)s): return self.%(func_name)s(%(args)s) """ % {'args': argspec, 'func_name': func.func_name}) d = {} exec func_code.compile() in d f = d['f'] f.func_defaults = unbound_meth.func_defaults f.func_doc = unbound_meth.func_doc f.__module__ = func.__module__ # necessary for unique identifiers for pickling f.func_name = func.func_name if unwrap_spec is None: unwrap_spec = getattr(unbound_meth, 'unwrap_spec', {}) else: assert isinstance(unwrap_spec, dict) unwrap_spec = unwrap_spec.copy() unwrap_spec['self'] = base_cls return interp2app(globals()['unwrap_spec'](**unwrap_spec)(f))
def inspect_signature(func): """Return dispatch conditions from func's argument annotations""" try: if six.PY2: func_args = inspect.getargs(func.func_code).args return tuple([object] * len(func_args)), object else: D = func.__annotations__ n_args = func.__code__.co_argcount - len(func.__defaults__ or ()) varnames = func.__code__.co_varnames[:n_args] return tuple(D.get(name, object) for name in varnames), object # Does not have annotations, maybe it is a builtin function. Try # looking at the docstring except AttributeError: body, sep1, _tail = getattr(func, '__doc__', '').partition(')') name, sep2, args = body.partition('(') # Fail conditions fail = (sep1 == '') or (sep2 == '') if '[' in args: fail = True if fail: print([body, sep1, sep2, name, args]) print(func) print(func.__doc__) raise ValueError( 'could not inspect signature. ' 'Try giving the signature explicitly') varnames = [x.strip() for x in args.split(',')] return tuple(object for name in varnames), object
def _get_feature_funcs(sfreq, module_name): """Inspection for feature functions. Inspects a given module and returns a dictionary of feature functions in this module. If the module does not contain any feature function, an empty dictionary is returned. Parameters ---------- sfreq : float Sampling rate of the data. module_name : str Name of the module to inspect. Returns ------- feature_funcs : dict """ feature_funcs = dict() res = getmembers(sys.modules[module_name], isfunction) for name, func in res: if name.startswith('compute_'): alias = name.split('compute_')[-1] if hasattr(func, 'func_code'): func_code = func.func_code else: func_code = func.__code__ args, _, _ = getargs(func_code) if 'sfreq' in args[0]: feature_funcs[alias] = partial(func, sfreq) else: feature_funcs[alias] = func return feature_funcs
def __get__(self, obj, objtype): val = super(ExpressionParameter, self).__get__(obj, objtype) if isinstance(val, types.FunctionType) and inspect.getargs(val.func_code) == (["p"], None, None): if not obj: # called on class my_val = self.initial_value O = objtype else: # called on instance; get last value produced for obj my_val = obj.__dict__.get(self._internal_name + "_last", self.initial_value) O = obj new_value = val(ParamOverrides(O, {self._attrib_name: my_val})) # store the generated value if obj: setattr(obj, self._internal_name + "_last", new_value) else: self.initial_value = new_value return new_value else: return val
def normalize_args(func, pargs, kwargs): """ This function puts the arguments into a dictionary mapping keywords to arguments. To do this it must look up the function spec for positional arguments. """ # This should be a list of the names of the arguments spec = inspect.getargs(func.__code__).args # Convert pargs to a list temporarily if need to change any mutable # types to immutable types pargs = list(pargs) # We normalize any list or dictionary arguments to tuples for i, parg in enumerate(pargs): if isinstance(parg, list): pargs[i] = tuple(parg) elif isinstance(parg, dict): pargs[i] = tuple(sorted(parg.items())) for key, value in kwargs.items(): if isinstance(value, list): kwargs[key] = tuple(value) elif isinstance(value, dict): kwargs[key] = tuple(sorted(value.items())) return dict(list(kwargs.items()) + list(zip(spec, pargs)))
def _repr(self,I=None): '''return a repr style string with named fixed args first, then keywords''' if type(self) is InstanceType: if self is EmptyClipPath: _addObjImport(self,I,'EmptyClipPath') return 'EmptyClipPath' if I: _addObjImport(self,I) if isinstance(self,Shape): from inspect import getargs args, varargs, varkw = getargs(self.__init__.im_func.func_code) P = self.getProperties() s = self.__class__.__name__+'(' for n in args[1:]: v = P[n] del P[n] s = s + '%s,' % _repr(v,I) for n,v in P.items(): v = P[n] s = s + '%s=%s,' % (n, _repr(v,I)) return s[:-1]+')' else: return repr(self) elif type(self) is FloatType: return fp_str(self) elif type(self) in (ListType,TupleType): s = '' for v in self: s = s + '%s,' % _repr(v,I) if type(self) is ListType: return '[%s]' % s[:-1] else: return '(%s%s)' % (s[:-1],len(self)==1 and ',' or '') else: return repr(self)
def _make_free_args(f, init_attrs): ''' Takes a function and a list of the instance attributes (as strings.) Returns a function intended to be turned into a method on the new class. The method will access all of its arguments that it took as a parameter in its prior life as a function from self, assuming the attributes are in init_args. ''' f_args = inspect.getargs(f.func_code) def func(self, *args, **kwargs): my_kwargs = {} for attr in init_attrs: my_kwargs[attr] = getattr(self, attr) leftover_args = _compute_leftover_args(f_args.args, args, my_kwargs) kw_from_positional_args = dict(zip(leftover_args, args)) if set(my_kwargs.keys()) & set(kwargs.keys()) != set([]): raise('Cannot override instance variables') my_kwargs.update(kwargs) my_kwargs.update(kw_from_positional_args) # Remove args in my_kwargs that are not in f_args.args for k,v in my_kwargs.copy().iteritems(): if not k in f_args.args: my_kwargs.pop(k) return f(**my_kwargs) func.func_name = f.func_name return func
def _repr(self, I=None): '''return a repr style string with named fixed args first, then keywords''' if type(self) is InstanceType: if self is EmptyClipPath: _addObjImport(self, I, 'EmptyClipPath') return 'EmptyClipPath' if I: _addObjImport(self, I) if isinstance(self, Shape): from inspect import getargs args, varargs, varkw = getargs(self.__init__.im_func.func_code) P = self.getProperties() s = self.__class__.__name__ + '(' for n in args[1:]: v = P[n] del P[n] s = s + '%s,' % _repr(v, I) for n, v in P.items(): v = P[n] s = s + '%s=%s,' % (n, _repr(v, I)) return s[:-1] + ')' else: return repr(self) elif type(self) is FloatType: return fp_str(self) elif type(self) in (ListType, TupleType): s = '' for v in self: s = s + '%s,' % _repr(v, I) if type(self) is ListType: return '[%s]' % s[:-1] else: return '(%s%s)' % (s[:-1], len(self) == 1 and ',' or '') else: return repr(self)
def trace_function(self, func): # type: (FunctionType) -> FunctionType new_func = super(BirdsEye, self).trace_function(func) code_info = self._code_infos.get(new_func.__code__) if code_info: return new_func lines, start_lineno = inspect.getsourcelines( func) # type: List[Text], int end_lineno = start_lineno + len(lines) name = safe_qualname(func) source_file = inspect.getsourcefile(func) if source_file.startswith('<ipython-input'): filename = IPYTHON_FILE_PATH else: filename = os.path.abspath(source_file) traced_file = new_func.traced_file arg_info = inspect.getargs(new_func.__code__) arg_names = list(chain(flatten_list(arg_info[0]), arg_info[1:])) # type: List[str] self._trace(name, filename, traced_file, new_func.__code__, typ='function', start_lineno=start_lineno, end_lineno=end_lineno, arg_names=arg_names) return new_func
def getmethparlist(ob): """Get strings describing the arguments for the given object Returns a pair of strings representing function parameter lists including parenthesis. The first string is suitable for use in function definition and the second is suitable for use in function call. The "self" parameter is not included. """ defText = callText = "" # bit of a hack for methods - turn it into a function # but we drop the "self" param. # Try and build one for Python defined functions args, varargs, varkw = inspect.getargs(ob.__code__) items2 = args[1:] realArgs = args[1:] defaults = ob.__defaults__ or [] defaults = ["=%r" % (value,) for value in defaults] defaults = [""] * (len(realArgs)-len(defaults)) + defaults items1 = [arg + dflt for arg, dflt in zip(realArgs, defaults)] if varargs is not None: items1.append("*" + varargs) items2.append("*" + varargs) if varkw is not None: items1.append("**" + varkw) items2.append("**" + varkw) defText = ", ".join(items1) defText = "(%s)" % defText callText = ", ".join(items2) callText = "(%s)" % callText return defText, callText
def __init__(self, xtb, frame, frame_info, tb_index): self.xtb = xtb self.frame = frame self.frame_info = frame_info self.tb_index = tb_index self.filename, self.lineno, self.function, self.code_context, self.index \ = self.frame_info self.args, self.varargs, self.varkw = inspect.getargs(self.frame.f_code) # keep track of what we've formatted in this frame self.formatted_vars = {} # we use a filtered copy of locals and globals self.locals = self._filter(self.frame.f_locals) self.globals = self._filter(self.frame.f_globals) # filter globals if self.xtb.options.globals_module_include is not None: for key, value in self.globals.items(): if isinstance(value, types.ModuleType): module = value.__name__ elif isinstance(value, types.InstanceType): module = value.__class__.__module__ else: module = getattr(value, "__module__", None) if module is not None \ and not module.startswith( self.xtb.options.globals_module_include ): del self.globals[key] # if path is a real path then try to shorten it if os.path.exists(self.filename): self.filename = self.xtb._format_filename( os.path.abspath(self.filename) ) # qualify method name with class name if self.xtb.options.qualify_methods and self.args: try: cls = self.frame.f_locals[self.args[0]] except KeyError: # pragma: no cover - defensive # we're assuming that the first argument is in f_locals but # it may not be in some cases so this is a defence, see # https://github.com/ischium/xtraceback/issues/3 with further # detail at http://www.sqlalchemy.org/trac/ticket/2317 and # https://dev.entrouvert.org/issues/765 pass else: if not isinstance(cls, type): cls = type(cls) if hasattr(cls, self.function): for base in inspect.getmro(cls): if self.function in base.__dict__: self.function = base.__name__ + "." + self.function break self._formatted = None
def is_args_in_task(func): """Check if func.func_code has *args. @aparm func: function reference """ arg = inspect.getargs(func.func_code) return arg.varargs is not None
def getargspec(func): """Like inspect.getargspec but supports functools.partial as well.""" if inspect.ismethod(func): func = func.im_func parts = 0, () 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.func_code) func_defaults = func.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 interpindirect2app(unbound_meth, unwrap_spec=None): base_cls = unbound_meth.im_class func = unbound_meth.im_func args = inspect.getargs(func.func_code) if args.varargs or args.keywords: raise TypeError("Varargs and keywords not supported in unwrap_spec") argspec = ', '.join([arg for arg in args.args[1:]]) func_code = py.code.Source(""" def f(w_obj, %(args)s): return w_obj.%(func_name)s(%(args)s) """ % {'args': argspec, 'func_name': func.func_name}) d = {} exec func_code.compile() in d f = d['f'] f.func_defaults = unbound_meth.func_defaults f.func_doc = unbound_meth.func_doc f.__module__ = func.__module__ # necessary for unique identifiers for pickling f.func_name = func.func_name if unwrap_spec is None: unwrap_spec = getattr(unbound_meth, 'unwrap_spec', {}) else: assert isinstance(unwrap_spec, dict) unwrap_spec = unwrap_spec.copy() unwrap_spec['w_obj'] = base_cls return interp2app(globals()['unwrap_spec'](**unwrap_spec)(f))
def getargspec_permissive(func): """ 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 getargtxt(obj, one_arg_per_line=True): """Get the names and default values of a function's arguments""" sep = ', ' if inspect.isfunction(obj) or inspect.isbuiltin(obj): func_obj = obj elif inspect.ismethod(obj): func_obj = obj.im_func elif inspect.isclass(obj) and hasattr(obj, '__init__'): func_obj = getattr(obj, '__init__') else: return None if not hasattr(func_obj, 'func_code'): # Builtin: try to extract info from getdoc return getargfromdoc(func_obj) args, _, _ = inspect.getargs(func_obj.func_code) if not args: return getargfromdoc(obj) defaults = func_obj.func_defaults if defaults is not None: for index, default in enumerate(defaults): args[index+len(args)-len(defaults)] += '='+repr(default) textlist = None for i_arg, arg in enumerate(args): if textlist is None: textlist = [''] textlist[-1] += arg if i_arg < len(args)-1: textlist[-1] += sep if len(textlist[-1]) >= 32 or one_arg_per_line: textlist.append('') if inspect.isclass(obj) or inspect.ismethod(obj): if len(textlist) == 1: return None textlist.remove('self'+sep) return textlist
def __repr__(self): args = _inspect.getargs(ABCApplication.__init__.__code__).args[1:] return "<{cls}({spec})>".format( cls=self.__class__.__name__, spec=", ".join("{0}={1!r}".format(arg, getattr(self, arg)) for arg in args))
def __new__(mcs, name, bases, namespace, **kwargs): cls = super().__new__(mcs, name, bases, namespace, **kwargs) multi_signatures = { name: value for name, value in namespace.items() if hasattr(value, "__multi_signature_wrappers__") and inspect.isfunction(value) # isfunction, because function is not bound yet } # search in base classes for decorated functions for base in bases: for name, value in getattr(base, "__multi_signature_methods__", {}).items(): if inspect.isfunction(value) and hasattr( value, "__multi_signature_wrappers__"): multi_signature_wrappers = getattr( value, "__multi_signature_wrappers__", False) if multi_signature_wrappers: current_function = multi_signatures.get(name) if current_function: current_function.__multi_signature_wrappers__.update( multi_signature_wrappers) else: multi_signatures[name] = value cls.__multi_signature_methods__ = multi_signatures for name, value in multi_signatures.items(): wrapped = getattr(cls, name) arguments = inspect.getargs(wrapped.__code__) if arguments == inspect.getargs(value.__code__): # Do not replace if the signature is the same continue # convert args into a tuple args, varargs, varkw = arguments arguments = tuple(args), varargs, varkw get_wrapper = value.__multi_signature_wrappers__.get( tuple(arguments), None) if get_wrapper: wrapper = get_wrapper(cls, wrapped) update_wrapper(wrapper, wrapped) setattr(cls, name, wrapper) else: # unknown implementation raise NotImplementedError( f"The signature {arguments} for {name} is not supported.") return cls
def check_docstring(self, f): """ Ensure the docstring of `f` is in accordance with the numpy standard Currently, only the Parameters section of the docstring is checked. Parameters ---------- f : function, method, class Returns ------- repr : string A string represntation """ doc = getdoc(f) if doc is None: if error_on_none: raise ValueError('no docstring for %s' % format(f)) else: with warnings.catch_warnings(): warnings.simplefilter('error') parsed = NumpyDocString(doc) param_names = set([e[0] for e in parsed['Parameters']]) if isbuiltin(f): # You can't get the arglist from a builtin, which # is how cython functions turn up # but you can, hackily, get the number of arguments it wants # by parseing the error hen you supply too many import re try: f(*list(range(100))) except TypeError as e: m = re.search('takes at most (\d+) positional arguments', str(e)) if not m: return n_args = int(m.group(1)) if len(param_names) != n_args: raise ValueError( "In %s, number of arguments, %d, doesn't " " match the length of the Parameters in the " "docstring, %d" % (format(f), n_args, len(param_names))) return args = set(getargs(get_function_code(f)).args) if 'self' in args: args.remove('self') if args != param_names: raise ValueError("In %s, arguments %s don't " "match Parameters list %s" % (format(f), list(args), list(param_names)))
def create_eval_metrics(self, features, labels, estimator_spec, metric_fn): """Creates evaluation metrics from the given arguments. Args: features: Input `dict` of `Tensor` objects. labels: Labels `Tensor` or a dictionary of string label name to `Tensor` (for multi-head). estimator_spec: The `EstimatorSpec` created by a `Head` instance. metric_fn: A function which should obey the following signature: - Args: can only have following three arguments in any order: * predictions: Predictions `Tensor` or dict of `Tensor` created by given `Head`. * features: Input `dict` of `Tensor` objects created by `input_fn` which is given to `estimator.evaluate` as an argument. * labels: Labels `Tensor` or dict of `Tensor` (for multi-head) created by `input_fn` which is given to `estimator.evaluate` as an argument. - Returns: Dict of metric results keyed by name. Final metrics are a union of this and `estimator`s existing metrics. If there is a name conflict between this and `estimator`s existing metrics, this will override the existing one. The values of the dict are the results of calling a metric function, namely a `(metric_tensor, update_op)` tuple. """ # If estimator_spec is not a TPUEstimatorSpec we create dummy metric_fn # and args. if isinstance(estimator_spec, tf.estimator.EstimatorSpec): spec_fn, spec_args = lambda: estimator_spec.eval_metric_ops, [] else: spec_fn, spec_args = estimator_spec.eval_metrics self._eval_metrics_store.add_eval_metrics( self._templatize_metric_fn(spec_fn), spec_args) loss_fn = lambda loss: {"loss": tf_compat.v1.metrics.mean(loss)} loss_fn_args = [tf.reshape(estimator_spec.loss, [1])] if not self._use_tpu: loss_ops = _call_eval_metrics((loss_fn, loss_fn_args)) loss_fn, loss_fn_args = lambda: loss_ops, [] self._eval_metrics_store.add_eval_metrics( self._templatize_metric_fn(loss_fn), loss_fn_args) # NOTE: the user supplied metrics_fn must be added last. This is because we # want user metrics to override AdaNet's metrics. if metric_fn: metric_fn_args = {} # Calling low level getargs for py_2_and_3 compatibility. argspec = inspect.getargs(metric_fn.__code__).args if "features" in argspec: metric_fn_args["features"] = features if "labels" in argspec: metric_fn_args["labels"] = labels if "predictions" in argspec: metric_fn_args["predictions"] = estimator_spec.predictions if not self._use_tpu: metric_fn_ops = _call_eval_metrics((metric_fn, metric_fn_args)) metric_fn, metric_fn_args = lambda: metric_fn_ops, [] self._eval_metrics_store.add_eval_metrics( self._templatize_metric_fn(metric_fn), metric_fn_args)
def test_fx_native_calls(f): import inspect ds = datasets['uni2small'] if f in ['size', 'rollaxis', 'stack']: # really not appropriate ones here to test return try: f_ = getattr(np, f) if 'axis' != inspect.getargs(f_.__code__).args[1]: # if 'axis' is not the 2nd arg -- skip return except: return # so we got a function which has 'axis' argument for naxis in (0, 1): # check on both axes for do_group in (False, True): # test with # groupping and without kwargs = dict(attrfx='merge') if do_group: if naxis == 0: kwargs['uattrs'] = ('targets', 'chunks') else: kwargs['uattrs'] = ('nonbogus_targets', ) axis = ('samples', 'features')[naxis] def custom(data): """So we could enforce apply_along_axis """ # always 0 since it would be the job for apply_along_axis return f_(data, axis=0) try: m2 = FxMapper(axis, custom, **kwargs) dsm2 = ds.get_mapped(m2) except: # We assume that our previous implementation should work ;-) continue m1 = FxMapper(axis, f_, **kwargs) dsm1 = ds.get_mapped(m1) if dsm2.samples.dtype == object: # assert_array_almost_equal does not always work # for object arrays assert_samples_equal = assert_objectarray_equal else: # deal with potential rounding errors assert_samples_equal = assert_array_almost_equal assert_samples_equal(dsm1.samples, dsm2.samples) # test other attributes assert_array_equal(dsm1.targets, dsm2.targets) assert_array_equal(dsm1.chunks, dsm2.chunks) assert_array_equal(dsm1.fa.nonbogus_targets, dsm2.fa.nonbogus_targets)
def test_inspect(self): if not hasattr(len, 'func_code'): skip("Cannot run this test if builtins have no func_code") import inspect args, varargs, varkw = inspect.getargs(len.func_code) assert args == ['obj'] assert varargs is None assert varkw is None
def from_code(cls, code, copy_lineno=False): import inspect self = cls.from_spec(code.co_name, *inspect.getargs(code)) if copy_lineno: self.set_lineno(code.co_firstlineno) self.co_filename = code.co_filename self.co_freevars = code.co_freevars # XXX untested! return self
def get_arguments(code): arguments = getargs(code) for arg in flatten(arguments.args): yield '', arg if arguments.varargs: yield '*', arguments.varargs if arguments.keywords: yield '**', arguments.keywords
def beautify_args(): arg_names = inspect.getargs(frame.f_code).args local_vals = inspect.getargvalues(frame).locals arg_dict = {name: frame.f_locals[name] for name in arg_names} text = '' for name, value in arg_dict.items(): text += beautify_variable(name, value) + ', ' return text[:-2]
def exception_handler(e): tb = get_current_traceback() last_frame = tb.frames[-1] last_frame_args = inspect.getargs(last_frame.code) return render_template('show_error.html', tb=tb, last_frame=last_frame, last_frame_args=last_frame_args), 500
def test_inspect(self): if not hasattr(len, 'func_code'): skip("CPython: no func_code attribute on built-in functions") import inspect args, varargs, varkw = inspect.getargs(len.func_code) assert args == ['obj'] assert varargs is None assert varkw is None
def __repr__(self): args = _inspect.getargs( ABCApplicationPolicy.__init__.__code__).args[1:] return "<{cls}({spec})>".format( cls=self.__class__.__name__, spec=", ".join("{0}={1!r}".format(arg, getattr(self, arg)) for arg in args))
def test_inspect(self): if not hasattr(len, 'func_code'): skip("Cannot run this test if builtins have no func_code") import inspect args, varargs, varkw = inspect.getargs(len.__code__) assert args == ['obj'] assert varargs is None assert varkw is None
def check_docstring(f): """ Ensure the docstring of `f` is in accordance with the numpy standard Currently, only the Parameters section of the docstring is checked. Parameters ---------- f : function, method, class Returns ------- repr : string A string represntation """ doc = getdoc(f) if doc is None: if error_on_none: raise ValueError('no docstring for %s' % format(f)) else: with warnings.catch_warnings(): warnings.simplefilter('error') parsed = NumpyDocString(doc) param_names = set([e[0] for e in parsed['Parameters']]) if isbuiltin(f): # You can't get the arglist from a builtin, which # is how cython functions turn up # but you can, hackily, get the number of arguments it wants # by parseing the error hen you supply too many import re try: f(*list(range(100))) except TypeError as e: m = re.search('takes at most (\d+) positional arguments', str(e)) if not m: return n_args = int(m.group(1)) if len(param_names) != n_args: raise ValueError("In %s, number of arguments, %d, doesn't " " match the length of the Parameters in the " "docstring, %d" % (format(f), n_args, len(param_names))) return args = set(getargs(get_function_code(f)).args) if 'self' in args: args.remove('self') if 'cls' in args: args.remove('cls') if args != param_names: raise ValueError("In %s, arguments %s don't " "match Parameters list %s" % (format(f), list(args), list(param_names)))
def __call__(self, func): retvalue = self.opts.get("retvalue", None) if retvalue is opitypes.VectorType: retvalue = opitypes.VectorValue fargs = inspect.getargs(func.func_code)[0] args = [VarRef(arg, typ) for arg, typ in zip(fargs, self.types)] code = func.func_code names = code.co_names dct = {} dct.update(func.func_globals) for n in names: if n in opiexpr.__all__: dct[n] = getattr(opiexpr, n) elif n not in func.func_globals: dct[n] = VarRef(n) dct["Return"] = opiexpr.Return(retvalue) newfunc = new.function(code, dct, func.func_name, closure=func.func_closure) #args = dict((arg,VarRef(arg,typ)) for arg,typ in zip(args,self.types)) statements = newfunc(*args) ops = [] for a in reversed(args): ops.append( opcode("setvar" + a._type.varcode, a._name, None, -a._type.stacksize)) for s in statements: try: ops.extend(s._get_stmt_ops()) except: t, v, tb = sys.exc_info() for l in traceback.format_list(s._tb): sys.stderr.write(l) for l in traceback.format_exception_only(t, v): sys.stderr.write(l) tb = None raise return if not ops or ops[-1][0] != "exit": if retvalue is not None: ops.extend(opiexpr._get_ops(retvalue.default)) ops.append(opcode("exit")) cc = CompilerFrame() cc.stack = sum(a._type.stacksize for a in args) cc.max_stack = cc.stack cc.debugout = self.opts.get("debugout", False) for op in ops: cc.compile(op) if cc.debugout: print "max. stack usage: %i bytes" % cc.max_stack print cc.__dict__ code = O2DCode(cc) code.retvalue = retvalue code.argspec = self.types return code
def _get_main_source(function): main_source = u'def azureml_main(df1 = None, df2 = None):\n' main_source += u' results = []\n' if _get_dataframe_schema(function): # function just takes a dataframe... main_source += u' results.append(__user_function(df1))' + chr(10) else: # we're marshalling the arguments in. main_source += u' for i in range(df1.shape[0]):' + chr(10) for arg in _get_args(function): arg_type = _get_arg_type(arg, function) if pandas is not None and arg_type is pandas.DataFrame: raise Exception('Only a single DataFrame argument is supported') if _get_arg_type(arg, function) == OBJECT_NAME: main_source += ' ' + arg + u' = ' + u'_decode(df1["' + arg + u'"][i])' + chr(10) else: main_source += ' ' + arg + u' = ' + u'df1["' + arg + u'"][i]' + chr(10) main_source += u' results.append(__user_function(' args = inspect.getargs(function.__code__) all_args = args.args if args.varargs is not None: all_args.append(u'*' + args.varargs) if args.keywords is not None: all_args.append(u'**' + args.keywords) # pass position arguments... main_source += u', '.join(all_args) main_source += u'))' + chr(10) ret_annotation = _get_annotation('return', function) if _get_dataframe_schema(function): # function just returns a data frame directly main_source += u' if len(results) == 1:' + chr(10) main_source += u' return results[0]' + chr(10) main_source += u' return pandas.DataFrame(results)' + chr(10) elif isinstance(ret_annotation, tuple): # multi-value return support... format = [] arg_names = [] for index, ret_type in enumerate(ret_annotation): arg_names.append(u'r' + str(index)) t = _annotation_to_type(ret_type) if t == OBJECT_NAME: format.append(u'_encode(r' + str(index) + u')') else: format.append(u'r' + str(index)) main_source += u' return pandas.DataFrame([(' + u', '.join(format) + u') for ' + ', '.join(arg_names) + u' in results])' + chr(10) elif _get_arg_type('return', function) == OBJECT_NAME: main_source += u' return pandas.DataFrame([_encode(r) for r in results])' + chr(10) else: main_source += u' return pandas.DataFrame(results)' + chr(10) return main_source
def is_handler_method_args_valid( class_handler: Any, method: Callable, method_name: str ): if "onebot" in method_name: mapping = ONEBOTV11_KWARGS_MAPPING event_name = method_name.replace("onebot_", "") elif "keaimao" in method_name: mapping = KEAIMAO_KWARGS_MAPPING event_name = method_name.replace("keaimao_", "") else: mapping = UNIVERSAL_KWARGS_MAPPING event_name = method_name kwarg_name_type_mapping, usable_kwargs_hint = gen_usable_kwargs_hint( mapping, event_name ) usable_kwarg_names = kwarg_name_type_mapping.keys() source_file_name = inspect.getsourcefile(class_handler) class_handler_name = class_handler.__name__ common_prefix = ( f"\n{source_file_name}文件中的类响应器{class_handler_name}的" + f"{method_name}事件" ) all_args, var_args, var_kwargs = inspect.getargs(method.__code__) if var_args or var_kwargs: raise InitializationError( common_prefix + "不需要提供*或者**参数,PepperBot会自动根据声明的参数以及类型注入" + usable_kwargs_hint ) for arg_name in all_args[1:]: # 第一个是self if arg_name not in usable_kwarg_names: raise InitializationError( common_prefix + f"上不存在参数{arg_name}" + usable_kwargs_hint ) if arg_name not in method.__annotations__.keys(): raise InitializationError( common_prefix + f"的参数{arg_name}未提供类型注解,其类型为{kwarg_name_type_mapping[arg_name]}" + usable_kwargs_hint ) # 经过上两步验证,此时的参数,一定是有效的,而且有类型注解 for arg_name, arg_type in method.__annotations__.items(): supposed_arg_type = kwarg_name_type_mapping[arg_name] is_kwarg_annotation_correct( arg_name, arg_type, supposed_arg_type, common_prefix )
def test_fx_native_calls(f): import inspect ds = datasets['uni2small'] if f in ['size', 'rollaxis']: # really not appropriate ones here to test return try: f_ = getattr(np, f) if 'axis' != inspect.getargs(f_.__code__).args[1]: # if 'axis' is not the 2nd arg -- skip return except: return # so we got a function which has 'axis' arugment for naxis in (0, 1): # check on both axes for do_group in (False, True): # test with # groupping and without kwargs = dict(attrfx='merge') if do_group: if naxis == 0: kwargs['uattrs'] = ('targets', 'chunks') else: kwargs['uattrs'] = ('nonbogus_targets',) axis = ('samples', 'features')[naxis] def custom(data): """So we could enforce apply_along_axis """ # always 0 since it would be the job for apply_along_axis return f_(data, axis=0) try: m2 = FxMapper(axis, custom, **kwargs) dsm2 = ds.get_mapped(m2) except: # We assume that our previous implementation should work ;-) continue m1 = FxMapper(axis, f_, **kwargs) dsm1 = ds.get_mapped(m1) if dsm2.samples.dtype == object: # assert_array_almost_equal does not always work # for object arrays assert_samples_equal = assert_objectarray_equal else: # deal with potential rounding errors assert_samples_equal = assert_array_almost_equal assert_samples_equal(dsm1.samples, dsm2.samples) # test other attributes assert_array_equal(dsm1.targets, dsm2.targets) assert_array_equal(dsm1.chunks, dsm2.chunks) assert_array_equal(dsm1.fa.nonbogus_targets, dsm2.fa.nonbogus_targets)
def _verify_metric_fn_args(metric_fn): if not metric_fn: return # Calling low level getargs for py_2_and_3 compatibility. args = set(inspect.getargs(metric_fn.__code__).args) invalid_args = list(args - _VALID_METRIC_FN_ARGS) if invalid_args: raise ValueError("metric_fn (%s) has following not expected args: %s" % (metric_fn, invalid_args))
def __init__(self, f, dir='func_persist'): self.__func = f self.__dir = dir if not os.path.exists(dir): os.makedirs(dir) self.__doc__ = '%s%s%s'%(\ f.func_name, inspect.formatargspec(*inspect.getargs(f.func_code)), f.__doc__)
def __init__(self, f, dir='func_persist'): from sage.misc.misc import sage_makedirs self.__func = f self.__dir = dir sage_makedirs(dir) self.__doc__ = '%s%s%s'%(\ f.__name__, inspect.formatargspec(*inspect.getargs(f.__code__)), f.__doc__)
def assertApplicationEqual(self, app1, app2, msg=None): args = _inspect.getargs(ABCApplication.__init__.__code__).args[1:] for arg in args: if arg == 'id': # Skip the id because our comparison objects may not have them. continue if getattr(app1, arg) != getattr(app2, arg): raise self.failureException(msg)
def __init__(self, f, dir='func_persist'): from sage.misc.misc import sage_makedirs self.__func = f self.__dir = dir sage_makedirs(dir) self.__doc__ = '%s%s%s'%(\ f.func_name, inspect.formatargspec(*inspect.getargs(f.func_code)), f.__doc__)
def exception_handler(e): tb = get_current_traceback() last_frame = next(frame for frame in reversed(tb.frames) if not frame.is_library) last_frame_args = inspect.getargs(last_frame.code) return render_template('show_error.html', tb=tb, last_frame=last_frame, last_frame_args=last_frame_args), 500
def sage_getargspec(obj): r""" Return the names and default values of a function'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 an n-tuple of the default values of the last n arguments. AUTHOR: -- William Stein: a modified version of inspect.getargspec from the Python Standard Library, which was taken from IPython for use in SAGE. -- Extensions by Nick Alexander """ if not callable(obj): raise TypeError, "obj is not a code object" if inspect.isfunction(obj): func_obj = obj elif inspect.ismethod(obj): func_obj = obj.im_func elif isclassinstance(obj): return sage_getargspec(obj.__class__.__call__) elif inspect.isclass(obj): return sage_getargspec(obj.__call__) else: # Perhaps it is binary and defined in a Cython file source = sage_getsource(obj, is_binary=True) if source: return _sage_getargspec_cython(source) else: func_obj = obj # Otherwise we're (hopefully!) plain Python, so use inspect try: args, varargs, varkw = inspect.getargs(func_obj.func_code) except AttributeError: args, varargs, varkw = inspect.getargs(func_obj) try: defaults = func_obj.func_defaults except AttributeError: defaults = tuple([]) return args, varargs, varkw,