def test_dc_on_top_of_non_dc(self, decl_base: Type[DeclarativeBase]): class Person(decl_base): __tablename__ = "person" person_id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] type: Mapped[str] = mapped_column() __mapper_args__ = {"polymorphic_on": type} class Engineer(MappedAsDataclass, Person): __tablename__ = "engineer" person_id: Mapped[int] = mapped_column( ForeignKey("person.person_id"), primary_key=True, init=False ) status: Mapped[str] = mapped_column(String(30)) engineer_name: Mapped[str] primary_language: Mapped[str] e1 = Engineer("st", "en", "pl") eq_(e1.status, "st") eq_(e1.engineer_name, "en") eq_(e1.primary_language, "pl") eq_( pyinspect.getfullargspec(Person.__init__), # the boring **kw __init__ pyinspect.FullArgSpec( args=["self"], varargs=None, varkw="kwargs", defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}, ), ) eq_( pyinspect.getfullargspec(Engineer.__init__), # the exciting dataclasses __init__ pyinspect.FullArgSpec( args=["self", "status", "engineer_name", "primary_language"], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}, ), )
def getargspec(func): """Like inspect.getargspec but supports functools.partial as well.""" if inspect.ismethod(func): func = func.__func__ if type(func) is partial: orig_func = func.func argspec = getargspec(orig_func) args = list(argspec[0]) defaults = list(argspec[3] or ()) kwoargs = list(argspec[4]) kwodefs = dict(argspec[5] or {}) if func.args: args = args[len(func.args):] for arg in func.keywords or (): try: i = args.index(arg) - len(args) del args[i] try: del defaults[i] except IndexError: pass except ValueError: # must be a kwonly arg i = kwoargs.index(arg) del kwoargs[i] del kwodefs[arg] return inspect.FullArgSpec(args, argspec[1], argspec[2], tuple(defaults), kwoargs, kwodefs, argspec[6]) while hasattr(func, '__wrapped__'): func = func.__wrapped__ if not inspect.isfunction(func): raise TypeError('%r is not a Python function' % func) return inspect.getfullargspec(func)
def getargspec(func: Callable) -> Any: """Like inspect.getfullargspec but supports bound methods, and wrapped methods.""" warnings.warn('sphinx.ext.inspect.getargspec() is deprecated', RemovedInSphinx50Warning, stacklevel=2) # On 3.5+, signature(int) or similar raises ValueError. On 3.4, it # succeeds with a bogus signature. We want a TypeError uniformly, to # match historical behavior. if (isinstance(func, type) and is_builtin_class_method(func, "__new__") and is_builtin_class_method(func, "__init__")): raise TypeError( "can't compute signature for built-in type {}".format(func)) sig = inspect.signature(func) args = [] varargs = None varkw = None kwonlyargs = [] defaults = () annotations = {} defaults = () kwdefaults = {} if sig.return_annotation is not sig.empty: annotations['return'] = sig.return_annotation for param in sig.parameters.values(): kind = param.kind name = param.name if kind is Parameter.POSITIONAL_ONLY: args.append(name) elif kind is Parameter.POSITIONAL_OR_KEYWORD: args.append(name) if param.default is not param.empty: defaults += (param.default, ) # type: ignore elif kind is Parameter.VAR_POSITIONAL: varargs = name elif kind is Parameter.KEYWORD_ONLY: kwonlyargs.append(name) if param.default is not param.empty: kwdefaults[name] = param.default elif kind is Parameter.VAR_KEYWORD: varkw = name if param.annotation is not param.empty: annotations[name] = param.annotation if not kwdefaults: # compatibility with 'func.__kwdefaults__' kwdefaults = None if not defaults: # compatibility with 'func.__defaults__' defaults = None return inspect.FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwdefaults, annotations)
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 visit_FunctionDef(self, node): """ Save an argSpec for user defined functions """ args = [a.arg for a in node.args.args] if node.args.kwonlyargs: raise ParseError( f"Keyword-only arguments not supported in Zbursh: def {node.name}, line {node.lineno}" ) if node.args.vararg: raise ParseError( f"Variable arguments not supported in Zbursh: def {node.name}, line {node.lineno}" ) if node.args.kw_defaults: raise ParseError( f"keyword default arguments not supported in Zbrush: def {node.name}, line {node.lineno}" ) if node.args.defaults: raise ParseError( f"default arguments not supported in Zbrush: def {node.name}, line {node.lineno}" ) if node.args.kwarg: raise ParseError( f"keyword arguments not allowed in Zbrush user : def {node.name}, line {node.lineno}" ) self.user_functions[node.name] = inspect.FullArgSpec( args=args, varargs=None, varkw=None, defaults=None, kwonlyargs=None, kwonlydefaults=None, annotations={})
def getargspec(func: Callable) -> Any: """Like inspect.getfullargspec but supports bound methods, and wrapped methods.""" warnings.warn('sphinx.ext.inspect.getargspec() is deprecated', RemovedInSphinx50Warning, stacklevel=2) sig = inspect.signature(func) args = [] varargs = None varkw = None kwonlyargs = [] defaults = () annotations = {} defaults = () kwdefaults = {} if sig.return_annotation is not sig.empty: annotations['return'] = sig.return_annotation for param in sig.parameters.values(): kind = param.kind name = param.name if kind is Parameter.POSITIONAL_ONLY: args.append(name) elif kind is Parameter.POSITIONAL_OR_KEYWORD: args.append(name) if param.default is not param.empty: defaults += (param.default, ) # type: ignore elif kind is Parameter.VAR_POSITIONAL: varargs = name elif kind is Parameter.KEYWORD_ONLY: kwonlyargs.append(name) if param.default is not param.empty: kwdefaults[name] = param.default elif kind is Parameter.VAR_KEYWORD: varkw = name if param.annotation is not param.empty: annotations[name] = param.annotation if not kwdefaults: # compatibility with 'func.__kwdefaults__' kwdefaults = None if not defaults: # compatibility with 'func.__defaults__' defaults = None return inspect.FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwdefaults, annotations)
def _gen_callable_matrix_adapter(self, f_spec): f_args_spec_struct = OrderedStructDict( f_spec.arg_spec._asdict()).deepcopy() f_args_spec_struct.kwonlyargs.append('param_struct') if f_args_spec_struct.kwonlydefaults: f_args_spec_struct.kwonlydefaults.update({'param_struct': None}) else: f_args_spec_struct.kwonlydefaults = {'param_struct': None} f_args_spec = inspect.FullArgSpec(**f_args_spec_struct) adapter = make_function(f_args_spec, name='adapter') return adapter
def test_getfullargspec(): instance = Instance(TEST_BYTES) assert instance.exports.sum.getfullargspec == inspect.FullArgSpec( args=['x0', 'x1'], varargs=None, varkw=None, defaults=None, kwonlyargs=None, kwonlydefaults=None, annotations={ 'x0': Type.I32, 'x1': Type.I32, 'return': Type.I32 })
def getargspec(func): """Like inspect.getfullargspec but supports bound methods, and wrapped methods.""" sig = inspect.signature(func) args = [] varargs = None varkw = None kwonlyargs = [] defaults = () annotations = {} defaults = () kwdefaults = {} if sig.return_annotation is not sig.empty: annotations['return'] = sig.return_annotation for param in sig.parameters.values(): kind = param.kind name = param.name if kind is inspect.Parameter.POSITIONAL_ONLY: args.append(name) elif kind is inspect.Parameter.POSITIONAL_OR_KEYWORD: args.append(name) if param.default is not param.empty: defaults += (param.default,) elif kind is inspect.Parameter.VAR_POSITIONAL: varargs = name elif kind is inspect.Parameter.KEYWORD_ONLY: kwonlyargs.append(name) if param.default is not param.empty: kwdefaults[name] = param.default elif kind is inspect.Parameter.VAR_KEYWORD: varkw = name if param.annotation is not param.empty: annotations[name] = param.annotation if not kwdefaults: # compatibility with 'func.__kwdefaults__' kwdefaults = None if not defaults: # compatibility with 'func.__defaults__' defaults = None return inspect.FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwdefaults, annotations)
def test_signature(methods, method, arguments): methods.remove(method) args = { "args": ["self"], "varargs": None, "varkw": None, "defaults": None, "kwonlyargs": [], "kwonlydefaults": None, "annotations": {}, **arguments } sig = inspect.FullArgSpec(**args) spec = inspect.getfullargspec(getattr(ThermalPrinter, method)) assert spec == sig
def arginfo(callable): """Get information about the arguments of a callable. Returns a :class:`inspect.FullArgSpec` object as for :func:`inspect.getfullargspec`. :func:`inspect.getfullargspec` returns information about the arguments of a function. arginfo also works for classes and instances with a __call__ defined. Unlike getfullargspec, arginfo treats bound methods like functions, so that the self argument is not reported. arginfo returns ``None`` if given something that is not callable. arginfo caches previous calls (except for instances with a __call__), making calling it repeatedly cheap. This was originally inspired by the pytest.core varnames() function, but has been completely rewritten to handle class constructors, also show other getarginfo() information, and for readability. """ try: return arginfo._cache[callable] except KeyError: # Try to get __call__ function from the cache. try: return arginfo._cache[callable.__call__] except (AttributeError, KeyError): pass func, cache_key, remove_self = get_callable_info(callable) if func is None: return None result = inspect.getfullargspec(func) if remove_self: args = result.args[1:] result = inspect.FullArgSpec( args, result.varargs, result.varkw, result.defaults, result.kwonlyargs, result.kwonlydefaults, result.annotations, ) arginfo._cache[cache_key] = result return result
def getfullargspec(func): if func in (_np.empty_like, _np.ones_like, _np.zeros_like): if func is _np.empty_like: sig = inspect._signature_fromstr( inspect.Signature, func, func.__doc__.strip().split('\n', maxsplit=1)[0]) else: sig = inspect.signature(func) return inspect.FullArgSpec( list(sig.parameters.keys()), # args None, # varargs None, # varkw tuple(v.default for v in sig.parameters.values() if v.default is not inspect._empty), # defaults [], # knwonlyargs {}, # kwonlydefaults {}, # annotations ) else: return _inspect_getfullargspec(func)
def get_cached_func_spec(func, bypass_cache=False, reset_cache=False, clear_cache=False): try: f_spec = func._f_spec if f_spec is not None and not any((bypass_cache, reset_cache, clear_cache)): return func._f_spec # use cached _f_spec except AttributeError: pass f_signature = inspect.signature(func) f_args_spec_dict = OrderedDict(inspect.getfullargspec(func)._asdict()) if isinstance(func, types.MethodType): f_args_spec_dict['args'] = f_args_spec_dict['args'][1:] f_args_spec = inspect.FullArgSpec(**f_args_spec_dict) f_pos_only_params = [param_name for param_name, param in f_signature.parameters.items() if param.kind is Parameter.POSITIONAL_ONLY] f_pos_or_kw_params = [param_name for param_name, param in f_signature.parameters.items() if param.kind is Parameter.POSITIONAL_OR_KEYWORD] f_kw_only_params = [param_name for param_name, param in f_signature.parameters.items() if param.kind is Parameter.KEYWORD_ONLY] f_all_kw_params = f_pos_or_kw_params + f_kw_only_params f_all_kw_default = {param_name: param.default for param_name, param in f_signature.parameters.items() if param.default is not Parameter.empty} f_type = type(func) f_spec = _FSpecNamedTup(f_signature, f_args_spec, f_pos_only_params, f_pos_or_kw_params, f_kw_only_params, f_all_kw_params, f_all_kw_default, f_type) cache_f_spec = f_spec if not clear_cache else None if (not bypass_cache) or reset_cache or clear_cache: if isinstance(func, types.MethodType): func.__func__._f_spec = cache_f_spec # cache f_spec as function attribute else: func._f_spec = cache_f_spec return f_spec
def getfullargspec(func): """Get the names and default values of a function's arguments. A tuple of seven things is returned: (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults annotations). '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. 'kwonlyargs' is a list of keyword-only argument names. 'kwonlydefaults' is a dictionary mapping names from kwonlyargs to defaults. 'annotations' is a dictionary mapping argument names to annotations. The first four items in the tuple correspond to getargspec(). """ if inspect.ismethod(func): func = func.__func__ if not inspect.isfunction(func): raise TypeError('arg is not a Python function') args, varargs, kwonlyargs, varkw = inspect._getfullargs( sys.get_func_code(func)) return inspect.FullArgSpec(args, varargs, varkw, func.__defaults__, kwonlyargs, func.__kwdefaults__, func.__annotations__)
def test_basic_constructor_repr_base_cls( self, dc_decl_base: Type[MappedAsDataclass] ): class A(dc_decl_base): __tablename__ = "a" id: Mapped[int] = mapped_column(primary_key=True, init=False) data: Mapped[str] x: Mapped[Optional[int]] = mapped_column(default=None) bs: Mapped[List["B"]] = relationship( # noqa: F821 default_factory=list ) class B(dc_decl_base): __tablename__ = "b" id: Mapped[int] = mapped_column(primary_key=True, init=False) data: Mapped[str] a_id: Mapped[Optional[int]] = mapped_column( ForeignKey("a.id"), init=False ) x: Mapped[Optional[int]] = mapped_column(default=None) A.__qualname__ = "some_module.A" B.__qualname__ = "some_module.B" eq_( pyinspect.getfullargspec(A.__init__), pyinspect.FullArgSpec( args=["self", "data", "x", "bs"], varargs=None, varkw=None, defaults=(None, mock.ANY), kwonlyargs=[], kwonlydefaults=None, annotations={}, ), ) eq_( pyinspect.getfullargspec(B.__init__), pyinspect.FullArgSpec( args=["self", "data", "x"], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={}, ), ) a2 = A("10", x=5, bs=[B("data1"), B("data2", x=12)]) eq_( repr(a2), "some_module.A(id=None, data='10', x=5, " "bs=[some_module.B(id=None, data='data1', a_id=None, x=None), " "some_module.B(id=None, data='data2', a_id=None, x=12)])", ) a3 = A("data") eq_(repr(a3), "some_module.A(id=None, data='data', x=None, bs=[])")
def has_type_depth(val, ty, depth): if depth > flags.CHECK_DEPTH: return True elif ty is TypeVariable: return True elif ty is Self: return True elif ty is Dyn: return True elif ty is InferBottom: return False elif ty is Void: return val == None elif ty is Int: return isinstance(val, int) or (not flags.FLAT_PRIMITIVES and has_type(val, Bool)) elif ty is Bytes: return isinstance(val, bytes) elif ty is Bool: return isinstance(val, bool) elif ty is Float: return isinstance(val, float) or (not flags.FLAT_PRIMITIVES and has_type(val, Int)) elif ty is Complex: return isinstance(val, complex) or (not flags.FLAT_PRIMITIVES and has_type(val, Float)) elif ty is String: return isinstance(val, str) elif isinstance(ty, Function): if callable(val): return True else: return False if val.__class__ is types.MethodType: # Only true for bound methods spec = getfullargspec(val) new_spec = inspect.FullArgSpec(spec.args[1:], spec.varargs, spec.varkw, spec.defaults, spec.kwonlyargs, spec.kwonlydefaults, spec.annotations) return func_has_type(new_spec, ty) elif val.__class__ is types.FunctionType: # Normal function return func_has_type(getfullargspec(val), ty) elif val.__class__ is type: if val.__init__.__class__ is types.FunctionType: spec = getfullargspec(val.__init__) new_spec = inspect.FullArgSpec(spec.args[1:], spec.varargs, spec.varkw, spec.defaults, spec.kwonlyargs, spec.kwonlydefaults, spec.annotations) return func_has_type(new_spec, ty) else: return True elif val.__class__ is types.BuiltinFunctionType: return True elif hasattr(val, '__call__'): if val.__call__.__class__ is types.MethodType: spec = getfullargspec(val.__call__) new_spec = inspect.FullArgSpec(spec.args[1:], spec.varargs, spec.varkw, spec.defaults, spec.kwonlyargs, spec.kwonlydefaults, spec.annotations) return func_has_type(new_spec, ty) else: return True elif callable(val): return True # No clue else: return False elif isinstance(ty, List): return (isinstance(val, list)) # and \ # all(map(lambda x: has_type_depth(x, ty.type, depth+1), val)) elif isinstance(ty, Set): return isinstance(val, set) and \ all(map(lambda x: has_type_depth(x, ty.type, depth+1), val)) elif isinstance(ty, Dict): return isinstance(val, dict)# and \ # all(map(lambda x: has_type_depth(x, ty.keys, depth+1), val.keys())) and \ # all(map(lambda x: has_type_depth(x, ty.values, depth+1), val.values())) elif isinstance(ty, Tuple): return (isinstance(val, tuple) or isinstance(val, list))# \ # and len(ty.elements) == len(val) and \ # all(map(lambda p: has_type_depth(p[0], p[1], depth+1), zip(val, ty.elements))) # elif isinstance(ty, Iterable): # if (isinstance(val, tuple) or isinstance(val, list) or isinstance(val, set)) or iter(val) is not val: # return all(map(lambda x: has_type_depth(x, ty.type, depth+1), val)) # elif isinstance(val, collections.Iterable): # if hasattr(val, '__iter__'): # return has_type_depth(val.__iter__, Function([Dyn], Iterable(ty.type)), depth+1) # else: return True # else: return False elif isinstance(ty, Object): for k in ty.members: if not hasattr(val, k):# or not has_type_depth(getattr(val, k), ty.members[k], depth+1): return False return True elif isinstance(ty, Class): for k in ty.members: if not hasattr(val, k):# or not has_type_depth(getattr(val, k), ty.members[k], depth+1): return False return isinstance(val, type) else: raise UnknownTypeError('Unknown type ', ty)
def custom_getfullargspec(func): """Taken from CPython inspect.getfullargspec: The method is deprecated and uses skip_bound_args=False and follow_wrapped_chains=False because it was legacy behavior We need the opposite to follow the wrapped methods, and skip the bound arguments instead of manually removing them """ try: sig = inspect._signature_from_callable(func, skip_bound_arg=True, follow_wrapper_chains=True, sigcls=inspect.Signature) except Exception as ex: # Most of the times 'signature' will raise ValueError. # But, it can also raise AttributeError, and, maybe something # else. So to be fully backwards compatible, we catch all # possible exceptions here, and reraise a TypeError. raise TypeError('unsupported callable') from ex args = [] varargs = None varkw = None kwonlyargs = [] defaults = () annotations = {} defaults = () kwdefaults = {} if sig.return_annotation is not sig.empty: annotations['return'] = sig.return_annotation for param in sig.parameters.values(): kind = param.kind name = param.name if kind is inspect._POSITIONAL_ONLY: args.append(name) elif kind is inspect._POSITIONAL_OR_KEYWORD: args.append(name) if param.default is not param.empty: defaults += (param.default, ) elif kind is inspect._VAR_POSITIONAL: varargs = name elif kind is inspect._KEYWORD_ONLY: kwonlyargs.append(name) if param.default is not param.empty: kwdefaults[name] = param.default elif kind is inspect._VAR_KEYWORD: varkw = name if param.annotation is not param.empty: annotations[name] = param.annotation if not kwdefaults: # compatibility with 'func.__kwdefaults__' kwdefaults = None if not defaults: # compatibility with 'func.__defaults__' defaults = None return inspect.FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwdefaults, annotations)
def test_basic_constructor_repr_cls_decorator( self, registry: _RegistryType ): @registry.mapped_as_dataclass() class A: __tablename__ = "a" id: Mapped[int] = mapped_column(primary_key=True, init=False) data: Mapped[str] x: Mapped[Optional[int]] = mapped_column(default=None) bs: Mapped[List["B"]] = relationship( # noqa: F821 default_factory=list ) @registry.mapped_as_dataclass() class B: __tablename__ = "b" id: Mapped[int] = mapped_column(primary_key=True, init=False) a_id = mapped_column(ForeignKey("a.id"), init=False) data: Mapped[str] x: Mapped[Optional[int]] = mapped_column(default=None) A.__qualname__ = "some_module.A" B.__qualname__ = "some_module.B" eq_( pyinspect.getfullargspec(A.__init__), pyinspect.FullArgSpec( args=["self", "data", "x", "bs"], varargs=None, varkw=None, defaults=(None, mock.ANY), kwonlyargs=[], kwonlydefaults=None, annotations={}, ), ) eq_( pyinspect.getfullargspec(B.__init__), pyinspect.FullArgSpec( args=["self", "data", "x"], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={}, ), ) a2 = A("10", x=5, bs=[B("data1"), B("data2", x=12)]) # note a_id isn't included because it wasn't annotated eq_( repr(a2), "some_module.A(id=None, data='10', x=5, " "bs=[some_module.B(id=None, data='data1', x=None), " "some_module.B(id=None, data='data2', x=12)])", ) a3 = A("data") eq_(repr(a3), "some_module.A(id=None, data='data', x=None, bs=[])")
def test_integrated_dc(self, dc_decl_base: Type[MappedAsDataclass]): """We will be telling users "this is a dataclass that is also mapped". Therefore, they will want *any* kind of attribute to do what it would normally do in a dataclass, including normal types without any field and explicit use of dataclasses.field(). additionally, we'd like ``Mapped`` to mean "persist this attribute". So the absence of ``Mapped`` should also mean something too. """ class A(dc_decl_base): __tablename__ = "a" ctrl_one: str = dataclasses.field() id: Mapped[int] = mapped_column(primary_key=True, init=False) data: Mapped[str] some_field: int = dataclasses.field(default=5) some_none_field: Optional[str] = dataclasses.field(default=None) some_other_int_field: int = 10 # some field is part of the constructor a1 = A("ctrlone", "datafield") eq_( dataclasses.asdict(a1), { "ctrl_one": "ctrlone", "data": "datafield", "id": None, "some_field": 5, "some_none_field": None, "some_other_int_field": 10, }, ) a2 = A( "ctrlone", "datafield", some_field=7, some_other_int_field=12, some_none_field="x", ) eq_( dataclasses.asdict(a2), { "ctrl_one": "ctrlone", "data": "datafield", "id": None, "some_field": 7, "some_none_field": "x", "some_other_int_field": 12, }, ) # only Mapped[] is mapped self.assert_compile(select(A), "SELECT a.id, a.data FROM a") eq_( pyinspect.getfullargspec(A.__init__), pyinspect.FullArgSpec( args=[ "self", "ctrl_one", "data", "some_field", "some_none_field", "some_other_int_field", ], varargs=None, varkw=None, defaults=(5, None, 10), kwonlyargs=[], kwonlydefaults=None, annotations={}, ), )
def Py3GetFullArgSpec(fn): """A alternative to the builtin getfullargspec. The builtin inspect.getfullargspec uses: `skip_bound_args=False, follow_wrapped_chains=False` in order to be backwards compatible. This function instead skips bound args (self) and follows wrapped chains. Args: fn: The function or class of interest. Returns: An inspect.FullArgSpec namedtuple with the full arg spec of the function. """ # pylint: disable=no-member # pytype: disable=module-attr try: sig = inspect._signature_from_callable( # pylint: disable=protected-access fn, skip_bound_arg=True, follow_wrapper_chains=True, sigcls=inspect.Signature) except Exception: # 'signature' can raise ValueError (most common), AttributeError, and # possibly others. We catch all exceptions here, and reraise a TypeError. raise TypeError('Unsupported callable.') args = [] varargs = None varkw = None kwonlyargs = [] defaults = () annotations = {} defaults = () kwdefaults = {} if sig.return_annotation is not sig.empty: annotations['return'] = sig.return_annotation for param in sig.parameters.values(): kind = param.kind name = param.name # pylint: disable=protected-access if kind is inspect._POSITIONAL_ONLY: args.append(name) elif kind is inspect._POSITIONAL_OR_KEYWORD: args.append(name) if param.default is not param.empty: defaults += (param.default, ) elif kind is inspect._VAR_POSITIONAL: varargs = name elif kind is inspect._KEYWORD_ONLY: kwonlyargs.append(name) if param.default is not param.empty: kwdefaults[name] = param.default elif kind is inspect._VAR_KEYWORD: varkw = name if param.annotation is not param.empty: annotations[name] = param.annotation # pylint: enable=protected-access if not kwdefaults: # compatibility with 'func.__kwdefaults__' kwdefaults = None if not defaults: # compatibility with 'func.__defaults__' defaults = None return inspect.FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwdefaults, annotations)