def __init__(self, *args, **kwargs): params = [Parameter(field, Parameter.POSITIONAL_OR_KEYWORD) for field in self._fields] sig = Signature(params) bound_values = sig.bind(*args, **kwargs) for name, value in bound_values.arguments.items(): setattr(self, name, value)
def __signature__(self): try: return self._value.__signature__ except AttributeError: pass try: return Signature.from_function(self._value) except TypeError: pass try: return Signature.from_buultin(self._value) except TypeError: pass return None
class LibFunction(object): def __init__(self, name, c_name, sig, c_func): self.sig = sig self.name = name self.c_name = c_name self.c_func = c_func sig_str = '{}({}) -> {}'.format(name, sig.args_py_str(), sig.rets_py_str()) c_sig_str = '{}({})'.format(c_name, sig.args_c_str()) self.__doc__ = sig_str + '\n\nOriginal C Function: ' + c_sig_str if sys.version_info >= (3,3): self._assign_signature() def _assign_signature(self): from inspect import Parameter, Signature params = [Parameter(h.c_argname, Parameter.POSITIONAL_OR_KEYWORD) for h in self.sig.in_handlers] self.__signature__ = Signature(params) def __get__(self, instance, owner): if instance is None: return self else: return LibMethod(instance, self) def __call__(self, *args, **kwds): return self._call(args, kwds) def _call(self, args, kwds, niceobj=None): if sys.version_info >= (3,3): bound_args = self.__signature__.bind(*args, **kwds) args = bound_args.args elif kwds: raise TypeError('Keyword args in LibFunctions are not supported for Python versions ' 'before 3.3') check_num_args(self.name, len(args), self.sig.num_inargs, self.sig.variadic) if len(args) != self.sig.num_inargs: raise TypeError("{}() takes {} arguments ({} given)" "".format(self.name, self.sig.num_inargs, len(args))) c_args = self.sig.make_c_args(args) # TODO: Add a custom object for logging these messages, to allow both filtering # and to avoid this text formatting unless it's needed log.info('Calling {}({})'.format(self.name, ', '.join(repr(arg) for arg in args))) retval = self.c_func(*c_args) ret_handler_args = { 'niceobj': niceobj, 'funcname': self.name, 'funcargs': c_args, } return self.sig.extract_outputs(c_args, retval, ret_handler_args)
def required_args(attrs): """Extract the required arguments from a class's attrs. Arguments: attrs (:py:class:`dict`) :The attributes of a class. Returns: :py:class:`set`: The required arguments. """ init_args = attr_args = set() if '__init__' in attrs: sig = Signature.from_callable(attrs['__init__']) init_args = set( name for name, param in sig.parameters.items() if param.kind == Parameter.KEYWORD_ONLY and param.default is Signature.empty ) if 'REQUIRED' in attrs: attr_args = attrs['REQUIRED'] return set.union(attr_args, init_args)
def __init__(self, *args, **kwargs): sig = Signature([Parameter(f, Parameter.POSITIONAL_OR_KEYWORD) for f in self.fields]) for k, v in sig.bind(*args, **kwargs).arguments.items(): setattr(self, k, v)
def render(self, scene, camera): content = { "type": "render", "scene": to_json(scene, None), "camera": to_json(camera, None) } self.send(content) def freeze(self): content = { "type": "freeze" } self.send(content) if six.PY3: from inspect import Signature, Parameter # Include explicit signature since the metaclass screws it up parameters = [ Parameter('scene', Parameter.POSITIONAL_OR_KEYWORD), Parameter('camera', Parameter.POSITIONAL_OR_KEYWORD), Parameter('controls', Parameter.POSITIONAL_OR_KEYWORD, default=None), ] for name in ('width', 'height', 'background', 'background_opacity'): parameters.append(Parameter( name, Parameter.KEYWORD_ONLY, default=getattr(Renderer, name).default_value)) parameters.append(Parameter('kwargs', Parameter.VAR_KEYWORD)) Renderer.__signature__ = Signature(parameters=tuple(parameters)) del parameters
def translate(cls, func): """ Decorator for Wrapper methods. The decorated method does not need to manually lookup objects when the caller (across DBus) passes an object path. Type information is provided using parameter annotations. The annotation accepts DBus type expressions (but in practice it is very limited). For the moment it cannot infer the argument types from the decorator for dbus.service.method. """ sig = Signature.from_function(func) def translate_o(object_path): try: obj = cls.find_object_by_path(object_path) except KeyError as exc: raise dbus.exceptions.DBusException(( "object path {} does not designate an existing" " object").format(exc)) else: return obj.native def translate_ao(object_path_list): try: obj_list = [cls.find_object_by_path(object_path) for object_path in object_path_list] except KeyError as exc: raise dbus.exceptions.DBusException(( "object path {} does not designate an existing" " object").format(exc)) else: return [obj.native for obj in obj_list] def translate_return_o(obj): try: return cls.find_wrapper_by_native(obj) except KeyError: raise dbus.exceptions.DBusException( "(o) internal error, unable to lookup object wrapper") def translate_return_ao(object_list): try: return dbus.types.Array([ cls.find_wrapper_by_native(obj) for obj in object_list ], signature='o') except KeyError: raise dbus.exceptions.DBusException( "(ao) internal error, unable to lookup object wrapper") def translate_return_a_brace_so_brace(mapping): try: return dbus.types.Dictionary({ key: cls.find_wrapper_by_native(value) for key, value in mapping.items() }, signature='so') except KeyError: raise dbus.exceptions.DBusException( "(a{so}) internal error, unable to lookup object wrapper") @functools.wraps(func) def wrapper(*args, **kwargs): bound = sig.bind(*args, **kwargs) cls._logger.debug( "wrapped %s called with %s", func, bound.arguments) for param in sig.parameters.values(): if param.annotation is Signature.empty: pass elif param.annotation == 'o': object_path = bound.arguments[param.name] bound.arguments[param.name] = translate_o(object_path) elif param.annotation == 'ao': object_path_list = bound.arguments[param.name] bound.arguments[param.name] = translate_ao( object_path_list) elif param.annotation in ('s', 'as'): strings = bound.arguments[param.name] bound.arguments[param.name] = strings else: raise ValueError( "unsupported translation {!r}".format( param.annotation)) cls._logger.debug( "unwrapped %s called with %s", func, bound.arguments) retval = func(**bound.arguments) cls._logger.debug("unwrapped %s returned %r", func, retval) if sig.return_annotation is Signature.empty: pass elif sig.return_annotation == 'o': retval = translate_return_o(retval) elif sig.return_annotation == 'ao': retval = translate_return_ao(retval) elif sig.return_annotation == 'a{so}': retval = translate_return_a_brace_so_brace(retval) else: raise ValueError( "unsupported translation {!r}".format( sig.return_annotation)) cls._logger.debug("wrapped %s returned %r", func, retval) return retval return wrapper
def test_instance_method(): r"""Ensure instance methods' signature.""" assert hasattr(SAttnGRUBlock, '__init__') assert inspect.signature(SAttnGRUBlock.__init__) == Signature(parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='d_hid', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='n_hid_lyr', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='p_hid', kind=Parameter.KEYWORD_ONLY, annotation=float, default=Parameter.empty, ), Parameter( name='kwargs', kind=Parameter.VAR_KEYWORD, annotation=Optional[Dict], ), ], ) assert hasattr(SAttnGRUModel, '__init__') assert inspect.signature(SAttnGRUModel.__init__) == Signature(parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='d_emb', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='d_hid', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='n_hid_lyr', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='n_post_hid_lyr', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='n_pre_hid_lyr', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='p_emb', kind=Parameter.KEYWORD_ONLY, annotation=float, default=Parameter.empty, ), Parameter( name='p_hid', kind=Parameter.KEYWORD_ONLY, annotation=float, default=Parameter.empty, ), Parameter( name='tknzr', kind=Parameter.KEYWORD_ONLY, annotation=BaseTknzr, default=Parameter.empty, ), Parameter( name='kwargs', kind=Parameter.VAR_KEYWORD, annotation=Optional[Dict], ), ], )
def _mk_sig(req_args, opt_args, anno_args): params = [_mk_param(k) for k in req_args] params += [_mk_param(k, default=v) for k,v in opt_args.items()] params += [_mk_param(k, **_mk_sig_detls(v)) for k,v in anno_args.items()] return Signature(params)
from inspect import Signature, Parameter import inspect # example 1 parms = [ Parameter('x', Parameter.POSITIONAL_OR_KEYWORD), Parameter('y', Parameter.POSITIONAL_OR_KEYWORD, default=42), Parameter('z', Parameter.KEYWORD_ONLY, default=None) ] sig = Signature(parms) print(sig) def func(*args, **kwargs): bound_values = sig.bind(*args, **kwargs) for name, value in bound_values.arguments.items(): print(name, value) func(1, 2, z=3) # example 2 def make_sig(*names): parms = [ Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names ] return Signature(parms) class Structure:
elif base is list: return List[gen_type(r, object)] # type: ignore elif base is set: return Set[gen_type(r, Hashable)] # type: ignore elif base is frozenset: return FrozenSet[gen_type(r, Hashable)] # type: ignore else: return base # TODO: consider replacing this with typeshed someday! _SIGNATURE_OVERRIDES = { getattr: Signature( [ Parameter("obj", Parameter.POSITIONAL_ONLY, annotation=object), Parameter("attr", Parameter.POSITIONAL_ONLY, annotation=str), Parameter("default", Parameter.POSITIONAL_ONLY, annotation=object), ] ), dict.items: Signature(), dict.keys: Signature(), # TODO: fuzz test values() somehow. items() and keys() are sets and # therefore comparable -- not values() though: # dict.values: Signature(), dict.clear: Signature(), dict.copy: Signature(), dict.pop: Signature( [ Parameter("k", Parameter.POSITIONAL_ONLY, annotation=object), Parameter("d", Parameter.POSITIONAL_ONLY, annotation=object), ]
from inspect import Signature, Parameter else: from funcsigs import Signature, Parameter # pylint: disable=import-error __all__ = ['simplified_test_function'] # Pytest determines the signature of the test function by unpacking any # wrapped functions (this is the default of the signature() function it # uses. We correct this behavior by setting the __signature__ attribute of # the wrapper function to its correct signature. To do that, we cannot use # signature() because its follow_wrapped parameter was introduced only in # Python 3.5. Instead, we build the signature manually. TESTFUNC_SIGNATURE = Signature(parameters=[ Parameter('desc', Parameter.POSITIONAL_OR_KEYWORD), Parameter('kwargs', Parameter.POSITIONAL_OR_KEYWORD), Parameter('exp_exc_types', Parameter.POSITIONAL_OR_KEYWORD), Parameter('exp_warn_types', Parameter.POSITIONAL_OR_KEYWORD), Parameter('condition', Parameter.POSITIONAL_OR_KEYWORD), ]) def simplified_test_function(test_func): """ A decorator for test functions that simplifies the test function by handling a number of things: * Skipping the test if the `condition` item in the testcase is `False`, * Invoking the Python debugger if the `condition` item in the testcase is the string "pdb", * Capturing and validating any warnings issued by the test function, if the `exp_warn_types` item in the testcase is set,
module_stub_for_method_with_typed_dict = { 'tests.util': ModuleStub( function_stubs=(), class_stubs=[ ClassStub( name='Dummy', function_stubs=[ FunctionStub( name='an_instance_method', signature=Signature( parameters=[ Parameter(name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=Parameter.empty), Parameter(name='foo', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=make_forward_ref('FooTypedDict')), Parameter(name='bar', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=int), ], return_annotation=make_forward_ref('DummyAnInstanceMethodTypedDict'), ), kind=FunctionKind.INSTANCE, strip_modules=['mypy_extensions'], is_async=False, ), ], ), ], imports_stub=ImportBlockStub(typed_dict_import_map), typed_dict_class_stubs=[
def generate_model_signature(init: Callable[..., None], fields: Dict[str, 'ModelField'], config: Type['BaseConfig']) -> 'Signature': """ Generate signature for model based on its fields """ from inspect import Parameter, Signature, signature present_params = signature(init).parameters.values() merged_params: Dict[str, Parameter] = {} var_kw = None use_var_kw = False for param in islice(present_params, 1, None): # skip self arg if param.kind is param.VAR_KEYWORD: var_kw = param continue merged_params[param.name] = param if var_kw: # if custom init has no var_kw, fields which are not declared in it cannot be passed through allow_names = config.allow_population_by_field_name for field_name, field in fields.items(): param_name = field.alias if field_name in merged_params or param_name in merged_params: continue elif not param_name.isidentifier(): if allow_names and field_name.isidentifier(): param_name = field_name else: use_var_kw = True continue # TODO: replace annotation with actual expected types once #1055 solved kwargs = {'default': field.default} if not field.required else {} merged_params[param_name] = Parameter(param_name, Parameter.KEYWORD_ONLY, annotation=field.outer_type_, **kwargs) if config.extra is config.extra.allow: use_var_kw = True if var_kw and use_var_kw: # Make sure the parameter for extra kwargs # does not have the same name as a field default_model_signature = [ ('__pydantic_self__', Parameter.POSITIONAL_OR_KEYWORD), ('data', Parameter.VAR_KEYWORD), ] if [(p.name, p.kind) for p in present_params] == default_model_signature: # if this is the standard model signature, use extra_data as the extra args name var_kw_name = 'extra_data' else: # else start from var_kw var_kw_name = var_kw.name # generate a name that's definitely unique while var_kw_name in fields: var_kw_name += '_' merged_params[var_kw_name] = var_kw.replace(name=var_kw_name) return Signature(parameters=list(merged_params.values()), return_annotation=None)
def test_module_method(): """Ensure module methods' signatures.""" assert hasattr(lmp.util.validate, 'raise_if_not_instance') assert inspect.isfunction(lmp.util.validate.raise_if_not_instance) assert inspect.signature( lmp.util.validate.raise_if_not_instance) == Signature( parameters=[ Parameter( name='val', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=Any, ), Parameter( name='val_name', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=str, ), Parameter( name='val_type', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=Type, ), ], return_annotation=None, ) assert hasattr(lmp.util.validate, 'raise_if_empty_str') assert inspect.isfunction(lmp.util.validate.raise_if_empty_str) assert inspect.signature( lmp.util.validate.raise_if_empty_str) == Signature( parameters=[ Parameter( name='val', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=str, ), Parameter( name='val_name', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=str, ), ], return_annotation=None, ) assert hasattr(lmp.util.validate, 'raise_if_not_in') assert inspect.isfunction(lmp.util.validate.raise_if_not_in) assert inspect.signature(lmp.util.validate.raise_if_not_in) == Signature( parameters=[ Parameter( name='val', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=Any, ), Parameter( name='val_name', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=str, ), Parameter( name='val_range', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=List, ), ], return_annotation=None, ) assert hasattr(lmp.util.validate, 'raise_if_is_directory') assert inspect.isfunction(lmp.util.validate.raise_if_is_directory) assert inspect.signature( lmp.util.validate.raise_if_is_directory) == Signature( parameters=[ Parameter( name='path', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=str, ), ], return_annotation=None, ) assert hasattr(lmp.util.validate, 'raise_if_is_file') assert inspect.isfunction(lmp.util.validate.raise_if_is_file) assert inspect.signature(lmp.util.validate.raise_if_is_file) == Signature( parameters=[ Parameter( name='path', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=str, ), ], return_annotation=None, ) assert hasattr(lmp.util.validate, 'raise_if_wrong_ordered') assert inspect.isfunction(lmp.util.validate.raise_if_wrong_ordered) assert inspect.signature( lmp.util.validate.raise_if_wrong_ordered) == Signature( parameters=[ Parameter( name='vals', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=List[Union[float, int]], ), Parameter( name='val_names', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=List[str], ), ], return_annotation=None, )
def make_sig(**fields): params = [Parameter(name, Parameter.KEYWORD_ONLY, default=attrs['default_value']) for name, attrs in fields.items()] return Signature(params)
if v.annotation is not Signature.empty } if signature.return_annotation is not Signature.empty: func.__annotations__["return"] = signature.return_annotation return func return _decorate _INDEX_SIGNATURE = Signature([ Parameter("self", Parameter.POSITIONAL_ONLY), Parameter("value", Parameter.POSITIONAL_ONLY, annotation=Any), Parameter("start", Parameter.POSITIONAL_ONLY, default=0, annotation=SupportsIndex), Parameter("stop", Parameter.POSITIONAL_ONLY, default=sys.maxsize, annotation=SupportsIndex), ], return_annotation=int) _COUNT_SIGNATURE = Signature([ Parameter("self", Parameter.POSITIONAL_ONLY), Parameter("value", Parameter.POSITIONAL_ONLY, annotation=Any), ], return_annotation=int) class SequenceView(Sequence[_T_co]):
def modify_signature( endpoint: t.Callable, model: t.Type[PydanticBaseModel], http_method: HTTPMethod, allow_pagination: bool = False, allow_ordering: bool = False, ): """ Modify the endpoint's signature, so FastAPI can correctly extract the schema from it. GET endpoints are given more filters. """ parameters = [ Parameter( name="request", kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=Request, ), ] for field_name, _field in model.__fields__.items(): type_ = _field.outer_type_ parameters.append( Parameter( name=field_name, kind=Parameter.POSITIONAL_OR_KEYWORD, default=Query( default=None, description=(f"Filter by the `{field_name}` column."), ), annotation=type_, ), ) if type_ in (int, float, Decimal): parameters.append( Parameter( name=f"{field_name}__operator", kind=Parameter.POSITIONAL_OR_KEYWORD, default=Query( default=None, description=( f"Which operator to use for `{field_name}`. " "The options are `e` (equals - default) `lt`, " "`lte`, `gt`, and `gte`." ), ), ) ) if type_ is str: parameters.append( Parameter( name=f"{field_name}__match", kind=Parameter.POSITIONAL_OR_KEYWORD, default=Query( default=None, description=( f"Specifies how `{field_name}` should be " "matched - `contains` (default), `exact`, " "`starts`, `ends`." ), ), ) ) if http_method == HTTPMethod.get: if allow_ordering: parameters.extend( [ Parameter( name="__order", kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=str, default=Query( default=None, description=( "Specifies which field to sort the " "results by. For example `id` to sort by " "id, and `-id` for descending." ), ), ) ] ) if allow_pagination: parameters.extend( [ Parameter( name="__page_size", kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=int, default=Query( default=None, description=( "The number of results to return." ), ), ), Parameter( name="__page", kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=int, default=Query( default=None, description=( "Which page of results to return (default " "1)." ), ), ), Parameter( name="__visible_fields", kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=str, default=Query( default=None, description=( "The fields to return. It's a comma " "separated list - for example " "'name,address'. By default all fields " "are returned." ), ), ), ] ) parameters.extend( [ Parameter( name="__range_header", kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=bool, default=Query( default=False, description=( "Set to 'true' to add the " "Content-Range response header" ), ), ) ] ) parameters.extend( [ Parameter( name="__range_header_name", kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=str, default=Query( default=None, description=( "Specify the object name in the Content-Range " "response header (defaults to the table name)." ), ), ) ] ) endpoint.__signature__ = Signature( # type: ignore parameters=parameters )
class YAMLConstructor: free_signature = Signature((Parameter('args', Parameter.VAR_POSITIONAL), Parameter('kwargs', Parameter.VAR_KEYWORD))) type_to_tag: tp.Dict[tp.Type, str] = {} strict_node_type = True @classmethod def fix_signature(cls, signature: BoundArguments) -> BoundArguments: for name, value in signature.arguments.items(): try: param = signature.signature.parameters[name] if param.annotation is param.empty: if param.default in (param.empty, None): continue else: hint = type(param.default) else: hint = (param.annotation if inspect.isclass(param.annotation) else tp.get_origin(param.annotation) or None) if not inspect.isclass(hint): # TODO: Maybe handle Union?? continue hint_is_builtin = any(hint.__module__.startswith(mod) for mod in ('builtins', 'typing', 'collections')) hint_is_str = issubclass(hint, str) hint_is_callable = issubclass(hint, type) or (not isinstance(hint, type) and issubclass(hint, tp.Callable)) target_nodetype = ( (hint_is_callable or hint_is_str) and yaml.ScalarNode or hint_is_builtin and issubclass(hint, tp.Mapping) and yaml.MappingNode or hint_is_builtin and issubclass(hint, tp.Iterable) and yaml.SequenceNode or yaml.Node ) for node in valueiter(value): if not isinstance(node, target_nodetype): raise NodeTypeMismatchError(f'Expected {target_nodetype} for {param}, but got {node}.') if (not hint_is_str and (not hint_is_builtin or target_nodetype in (yaml.ScalarNode, yaml.Node)) and node.tag.startswith('tag:yaml.org')): if hint_is_callable: node.tag = f'!py:{node.value}' node.value = '' else: node.tag = cls.type_to_tag.get(hint, f'!py:{hint.__module__}.{hint.__name__}') except Exception as e: if cls.strict_node_type and isinstance(e, NodeTypeMismatchError): raise e warn(str(e)) return signature @classmethod def get_args_kwargs(cls, loader: yaml.Loader, node: yaml.Node, signature: Signature = free_signature) -> tp.Optional[BoundArguments]: if isinstance(node, yaml.ScalarNode): try: # This sometimes fails because of ruamel/yaml/resolver.py line 370 node.tag = loader.resolver.resolve(yaml.ScalarNode, node.value, [True, False]) except IndexError: node.tag = loader.DEFAULT_SCALAR_TAG val = loader.construct_object(node) if val is None: val = loader.yaml_constructors[node.tag](loader, node) return None if val is None else signature.bind(val) elif isinstance(node, yaml.SequenceNode): bound = signature.bind(*node.value) args = [] subnodes = node.value elif isinstance(node, yaml.MappingNode): # Construct the keys kwargs = {loader.construct_object(key, deep=True): val for key, val in node.value} args = kwargs.setdefault('__args', yaml.SequenceNode('tag:yaml.org,2002:seq', [])) args_is_seq = isinstance(args, yaml.SequenceNode) and args.tag == 'tag:yaml.org,2002:seq' if args_is_seq: kwargs['__args'] = args.value # Extract nodes in order (nodes are not iterable, so only "flattens" __args) subnodes = list(flatten(kwargs.values())) __args = kwargs.pop('__args') bound = signature.bind_partial(*(__args if args_is_seq else ()), **kwargs) else: raise ValueError(f'Invalid node type, {node}') # Experimental cls.fix_signature(bound) # Construct nodes in yaml order subnode_values = {n: loader.construct_object(n, deep=True) for n in subnodes} for key, val in bound.arguments.items(): bound.arguments[key] = ( signature.parameters[key].kind == Parameter.VAR_POSITIONAL and (subnode_values[n] for n in val) or signature.parameters[key].kind == Parameter.VAR_KEYWORD and {name: subnode_values[n] for name, n in val.items()} or subnode_values[val] ) if args and args in subnode_values: return bound.signature.bind(*subnode_values[args], **bound.kwargs) return bound @classmethod def construct(cls, obj, loader: yaml.Loader, node: yaml.Node, **kw): try: signature = inspect.signature(obj, follow_wrapped=False) except (TypeError, ValueError): signature = cls.free_signature signature = cls.get_args_kwargs(loader, node, signature) if signature is None: return obj else: signature.apply_defaults() signature.arguments.update(kw) return obj(*signature.args, **signature.kwargs) @classmethod def apply(cls, obj): return partial(cls.construct, obj)
class TestFunctionDefinition: @pytest.mark.parametrize( 'func, expected', [ (Dummy.a_static_method, False), (Dummy.a_class_method.__func__, True), (Dummy.an_instance_method, True), (Dummy.a_property.fget, True), (Dummy.a_cached_property.func, True), (a_module_func, False), ], ) def test_has_self(self, func, expected): defn = FunctionDefinition.from_callable(func) assert defn.has_self == expected @pytest.mark.parametrize( 'func, expected', [ (Dummy.a_static_method, FunctionDefinition( 'tests.util', 'Dummy.a_static_method', FunctionKind.STATIC, Signature.from_callable(Dummy.a_static_method))), (Dummy.a_class_method.__func__, FunctionDefinition( 'tests.util', 'Dummy.a_class_method', FunctionKind.CLASS, Signature.from_callable(Dummy.a_class_method.__func__))), (Dummy.an_instance_method, FunctionDefinition( 'tests.util', 'Dummy.an_instance_method', FunctionKind.INSTANCE, Signature.from_callable(Dummy.an_instance_method))), (Dummy.a_property.fget, FunctionDefinition( 'tests.util', 'Dummy.a_property', FunctionKind.PROPERTY, Signature.from_callable(Dummy.a_property.fget))), (Dummy.a_cached_property.func, FunctionDefinition( 'tests.util', 'Dummy.a_cached_property', FunctionKind.DJANGO_CACHED_PROPERTY, Signature.from_callable(Dummy.a_cached_property.func))), (a_module_func, FunctionDefinition( 'tests.test_stubs', 'a_module_func', FunctionKind.MODULE, Signature.from_callable(a_module_func))), (an_async_func, FunctionDefinition( 'tests.test_stubs', 'an_async_func', FunctionKind.MODULE, Signature.from_callable(a_module_func), is_async=True)), ], ) def test_from_callable(self, func, expected): defn = FunctionDefinition.from_callable(func) assert defn == expected @pytest.mark.parametrize( 'func, arg_types, return_type, yield_type, expected', [ # Non-TypedDict case. ( Dummy.an_instance_method, {'foo': int, 'bar': List[str]}, int, None, FunctionDefinition( 'tests.util', 'Dummy.an_instance_method', FunctionKind.INSTANCE, Signature( parameters=[ Parameter(name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=Parameter.empty), Parameter(name='foo', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=int), Parameter(name='bar', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=List[str]), ], return_annotation=int, ), False, [], ) ), # TypedDict: Add class definitions and use the class names as types. ( Dummy.an_instance_method, { 'foo': TypedDict(DUMMY_TYPED_DICT_NAME, {'a': int, 'b': str}), 'bar': TypedDict(DUMMY_TYPED_DICT_NAME, {'c': int}), }, int, None, FunctionDefinition( 'tests.util', 'Dummy.an_instance_method', FunctionKind.INSTANCE, Signature( parameters=[ Parameter(name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=Parameter.empty), Parameter(name='foo', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=make_forward_ref('FooTypedDict')), Parameter(name='bar', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=make_forward_ref('BarTypedDict')), ], return_annotation=int, ), False, [ ClassStub( name='FooTypedDict(TypedDict)', function_stubs=[], attribute_stubs=[ AttributeStub('a', int), AttributeStub('b', str), ] ), ClassStub( name='BarTypedDict(TypedDict)', function_stubs=[], attribute_stubs=[ AttributeStub('c', int), ] ), ], ) ), ], ) def test_from_callable_and_traced_types(self, func, arg_types, return_type, yield_type, expected): function = FunctionDefinition.from_callable_and_traced_types( func, arg_types, return_type, yield_type, existing_annotation_strategy=ExistingAnnotationStrategy.IGNORE ) assert function == expected
class _UnifiAPICall: # pylint: disable=too-many-instance-attributes, too-many-arguments # pylint: disable=too-few-public-methods, protected-access "A representation of a single API call in a specific site" def __init__(self, doc, endpoint, path_arg_name=None, path_arg_optional=True, json_args=None, json_body_name=None, json_fix=None, rest_command=None, method=None, need_login=True): self._endpoint = endpoint self._path_arg_name = path_arg_name self._json_args = json_args self._json_body_name = json_body_name self._rest = rest_command self._need_login = need_login if not isinstance(json_fix, (list, tuple, type(None))): json_fix = [json_fix] self._fixes = json_fix self.__doc__ = doc args = [Parameter('self', POSITIONAL_ONLY)] if path_arg_name: args.append(Parameter(path_arg_name, POSITIONAL_OR_KEYWORD, default=None if path_arg_optional else Parameter.empty)) if json_args: json_args.sort(key=lambda x:isinstance(x,tuple)) for arg_name in json_args: if isinstance(arg_name, tuple): arg_name, default = arg_name else: default = Parameter.empty args.append(Parameter(arg_name, POSITIONAL_OR_KEYWORD, default=default)) if json_body_name: args.append(Parameter(json_body_name, POSITIONAL_OR_KEYWORD if path_arg_optional else POSITIONAL_OR_KEYWORD, default=None)) self.call_sig = Signature(args) if method is None: if json_args or json_body_name or rest_command: method = "POST" else: method = "GET" self._method = method def _build_url(self, client, path_arg): if not client.site: raise UnifiAPIError("No site specified for site-specific call") return "https://{host}:{port}/api/s/{site}/{endpoint}{path}".format( host=client.host, port=client.port, site=client.site, endpoint=self._endpoint, path="/" + path_arg if path_arg else "") def __call__(self, *args, **kwargs): bound = self.call_sig.bind(*args, **kwargs) bound.apply_defaults() # The first parameter is the 'self' of the API class to which it is attached client = bound.arguments["self"] path_arg = bound.arguments[self._path_arg_name] if self._path_arg_name else None rest_dict = bound.arguments[self._json_body_name] if self._json_body_name else {} if self._rest: rest_dict["cmd"] = self._rest if self._json_args: for arg_name in self._json_args: if isinstance(arg_name, tuple): arg_name, _ = arg_name if arg_name not in bound.arguments: raise TypeError("Argument {} is required".format(arg_name)) if bound.arguments[arg_name] is not None: rest_dict[arg_name] = bound.arguments[arg_name] if self._fixes: for fix in self._fixes: rest_dict = fix(rest_dict) url = self._build_url(client, path_arg) return client._execute(url, self._method, rest_dict, need_login=self._need_login)
def _combined_cli_sig(signature: Signature, *other_signatures: Signature, parse: Optional[Set[str]] = None, have_fallback: Optional[Set[str]] = None): all_signatures = (signature, *other_signatures) all_names = chain.from_iterable(s.parameters for s in all_signatures) if parse is not None: all_names = filter(parse.__contains__, all_names) name_counts = Counter(all_names) common_names = tuple(n for n, c in name_counts.items() if c > 1) if common_names: raise OutputHandlerSignatureError( "signatures share overlapping arg names: {}".format(common_names)) params = { k: [] for k in ( Parameter.POSITIONAL_ONLY, Parameter.POSITIONAL_OR_KEYWORD, Parameter.VAR_POSITIONAL, Parameter.KEYWORD_ONLY, Parameter.VAR_KEYWORD, ) } for sig in all_signatures: for param in sig.parameters.values(): if parse is None or param.name in parse: params[param.kind].append(param) # algorithm: # sort variadics to the end of the positionals # if there are any positional variadics, move all but the first to kw_only, and move any *args to kw_only # if there are no positional variadics, move the first *args to the end of positionals, the rest to kw_only # if there are more than one **kwargs, move the tail to kw_only all_pos = (params[Parameter.POSITIONAL_ONLY] + params[Parameter.POSITIONAL_OR_KEYWORD]) non_variadic_pos, variadic_pos = _separate_variadic_params(all_pos) maybe_variadic_pos = [] if variadic_pos: first_variadic = variadic_pos[0] last_pos_kind = (max(non_variadic_pos[-1].kind, first_variadic.kind) if non_variadic_pos else first_variadic.kind) maybe_variadic_pos.append(first_variadic.replace(kind=last_pos_kind)) params[Parameter.KEYWORD_ONLY].extend( p.replace(kind=Parameter.KEYWORD_ONLY) for p in variadic_pos[1:]) elif params[Parameter.VAR_POSITIONAL]: varargs = params[Parameter.VAR_POSITIONAL] first_varargs = varargs[0] maybe_variadic_pos.append( first_varargs.replace( kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=Tuple[first_varargs.annotation, ...], )) params[Parameter.VAR_POSITIONAL] = varargs[1:] for kind in Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD: ps = params[kind] params[Parameter.KEYWORD_ONLY].extend( p.replace( kind=Parameter.KEYWORD_ONLY, annotation=Tuple[p.annotation, ...] if kind is Parameter.VAR_POSITIONAL else Dict[str, p.annotation], ) for p in ps) nondefault_pos, default_pos = _separate_default_params( non_variadic_pos, have_fallback=have_fallback) all_params = (nondefault_pos + default_pos + maybe_variadic_pos + params[Parameter.KEYWORD_ONLY]) # Don't validate because we may have defaults preceding non-defaults at this point return Signature( all_params, return_annotation=signature.return_annotation, __validate_parameters__=False, )
def test_instance_method(): r"""Ensure instance methods' signature.""" assert hasattr(SAttnRNNBlock, '__init__') assert inspect.signature(SAttnRNNBlock.__init__) == Signature(parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='d_hid', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='n_hid_lyr', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='p_hid', kind=Parameter.KEYWORD_ONLY, annotation=float, default=Parameter.empty, ), Parameter( name='kwargs', kind=Parameter.VAR_KEYWORD, annotation=Optional[Dict], ), ], ) assert hasattr(SAttnRNNBlock, 'forward') assert inspect.signature(SAttnRNNBlock.forward) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='batch_tk_mask', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=torch.Tensor, default=Parameter.empty, ), Parameter( name='batch_tk_reps', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=torch.Tensor, default=Parameter.empty, ), ], return_annotation=torch.Tensor, ) assert hasattr(SAttnRNNModel, '__init__') assert inspect.signature(SAttnRNNModel.__init__) == Signature(parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='d_emb', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='d_hid', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='n_hid_lyr', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='n_post_hid_lyr', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='n_pre_hid_lyr', kind=Parameter.KEYWORD_ONLY, annotation=int, default=Parameter.empty, ), Parameter( name='p_emb', kind=Parameter.KEYWORD_ONLY, annotation=float, default=Parameter.empty, ), Parameter( name='p_hid', kind=Parameter.KEYWORD_ONLY, annotation=float, default=Parameter.empty, ), Parameter( name='tknzr', kind=Parameter.KEYWORD_ONLY, annotation=BaseTknzr, default=Parameter.empty, ), Parameter( name='kwargs', kind=Parameter.VAR_KEYWORD, annotation=Optional[Dict], ), ], ) assert hasattr(SAttnRNNModel, 'create_mask') assert inspect.signature(SAttnRNNModel.create_mask) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='batch_prev_tkids', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=torch.Tensor, default=Parameter.empty, ), ], return_annotation=torch.Tensor, ) assert hasattr(SAttnRNNModel, 'forward') assert inspect.signature(SAttnRNNModel.forward) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='batch_prev_tkids', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=torch.Tensor, default=Parameter.empty, ), ], return_annotation=torch.Tensor, )
# Written by Conan Albrecht # Released under the Apache open source license # from django.conf import settings from django import forms from django_mako_plus import view_function, render_template from inspect import Signature import inspect formsig = Signature.from_callable(forms.Form.__init__) class Formless(forms.Form): """ A mixin that prints a full form (instead of just the fields). In your view.py file: from django.http import HttpResponseRedirect from django_mako_plus import view_function from formlib import Formless from django import forms @view_function def process_request(request): # process the form form = MyForm(request) if form.is_valid(): d = form.commit(c=3)
def make_signature(names): return Signature( Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names)
def make_sig(*names): parms = [ Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names ] return Signature(parms)
elif base is list: return List[gen_type(r, object)] # type: ignore elif base is set: return Set[gen_type(r, Hashable)] # type: ignore elif base is frozenset: return FrozenSet[gen_type(r, Hashable)] # type: ignore else: return base # TODO: consider replacing this with typeshed someday! _SIGNATURE_OVERRIDES = { getattr: Signature([ Parameter("obj", Parameter.POSITIONAL_ONLY, annotation=object), Parameter("attr", Parameter.POSITIONAL_ONLY, annotation=str), Parameter("default", Parameter.POSITIONAL_ONLY, annotation=object), ]), dict.items: Signature(), dict.keys: Signature(), # TODO: fuzz test values() somehow. items() and keys() are sets and # therefore comparable -- not values() though: # dict.values: Signature(), dict.clear: Signature(), dict.copy: Signature(), dict.pop: Signature([
def test_update_return(self): """Update return annotations from types""" sig = Signature.from_callable(UpdateSignatureHelper.a_class_method) sig = update_signature_return(sig, return_type=str) assert sig == Signature(return_annotation=str)
def test_check_function_3(state): with pytest.raises(InstructorError, match=r"`check_function\(\)` couldn't match the first call of `round` to its signature\."): sig = Signature([Parameter('wrong', Parameter.KEYWORD_ONLY)]) state.check_function('round', 0, signature=sig)
def __signature__(self): return Signature.from_function(self._compiled_fn)
def set_first_arg_type(sig: Signature, first_arg_type: object) -> Signature: newparams = list(sig.parameters.values()) newparams[0] = newparams[0].replace(annotation=first_arg_type) return Signature(newparams, return_annotation=sig.return_annotation)
from typing import Union from inspect import Parameter, Signature from ..primitives import Str, Float, Int, Bool, NoneType from ..array import Array, MaskedArray, Scalar, DType from ..containers import List, Tuple, Slice EMPTY = Parameter.empty VAR_P = Parameter.VAR_POSITIONAL VAR_KW = Parameter.VAR_KEYWORD KW_ONLY = Parameter.KEYWORD_ONLY Param = lambda name, annotation=None, default=EMPTY, kind=Parameter.POSITIONAL_OR_KEYWORD: Parameter( # noqa: E731 name, kind=kind, default=default, annotation=annotation) Sig = lambda parameters, return_annotation: Signature( # noqa: E731 parameters=parameters, return_annotation=return_annotation) # TODO: Once interpret-time compute is available, change Scalar return types to # more specific types, if possible NUMPY_SIGNATURES = { "all": [ Sig([Param("a", Array), Param("axis", Union[Int, List[Int]], None)], Array), Sig( [ Param("a", Union[Array, MaskedArray]), Param("axis", NoneType, None) ], Scalar, # TODO: Bool ),
def _func_stub_from_callable(func: Callable, strip_modules: List[str] = None): kind = FunctionKind.from_callable(func) sig = Signature.from_callable(func) return FunctionStub(func.__name__, sig, kind, strip_modules)
def test_update_self(self): """Don't annotate first arg of instance methods""" sig = Signature.from_callable(UpdateSignatureHelper.an_instance_method) sig = update_signature_args(sig, {'self': UpdateSignatureHelper}, True) expected = Signature(parameters=[Parameter('self', Parameter.POSITIONAL_OR_KEYWORD)]) assert sig == expected
def test_update_yield_and_return(self): sig = Signature.from_callable(UpdateSignatureHelper.a_class_method) sig = update_signature_return(sig, return_type=str, yield_type=int) assert sig == Signature(return_annotation=Generator[int, NoneType, str])
def test_update_class(self): """Don't annotate the first arg of classmethods""" sig = Signature.from_callable(UpdateSignatureHelper.a_class_method.__func__) sig = update_signature_args(sig, {'cls': Type[UpdateSignatureHelper]}, True) expected = Signature(parameters=[Parameter('cls', Parameter.POSITIONAL_OR_KEYWORD)]) assert sig == expected
def _assign_signature(self): from inspect import Parameter, Signature params = [Parameter(h.c_argname, Parameter.POSITIONAL_OR_KEYWORD) for h in self.sig.in_handlers] self.__signature__ = Signature(params)
# STEP 1 -> Estimate Probabilities ''' This step involves using the Forward-Backward algorithm to calculate the probability of observing a sequence, given a set of HMM parameters ''' # Enforce an Argument Signature on following function to prevent errors with **kwargs params = [Parameter('list_of_unique_states', Parameter.POSITIONAL_OR_KEYWORD), Parameter('sequence', Parameter.POSITIONAL_OR_KEYWORD), Parameter('A', Parameter.KEYWORD_ONLY, default=generate_state_trans_dict), Parameter('B', Parameter.KEYWORD_ONLY, default=generate_emission_prob_dist), Parameter('pi', Parameter.KEYWORD_ONLY, default=generate_init_prob_dist)] sig = Signature(params) def calculate_probabilities(list_of_unique_states, sequence, **kwargs): # enforce signature to ensure variable names bound_values = sig.bind(list_of_unique_states, sequence, **kwargs) bound_values.apply_defaults() # grab params that are left to default values param_defaults = [(name, val) for name, val in bound_values.arguments.items() if callable(val)] # grab non-default params set_params = [(name, val) for name, val in bound_values.arguments.items() if isinstance(val, dict)] # this will run if any default hmm parameters are used