def test__call__vpo_param_mapped(self, vary_name): """ Ensure ``var-positional`` params are directly mapped (w/ and w/o varied name) """ from_name, to_name = ('p1', 'p1') if not vary_name else ('p1', 'p2') fsig = FSignature([FParameter(VAR_POSITIONAL, from_name, to_name)]) func = lambda: None func.__signature__ = \ inspect.Signature([inspect.Parameter(to_name, VAR_POSITIONAL)]) mapper = Mapper(fsig, func) call_args = CallArguments(1, 2, 3) assert mapper(*call_args.args) == call_args
def _np_signature(f): """An enhanced inspect.signature that can handle numpy.ufunc.""" # TODO(wangpeng): consider migrating away from inspect.signature. # inspect.signature is supported in Python 3.3. if not hasattr(inspect, 'signature'): return None if f is None: return None if not isinstance(f, np.ufunc): try: return inspect.signature(f) except ValueError: return None def names_from_num(prefix, n): if n <= 0: return [] elif n == 1: return [prefix] else: return [prefix + str(i + 1) for i in range(n)] input_names = names_from_num('x', f.nin) output_names = names_from_num('out', f.nout) keyword_only_params = [('where', True), ('casting', 'same_kind'), ('order', 'K'), ('dtype', None), ('subok', True), ('signature', None), ('extobj', None)] params = [] params += [ inspect.Parameter(name, inspect.Parameter.POSITIONAL_ONLY) for name in input_names ] if f.nout > 1: params += [ inspect.Parameter(name, inspect.Parameter.POSITIONAL_ONLY, default=None) for name in output_names ] params += [ inspect.Parameter('out', inspect.Parameter.POSITIONAL_OR_KEYWORD, default=None if f.nout == 1 else (None, ) * f.nout) ] params += [ inspect.Parameter(name, inspect.Parameter.KEYWORD_ONLY, default=default) for name, default in keyword_only_params ] return inspect.Signature(params)
def get_typed_signature(call: Callable) -> inspect.Signature: "Finds call signature and resolves all forwardrefs" signature = inspect.signature(call) globalns = getattr(call, "__globals__", {}) typed_params = [ inspect.Parameter( name=param.name, kind=param.kind, default=param.default, annotation=get_typed_annotation(param, globalns), ) for param in signature.parameters.values() ] typed_signature = inspect.Signature(typed_params) return typed_signature
class OneOf(Element): """Enum data type. Usage example from ``OPTINFO``: >> opttype = OneOf("CALL", "PUT", required=True) N.B. the variable number of positional args used for instantiation violates the assumptions of ``call_signature``, so we skip the ``@call_signature`` decorator and directly create the ``__signature__`` attribute in the class definition. """ __type__ = str __signature__ = inspect.Signature(( inspect.Parameter("valid", kind=inspect.Parameter.VAR_POSITIONAL), inspect.Parameter("required", kind=inspect.Parameter.KEYWORD_ONLY, default=False), )) @singledispatchmethod def convert(self, value): return self._convert_default(value) def _convert_default(self, value): value = self.enforce_required(value) if value is not None and value not in self.valid: raise OFXSpecError(f"'{value}' is not OneOf {self.valid}") return value @convert.register def _convert_str(self, value: str): return self._convert_default(value or None) @convert.register def _convert_none(self, value: None): # Pass through None, unless value is required return self.enforce_required(value) @singledispatchmethod def unconvert(self, value): value = self.enforce_required(value) if value is not None and value not in self.valid: raise OFXSpecError(f"'{value}' is not OneOf {self.valid}") return value @unconvert.register def _unconvert_none(self, value: None) -> None: # Pass through None, unless value is required return self.enforce_required(value)
def signature(subject: Callable, bound_method: bool = False, follow_wrapped: bool = False ) -> inspect.Signature: """Return a Signature object for the given *subject*. :param bound_method: Specify *subject* is a bound method or not :param follow_wrapped: Same as ``inspect.signature()``. Defaults to ``False`` (get a signature of *subject*). """ try: try: signature = inspect.signature(subject, follow_wrapped=follow_wrapped) except ValueError: # follow built-in wrappers up (ex. functools.lru_cache) signature = inspect.signature(subject) parameters = list(signature.parameters.values()) return_annotation = signature.return_annotation except IndexError: # Until python 3.6.4, cpython has been crashed on inspection for # partialmethods not having any arguments. # https://bugs.python.org/issue33009 if hasattr(subject, '_partialmethod'): parameters = [] return_annotation = Parameter.empty else: raise try: # Update unresolved annotations using ``get_type_hints()``. annotations = typing.get_type_hints(subject) for i, param in enumerate(parameters): if isinstance(param.annotation, str) and param.name in annotations: parameters[i] = param.replace(annotation=annotations[param.name]) if 'return' in annotations: return_annotation = annotations['return'] except Exception: # ``get_type_hints()`` does not support some kind of objects like partial, # ForwardRef and so on. pass if bound_method: if inspect.ismethod(subject): # ``inspect.signature()`` considers the subject is a bound method and removes # first argument from signature. Therefore no skips are needed here. pass else: if len(parameters) > 0: parameters.pop(0) return inspect.Signature(parameters, return_annotation=return_annotation)
def get_init(fields): ''' Dynamically generate an `__init__` method from a list of fields This is a bit of dark magic but still nice if you ask me :) ''' parameters = [] needs_default = False for key, field in fields.items(): kwargs = dict(name=key) # Get the default if available, once we've gotten a single # element with a default all the following parameters need defaults # or must be keyword only if field._default is not base.Undefined: needs_default = True kwargs['default'] = field._default if field._type: kwargs['annotation'] = field._type if not needs_default or 'default' in kwargs: kwargs['kind'] = inspect.Parameter.POSITIONAL_OR_KEYWORD else: kwargs['kind'] = inspect.Parameter.KEYWORD_ONLY parameters.append(inspect.Parameter(**kwargs)) signature = inspect.Signature(parameters=parameters) def __init__(self, *args, **kwargs): etree.ElementBase.__init__(self) if args or kwargs: bound = signature.bind(*args, **kwargs) for key, value in bound.arguments.items(): field = fields[key] # Handle automatic model to dict conversion if isinstance(value, dict) and issubclass(field, Model): value = field(**value) self.append(value) setattr(self, key, value) __init__.__signature__ = signature return __init__
def merge_super_sigs(cls, exclude=("widget_type", "kwargs", "args", "kwds", "extra")): """Merge the signature and kwarg docs from all superclasses, for clearer docs. Parameters ---------- cls : Type The class being modified exclude : tuple, optional A list of parameter names to excluded from the merged docs/signature, by default ("widget_type", "kwargs", "args", "kwds") Returns ------- cls : Type The modified class (can be used as a decorator) """ params = {} param_docs: list[DocstringParam] = [] for sup in reversed(inspect.getmro(cls)): try: sig = inspect.signature(getattr(sup, "__init__")) # in some environments `object` or `abc.ABC` will raise ValueError here except ValueError: continue for name, param in sig.parameters.items(): if name in exclude: continue params[name] = param param_docs += parse(getattr(sup, "__doc__", "")).params # sphinx_autodoc_typehints isn't removing the type annotations from the signature # so we do it manually when building documentation. if BUILDING_DOCS: params = { k: v.replace(annotation=inspect.Parameter.empty) for k, v in params.items() } cls.__init__.__signature__ = inspect.Signature( sorted(params.values(), key=lambda x: x.kind)) param_docs = [p for p in param_docs if p.arg_name not in exclude] cls.__doc__ = (cls.__doc__ or "").split("Parameters")[0].rstrip() + "\n\n" cls.__doc__ += _param_list_to_str(param_docs) # this makes docs linking work... but requires that all of these be in __init__ cls.__module__ = "magicgui.widgets" return cls
def _get_signature_from_schema(s: dict): p = s.get("properties", {}) a = [] required = s.get("required", []) for k in required: try: a += (inspect.Parameter( k, inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=p.get(k, inspect._empty), ), ) except (ValueError, TypeError): return inspect.signature(cls) for k in p: if k in required: continue v = p[k] if isinstance(v, type) and issubclass(v, base.Default): d = base.Default.forms(v) if not callable(d): a += (inspect.Parameter( k, inspect.Parameter.KEYWORD_ONLY, annotation=p[k], default=d, ), ) continue try: a += (inspect.Parameter( k, inspect.Parameter.KEYWORD_ONLY, annotation=p[k], ), ) except ValueError: pass additional = s.get("additionalProperties", True) if not additional: a += ((inspect.Parameter( "kwargs", inspect.Parameter.VAR_KEYWORD, annotation=inspect._empty if isinstance(additional, bool) else additional, ), ), ) return inspect.Signature(a)
def resolve_signature(fn: Callable) -> Optional[inspect.Signature]: ''' Resolve type annotations with get_type_hints ''' try: sig = inspect.signature(fn) except ValueError: return None type_hints = get_type_hints(fn, fn_globals(fn)) params = sig.parameters.values() newparams = [] for name, param in sig.parameters.items(): if name in type_hints: param = param.replace(annotation=type_hints[name]) newparams.append(param) newreturn = type_hints.get('return', sig.return_annotation) return inspect.Signature(newparams, return_annotation=newreturn)
def function_mock() -> GenericFunction: return GenericFunction( function=simple_function, inferred_signature=InferredSignature( signature=inspect.Signature(parameters=[ inspect.Parameter( name="z", kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=float, ), ]), return_type=float, parameters={"z": float}, ), )
def _set_signature(func, params): """Set the signature of 'func'. Parameters ---------- func : callable params: sequence of str Parameter names to put in the signature. These will be added as 'POSITIONAL_ONLY' type parameters. """ params = [ inspect.Parameter(name, inspect.Parameter.POSITIONAL_ONLY) for name in params ] func.__signature__ = inspect.Signature(params)
def signature(self) -> inspect.Signature: """ The function's signature. This usually returns an instance of `_PrettySignature`, a subclass of `inspect.Signature` that contains pdoc-specific optimizations. For example, long argument lists are split over multiple lines in repr(). Additionally, all types are already resolved. If the signature cannot be determined, a placeholder Signature object is returned. """ if self.obj is object.__init__: # there is a weird edge case were inspect.signature returns a confusing (self, /, *args, **kwargs) # signature for the default __init__ method. return inspect.Signature() try: sig = _PrettySignature.from_callable(self.obj) except Exception: return inspect.Signature([ inspect.Parameter("unknown", inspect.Parameter.POSITIONAL_OR_KEYWORD) ]) mod = inspect.getmodule(self.obj) globalns = _safe_getattr(mod, "__dict__", {}) if self.name == "__init__": # noinspection PyTypeHints sig._return_annotation = empty # type: ignore else: # noinspection PyTypeHints sig._return_annotation = safe_eval_type( sig.return_annotation, globalns, self.fullname) # type: ignore for p in sig.parameters.values(): # noinspection PyTypeHints p._annotation = safe_eval_type(p.annotation, globalns, self.fullname) # type: ignore return sig
def test_function_signature(self): f = self._get_f('0.1.0', until='0.1.4', reason='You should now use skbio.g().') parameters = [ inspect.Parameter('x', inspect.Parameter.POSITIONAL_OR_KEYWORD), inspect.Parameter('y', inspect.Parameter.POSITIONAL_OR_KEYWORD, default=42) ] expected = inspect.Signature(parameters) self.assertEqual(inspect.signature(f), expected) self.assertEqual(f.__name__, 'f')
class constant: def __call__(self, _: Env) -> T: return value # Update the signature's return annotation to reflect the # concrete type of the wrapped value. __name__ = "constant" __signature__ = inspect.Signature( [ inspect.Parameter( "_", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=Any ) ], return_annotation=type(value), )
def constructor_mock() -> GenericConstructor: return GenericConstructor( owner=SomeType, inferred_signature=InferredSignature( signature=inspect.Signature(parameters=[ inspect.Parameter( name="y", kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=float, ), ]), return_type=type(None), parameters={"y": float}, ), )
def _extract_signature(sql: str) -> Optional[inspect.Signature]: params = [] self = inspect.Parameter("self", inspect.Parameter.POSITIONAL_OR_KEYWORD) for match in var_pattern.finditer(sql): gd = match.groupdict() if gd["quote"] or gd["dblquote"] or gd["var_name"].isdigit(): continue name = gd["var_name"] params.append( inspect.Parameter( name=name, kind=inspect.Parameter.KEYWORD_ONLY, ) ) return inspect.Signature(parameters=[self] + params) if params else None
def _get_typed_signature(self, follow_wrapped: bool = True) -> inspect.Signature: signature = inspect.signature(self.func, follow_wrapped=follow_wrapped) globalns = getattr(self.func, "__globals__", {}) typed_params = [ inspect.Parameter( name=param.name, kind=param.kind, default=param.default, annotation=param.annotation if follow_wrapped else self._get_typed_annotation(param, globalns), ) for param in signature.parameters.values() ] typed_signature = inspect.Signature(typed_params) return typed_signature
def test_signature(self): r"""Ensure signature consistency.""" msg = 'Inconsistent method signature.' self.assertEqual( inspect.signature(lmp.util._dataset._preprocess_wiki_tokens), inspect.Signature( parameters=[ inspect.Parameter( name='split', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=str, default=inspect.Parameter.empty) ], return_annotation=lmp.dataset.LanguageModelDataset), msg=msg)
def __call__(self, cls): # At first, apply attr.dataclass to cls cls = attr.s(**self.kwargs)(cls) # Move and keep old init cls.__old_init__ = cls.__init__ cls.__old_init__.__name__ = '__old_init__' cls.__old_init__.__qualname__ = f'{cls.__qualname__}.__old_init__' # make parts of new body of __init__ old_signature = inspect.signature(cls.__old_init__) init_args = ', '.join(key for key in old_signature.parameters.keys() if key != 'self') params = [ p.replace(annotation=inspect.Parameter.empty) for p in old_signature.parameters.values() ] params.append( inspect.Parameter( '_kwargs', inspect.Parameter.VAR_KEYWORD, )) new_signature = inspect.Signature( params, return_annotation=old_signature.return_annotation, ) # make new __init__ by eval _global = {} _local = {} code = f"""\ def __init__{str(new_signature)}: self.__old_init__({init_args}) self.__dict__.update(_kwargs) """ eval(compile(code, cls.__qualname__, 'exec'), _global, _local) # update metadata of new __init__ __new_init__ = _local['__init__'] __new_init__.__module__ = cls.__module__ __new_init__.__annotations__ = cls.__old_init__.__annotations__ __new_init__.__qualname__ = f'{cls.__qualname__}.__init__' __new_init__.__name__ = '__init__' # overwrite __init__ cls.__init__ = __new_init__ return cls
def signature(subject: Callable, bound_method: bool = False) -> inspect.Signature: """Return a Signature object for the given *subject*. :param bound_method: Specify *subject* is a bound method or not """ # check subject is not a built-in class (ex. int, str) if (isinstance(subject, type) and is_builtin_class_method(subject, "__new__") and is_builtin_class_method(subject, "__init__")): raise TypeError("can't compute signature for built-in type {}".format(subject)) try: signature = inspect.signature(subject) parameters = list(signature.parameters.values()) return_annotation = signature.return_annotation except IndexError: # Until python 3.6.4, cpython has been crashed on inspection for # partialmethods not having any arguments. # https://bugs.python.org/issue33009 if hasattr(subject, '_partialmethod'): parameters = [] return_annotation = Parameter.empty else: raise try: # Update unresolved annotations using ``get_type_hints()``. annotations = typing.get_type_hints(subject) for i, param in enumerate(parameters): if isinstance(param.annotation, str) and param.name in annotations: parameters[i] = param.replace(annotation=annotations[param.name]) if 'return' in annotations: return_annotation = annotations['return'] except Exception: # ``get_type_hints()`` does not support some kind of objects like partial, # ForwardRef and so on. pass if bound_method: if inspect.ismethod(subject): # ``inspect.signature()`` considers the subject is a bound method and removes # first argument from signature. Therefore no skips are needed here. pass else: if len(parameters) > 0: parameters.pop(0) return inspect.Signature(parameters, return_annotation=return_annotation)
def test_structmeta_positional_only(): class Test(Struct): y: float x: int assert Test.__struct_fields__ == ("y", "x") assert Test.__struct_defaults__ == () assert Test.__slots__ == ("x", "y") sig = inspect.Signature(parameters=[ inspect.Parameter( "y", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=float), inspect.Parameter( "x", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=int), ]) assert Test.__signature__ == sig
def method_mock() -> GenericMethod: return GenericMethod( owner=SomeType, method=SomeType.simple_method, inferred_signature=InferredSignature( signature=inspect.Signature(parameters=[ inspect.Parameter( name="x", kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=int, ), ]), return_type=float, parameters={"x": int}, ), )
def get_typed_signature(cls, call: Callable) -> inspect.Signature: signature = inspect.signature(call) # call global namespace globalns = getattr(call, "__globals__", {}) typed_params = [ inspect.Parameter( name=param.name, kind=param.kind, default=param.default, annotation=cls.get_typed_annotation(param, globalns), ) for param in signature.parameters.values() ] typed_signature = inspect.Signature(typed_params) return typed_signature
def _update_prediction_signatures(self): """Updates the `self.predict` signature to match the model inputs for interactive work-flows""" updated_parameters = [ par for name, par in inspect.signature(self.head.featurize).parameters.items() if par.default == Parameter.empty ] + [ par for name, par in inspect.signature(self.predict).parameters.items() if name not in ["args", "kwargs"] ] new_signature = inspect.Signature(updated_parameters) self.__setattr__( self.predict.__name__, update_method_signature(new_signature, self.predict) )
def test_structmeta_subclass_extends(): class Test(Struct): c: int d: int = 1 b: float a: float = 2.0 class Test2(Test): e: str f: float = 3.0 assert Test2.__struct_fields__ == ("c", "b", "e", "d", "a", "f") assert Test2.__struct_defaults__ == (1, 2.0, 3.0) assert Test2.__slots__ == ("e", "f") sig = inspect.Signature( parameters=[ inspect.Parameter( "c", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=int ), inspect.Parameter( "b", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=float ), inspect.Parameter( "e", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=str ), inspect.Parameter( "d", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=int, default=1 ), inspect.Parameter( "a", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=float, default=2.0, ), inspect.Parameter( "f", inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=float, default=3.0, ), ] ) assert Test2.__signature__ == sig assert as_tuple(Test2(1, 2, 3, 4, 5, 6)) == (1, 2, 3, 4, 5, 6) assert as_tuple(Test2(4, 5, 6)) == (4, 5, 6, 1, 2.0, 3.0)
def call(self, *values, **named_values): """ Call an expression to evaluate it at the given point. Future improvements: I would like if func and signature could be buffered after the first call so they don't have to be recalculated for every call. However, nothing can be stored on self as sympy uses __slots__ for efficiency. This means there is no instance dict to put stuff in! And I'm pretty sure it's ill advised to hack into the __slots__ of Expr. However, for the moment I don't really notice a performance penalty in running tests. p.s. In the current setup signature is not even needed since no introspection is possible on the Expr before calling it anyway, which makes calculating the signature absolutely useless. However, I hope that someday some monkey patching expert in shining armour comes by and finds a way to store it in __signature__ upon __init__ of any ``symfit`` expr such that calling inspect_sig.signature on a symbolic expression will tell you which arguments to provide. :param self: Any subclass of sympy.Expr :param values: Values for the Parameters and Variables of the Expr. :param named_values: Values for the vars and params by name. ``named_values`` is allowed to contain too many values, as this sometimes happens when using \*\*fit_result.params on a submodel. The irrelevant params are simply ignored. :return: The function evaluated at ``values``. The type depends entirely on the input. Typically an array or a float but nothing is enforced. """ independent_vars, params = seperate_symbols(self) # Convert to a pythonic function func = sympy_to_py(self, independent_vars + params) # Handle args and kwargs according to the allowed names. parameters = [ # Note that these are inspect_sig.Parameter's, not symfit parameters! inspect_sig.Parameter(arg.name, inspect_sig.Parameter.POSITIONAL_OR_KEYWORD) for arg in independent_vars + params ] arg_names = [arg.name for arg in independent_vars + params] relevant_named_values = { name: value for name, value in named_values.items() if name in arg_names } signature = inspect_sig.Signature(parameters=parameters) bound_arguments = signature.bind(*values, **relevant_named_values) return func(**bound_arguments.arguments)
def test_signature(self): r"""Ensure signature consistency.""" msg = 'Inconsistent method signature.' self.assertEqual( inspect.signature(BaseTokenizer.convert_ids_to_tokens), inspect.Signature(parameters=[ inspect.Parameter(name='self', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, default=inspect.Parameter.empty), inspect.Parameter(name='token_ids', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=Iterable[int], default=inspect.Parameter.empty), ], return_annotation=List[str]), msg=msg)
def test_signature(self): r"""Ensure signature consistency.""" msg = 'Inconsistent method signature.' self.assertEqual( inspect.signature(BaseListTokenizer.normalize), inspect.Signature(parameters=[ inspect.Parameter(name='self', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, default=inspect.Parameter.empty), inspect.Parameter(name='sequence', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=str, default=inspect.Parameter.empty) ], return_annotation=str), msg=msg)
def test_signature(self): r"""Ensure signature consistency.""" msg = 'Inconsistenct method signature.' self.assertEqual( inspect.signature(BaseDataset.__getitem__), inspect.Signature(parameters=[ inspect.Parameter(name='self', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, default=inspect.Parameter.empty), inspect.Parameter(name='index', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=int, default=inspect.Parameter.empty), ], return_annotation=str), msg=msg)
def test_signature(self): r"""Ensure signature consistency.""" msg = 'Inconsistenct method signature.' self.assertEqual( inspect.signature(LanguageModelDataset.__init__), inspect.Signature(parameters=[ inspect.Parameter(name='self', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, default=inspect.Parameter.empty), inspect.Parameter(name='batch_sequences', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=Iterable[str], default=inspect.Parameter.empty), ], return_annotation=inspect.Signature.empty), msg=msg)