def __new__(cls, clsname, bases, clsdict): clsobject = super().__new__(cls, clsname, bases, clsdict) keys = clsobject._datafields.keys() sig = Signature( Parameter(name, Parameter.KEYWORD_ONLY, default=Parameter.default) for name in keys ) setattr(clsobject, "__signature__", sig) for enum in clsobject._enums.keys(): for value, const in clsobject._enums[enum].items(): if hasattr(clsobject, const.upper()): raise ValueError(f"{const} already defined") setattr(clsobject, const.upper(), value) for name in keys: if name.startswith("_pad"): setattr(clsobject, name, PaddingField(name=name)) elif name in clsobject._constants.keys(): setattr(clsobject, name, ConstField(name=name)) elif name in clsobject._enums.keys(): setattr(clsobject, name, EnumField(name=name)) setattr(clsobject, f"_{name}", BinField(name=f"_{name}")) else: setattr(clsobject, name, BinField(name=name)) return clsobject
def _create_call(regmap): from inspect import Parameter, Signature sorted_regmap = list(regmap.items()) sorted_regmap.sort(key=lambda x: x[1]['address_offset']) parameters = [] ptr_list = [] struct_string = "=" arg_details = {} for k, v in sorted_regmap: curr_offset = struct.calcsize(struct_string) reg_offset = v['address_offset'] if reg_offset < curr_offset: raise RuntimeError("Struct string generation failed") elif reg_offset > curr_offset: struct_string += "{}x".format(reg_offset - curr_offset) reg_type = v['type'] if "*" in reg_type: struct_string += "Q" ptr_type = True else: struct_string += _struct_dict[v['type']] ptr_type = False if k != 'CTRL': ptr_list.append(ptr_type) parameters.append( Parameter(k, Parameter.POSITIONAL_OR_KEYWORD, annotation=v['type'])) arg_details[k] = XrtArgument( k, len(parameters), v['type'], v['memory'] if 'memory' in v else None) signature = Signature(parameters) return signature, struct_string, ptr_list, arg_details
def mk_signature_from_dict_specs(arg_name_default_annot=(), *, return_annotation=inspect._empty, __validate_parameters__=True): """ :param arg_name_default_annot: :param return_annotation: :param __validate_parameters__: :return: >>> def foo(a, b: int, c=0, d:float=1.0) -> float: ... return a + (c * b) ** d >>> params = mk_arg_name_dflt_annot_dict_list_from_func(foo) >>> s = mk_signature_from_dict_specs(params, return_annotation=float) >>> print(s) (a, b: int, c=0, d: float = 1.0) -> float """ parameters = list() for d in arg_name_default_annot: d = dict(dflt_params, **d) parameters.append(Parameter(**d)) return Signature(parameters=parameters, return_annotation=return_annotation, __validate_parameters__=__validate_parameters__)
def signature(obj): """Get signature function, try to support builtin functions: map, filter, functools.reduce """ if obj is map: return Signature([ Parameter("func", Parameter.POSITIONAL_OR_KEYWORD), Parameter("iter", Parameter.POSITIONAL_OR_KEYWORD), Parameter("iterables", Parameter.VAR_POSITIONAL), ]) elif obj is filter: return Signature([ Parameter("func", Parameter.POSITIONAL_OR_KEYWORD), Parameter("iter", Parameter.POSITIONAL_OR_KEYWORD), ]) elif obj is reduce: return Signature([ Parameter("func", Parameter.POSITIONAL_OR_KEYWORD), Parameter("sequence", Parameter.POSITIONAL_OR_KEYWORD), ]) else: return inspect.signature(obj)
def ept_par(): # Return none signature parameter. name = Token('none') return name, Parameter(name, _POSITIONAL_OR_KEYWORD)
def make_signature(names): return Signature( Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names)
# duplicated example class DupA(metaclass=OrderedMeta): def spam(self): pass def spam2(self): pass # cookbook 9.16 # fixed parm signature # make a signature for a func(x, y=42, *, z=None) 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_value = sig.bind(*args, **kwargs) for name, value in bound_value.arguments.items(): print(name, value) # cookbook 9.16
def signature_from_ast(node: ast.FunctionDef, code: str = '') -> inspect.Signature: """Create a Signature object from AST *node*.""" args = node.args defaults = list(args.defaults) params = [] if hasattr(args, "posonlyargs"): posonlyargs = len(args.posonlyargs) # type: ignore positionals = posonlyargs + len(args.args) else: posonlyargs = 0 positionals = len(args.args) for _ in range(len(defaults), positionals): defaults.insert(0, Parameter.empty) if hasattr(args, "posonlyargs"): for i, arg in enumerate(args.posonlyargs): # type: ignore if defaults[i] is Parameter.empty: default = Parameter.empty else: default = ast_unparse(defaults[i], code) annotation = ast_unparse(arg.annotation, code) or Parameter.empty params.append( Parameter(arg.arg, Parameter.POSITIONAL_ONLY, default=default, annotation=annotation)) for i, arg in enumerate(args.args): if defaults[i + posonlyargs] is Parameter.empty: default = Parameter.empty else: default = ast_unparse(defaults[i + posonlyargs], code) annotation = ast_unparse(arg.annotation, code) or Parameter.empty params.append( Parameter(arg.arg, Parameter.POSITIONAL_OR_KEYWORD, default=default, annotation=annotation)) if args.vararg: annotation = ast_unparse(args.vararg.annotation, code) or Parameter.empty params.append( Parameter(args.vararg.arg, Parameter.VAR_POSITIONAL, annotation=annotation)) for i, arg in enumerate(args.kwonlyargs): default = ast_unparse(args.kw_defaults[i], code) or Parameter.empty annotation = ast_unparse(arg.annotation, code) or Parameter.empty params.append( Parameter(arg.arg, Parameter.KEYWORD_ONLY, default=default, annotation=annotation)) if args.kwarg: annotation = ast_unparse(args.kwarg.annotation, code) or Parameter.empty params.append( Parameter(args.kwarg.arg, Parameter.VAR_KEYWORD, annotation=annotation)) return_annotation = ast_unparse(node.returns, code) or Parameter.empty return inspect.Signature(params, return_annotation=return_annotation)
def _ctor_bind_args(self, args, kw): sig = Signature([Parameter("doinit", Parameter.POSITIONAL_OR_KEYWORD)]) return sig.bind(*args, **kw).arguments
def resolve(self, parameter: inspect.Parameter, data: ValidatedRequestData): try: return parameter.annotation(data) except validators.ValidationError as exc: raise exceptions.BadRequest(exc.detail)
def parametrize_plus_decorate(test_func): """ A decorator that wraps the test function so that instead of receiving the parameter names, it receives the new fixture. All other decorations are unchanged. :param test_func: :return: """ test_func_name = test_func.__name__ # Are there explicit ids provided ? try: if len(ids) != len(argvalues): raise ValueError("Explicit list of `ids` provided has a different length (%s) than the number of " "parameter sets (%s)" % (len(ids), len(argvalues))) explicit_ids_to_use = [] except TypeError: explicit_ids_to_use = None # first check if the test function has the parameters as arguments old_sig = signature(test_func) for p in argnames: if p not in old_sig.parameters: raise ValueError("parameter '%s' not found in test function signature '%s%s'" "" % (p, test_func_name, old_sig)) # The name for the final "union" fixture # style_template = "%s_param__%s" main_fixture_style_template = "%s_%s" fixture_union_name = main_fixture_style_template % (test_func_name, param_names_str) fixture_union_name = check_name_available(caller_module, fixture_union_name, if_name_exists=CHANGE, caller=parametrize_plus) # Retrieve (if ref) or create (for normal argvalues) the fixtures that we will union fixture_alternatives = [] prev_i = -1 for i, j_list in fixture_indices: # noqa # A/ Is there any non-empty group of 'normal' parameters before the fixture_ref at <i> ? If so, handle. if i > prev_i + 1: # create a new "param" fixture parametrized with all of that consecutive group. # Important note: we could either wish to create one fixture for parameter value or to create # one for each consecutive group as shown below. This should not lead to different results but perf # might differ. Maybe add a parameter in the signature so that users can test it ? # this would make the ids more readable by removing the "P2toP3"-like ids p_fix_name, p_fix_alt = _create_params_alt(test_func_name=test_func_name, hook=hook, union_name=fixture_union_name, from_i=prev_i + 1, to_i=i) fixture_alternatives.append((p_fix_name, p_fix_alt)) if explicit_ids_to_use is not None: if isinstance(p_fix_alt, SingleParamAlternative): explicit_ids_to_use.append(ids[prev_i + 1]) else: # the ids provided by the user are propagated to the params of this fix, so we need an id explicit_ids_to_use.append(ParamIdMakers.explicit(p_fix_alt)) # B/ Now handle the fixture ref at position <i> if j_list is None: # argvalues[i] contains a single argvalue that is a fixture_ref : add the referenced fixture f_fix_name, f_fix_alt = _create_fixture_ref_alt(union_name=fixture_union_name, i=i) fixture_alternatives.append((f_fix_name, f_fix_alt)) if explicit_ids_to_use is not None: explicit_ids_to_use.append(ids[i]) else: # argvalues[i] is a tuple, some of them being fixture_ref. create a fixture refering to all of them prod_fix_name, prod_fix_alt = _create_fixture_ref_product(union_name=fixture_union_name, i=i, fixture_ref_positions=j_list, test_func_name=test_func_name, hook=hook) fixture_alternatives.append((prod_fix_name, prod_fix_alt)) if explicit_ids_to_use is not None: explicit_ids_to_use.append(ids[i]) prev_i = i # C/ handle last consecutive group of normal parameters, if any i = len(argvalues) # noqa if i > prev_i + 1: p_fix_name, p_fix_alt = _create_params_alt(test_func_name=test_func_name, union_name=fixture_union_name, from_i=prev_i + 1, to_i=i, hook=hook) fixture_alternatives.append((p_fix_name, p_fix_alt)) if explicit_ids_to_use is not None: if isinstance(p_fix_alt, SingleParamAlternative): explicit_ids_to_use.append(ids[prev_i + 1]) else: # the ids provided by the user are propagated to the params of this fix, so we need an id explicit_ids_to_use.append(ParamIdMakers.explicit(p_fix_alt)) # TO DO if fixtures_to_union has length 1, simplify ? >> No, we leave such "optimization" to the end user # consolidate the list of alternatives fix_alternatives = tuple(a[1] for a in fixture_alternatives) # and the list of their names. Duplicates should be removed here fix_alt_names = [] for a, alt in fixture_alternatives: if a not in fix_alt_names: fix_alt_names.append(a) else: # this should only happen when the alternative is directly a fixture reference assert isinstance(alt, FixtureParamAlternative), \ "Created fixture names are not unique, please report" # Finally create a "main" fixture with a unique name for this test function if debug: print("Creating final union fixture %r with alternatives %r" % (fixture_union_name, fix_alternatives)) # note: the function automatically registers it in the module _make_fixture_union(caller_module, name=fixture_union_name, hook=hook, caller=parametrize_plus, fix_alternatives=fix_alternatives, unique_fix_alt_names=fix_alt_names, ids=explicit_ids_to_use or ids or ParamIdMakers.get(idstyle)) # --create the new test function's signature that we want to expose to pytest # it is the same than existing, except that we want to replace all parameters with the new fixture # first check where we should insert the new parameters (where is the first param we remove) _first_idx = -1 for _first_idx, _n in enumerate(old_sig.parameters): if _n in argnames: break # then remove all parameters that will be replaced by the new fixture new_sig = remove_signature_parameters(old_sig, *argnames) # finally insert the new fixture in that position. Indeed we can not insert first or last, because # 'self' arg (case of test class methods) should stay first and exec order should be preserved when possible new_sig = add_signature_parameters(new_sig, custom_idx=_first_idx, custom=Parameter(fixture_union_name, kind=Parameter.POSITIONAL_OR_KEYWORD)) if debug: print("Creating final test function wrapper with signature %s%s" % (test_func_name, new_sig)) # --Finally create the fixture function, a wrapper of user-provided fixture with the new signature def replace_paramfixture_with_values(kwargs): # noqa # remove the created fixture value encompassing_fixture = kwargs.pop(fixture_union_name) # and add instead the parameter values if nb_params > 1: for i, p in enumerate(argnames): # noqa kwargs[p] = encompassing_fixture[i] else: kwargs[argnames[0]] = encompassing_fixture # return return kwargs if not isgeneratorfunction(test_func): # normal test function with return statement @wraps(test_func, new_sig=new_sig) def wrapped_test_func(*args, **kwargs): # noqa if kwargs.get(fixture_union_name, None) is NOT_USED: # TODO why this ? it is probably useless: this fixture # is private and will never end up in another union return NOT_USED else: replace_paramfixture_with_values(kwargs) return test_func(*args, **kwargs) else: # generator test function (with one or several yield statements) @wraps(test_func, new_sig=new_sig) def wrapped_test_func(*args, **kwargs): # noqa if kwargs.get(fixture_union_name, None) is NOT_USED: # TODO why this ? it is probably useless: this fixture # is private and will never end up in another union yield NOT_USED else: replace_paramfixture_with_values(kwargs) for res in test_func(*args, **kwargs): yield res # move all pytest marks from the test function to the wrapper # not needed because the __dict__ is automatically copied when we use @wraps # move_all_pytest_marks(test_func, wrapped_test_func) # With this hack we will be ordered correctly by pytest https://github.com/pytest-dev/pytest/issues/4429 wrapped_test_func.place_as = test_func # return the new test function return wrapped_test_func
def test_instance_method(): r"""Ensure instance methods' signature.""" assert hasattr(ResSAttnGRUBlock, '__init__') assert inspect.signature(ResSAttnGRUBlock.__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], ), ], return_annotation=Signature.empty, ) assert hasattr(ResSAttnGRUModel, '__init__') assert inspect.signature(ResSAttnGRUModel.__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], ), ], return_annotation=Signature.empty, )
def __init__(self, backends: Sequence[BaseAuthentication], user_db: BaseUserDatabase): self.backends = backends self.user_db = user_db parameters = [ Parameter(name=name_to_variable_name(backend.name), kind=Parameter.POSITIONAL_OR_KEYWORD, default=Depends(backend.scheme)) for backend in self.backends ] signature = Signature(parameters) @with_signature(signature, func_name='get_optional_current_user') async def get_optional_current_user(*args, **kwargs): return await self.authenticate(*args, **kwargs) @with_signature(signature, func_name='get_optional_current_active_user') async def get_optional_current_active_user(*args, **kwargs): user = await get_optional_current_user(*args, **kwargs) if not user or not user.is_active: return None return user @with_signature(signature, func_name='get_optional_current_superuser') async def get_optional_current_superuser(*args, **kwargs): user = await get_optional_current_active_user(*args, **kwargs) if not user or not user.is_superuser: return None return user @with_signature(signature, func_name='get_current_user') async def get_current_user(*args, **kwargs): user = await get_optional_current_user(*args, **kwargs) if user is None: raise HTTPException(status_code=403, detail='You do not have the permission') return user @with_signature(signature, func_name='get_current_active_user') async def get_current_active_user(*args, **kwargs): user = await get_optional_current_active_user(*args, **kwargs) if user is None: raise HTTPException(status_code=403, detail='You do not have the permission') return user @with_signature(signature, func_name='get_current_superuser') async def get_current_superuser(*args, **kwargs): user = await get_optional_current_active_user(*args, **kwargs) if user is None: raise HTTPException(status_code=403, detail='You do not have the permission') if not user.is_superuser: raise HTTPException(status_code=403, detail='You need to be superuser') return user self.get_current_user = get_current_user self.get_current_active_user = get_current_active_user self.get_optional_current_active_user = get_optional_current_active_user self.get_optional_current_superuser = get_optional_current_superuser self.get_optional_current_user = get_optional_current_user self.get_current_superuser = get_current_superuser
class WeirdSig: __signature__ = Signature( parameters=[Parameter(name="args", kind=Parameter.VAR_POSITIONAL)] )
def make_signature(names): args = [Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names] signature_object = Signature(args) return signature_object
def test_module_method() -> None: """Ensure module methods' signatures.""" assert hasattr(lmp.util.optim, 'get_optimizer') assert inspect.isfunction(lmp.util.optim.get_optimizer) assert inspect.signature(lmp.util.optim.get_optimizer) == Signature( parameters=[ Parameter( name='beta1', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=float, ), Parameter( name='beta2', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=float, ), Parameter( name='eps', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=float, ), Parameter( name='lr', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=float, ), Parameter( name='model', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=BaseModel, ), Parameter( name='wd', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=float, ), ], return_annotation=torch.optim.AdamW, ) assert hasattr(lmp.util.optim, 'get_scheduler') assert inspect.isfunction(lmp.util.optim.get_scheduler) assert inspect.signature(lmp.util.optim.get_scheduler) == Signature( parameters=[ Parameter( name='optim', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=torch.optim.AdamW, ), Parameter( name='total_step', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=int, ), Parameter( name='warmup_step', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=int, ), ], return_annotation=torch.optim.lr_scheduler.LambdaLR, )
def signature_has_traits(cls): """Return a decorated class with a constructor signature that contain Trait names as kwargs.""" traits = [(name, _get_default(value.default_value)) for name, value in cls.class_traits().items() if not name.startswith('_')] # Taking the __init__ signature, as the cls signature is not initialized yet old_signature = signature(cls.__init__) old_parameter_names = list(old_signature.parameters) old_positional_parameters = [] old_var_positional_parameter = None # This won't be None if the old signature contains *args old_keyword_only_parameters = [] old_var_keyword_parameter = None # This won't be None if the old signature contains **kwargs for parameter_name in old_signature.parameters: # Copy the parameter parameter = copy.copy(old_signature.parameters[parameter_name]) if parameter.kind is Parameter.POSITIONAL_ONLY or parameter.kind is Parameter.POSITIONAL_OR_KEYWORD: old_positional_parameters.append(parameter) elif parameter.kind is Parameter.VAR_POSITIONAL: old_var_positional_parameter = parameter elif parameter.kind is Parameter.KEYWORD_ONLY: old_keyword_only_parameters.append(parameter) elif parameter.kind is Parameter.VAR_KEYWORD: old_var_keyword_parameter = parameter # Unfortunately, if the old signature does not contain **kwargs, we can't do anything, # because it can't accept traits as keyword arguments if old_var_keyword_parameter is None: raise RuntimeError( 'The {} constructor does not take **kwargs, which means that the signature can not be expanded with trait names' .format(cls)) new_parameters = [] # Append the old positional parameters (except `self` which is the first parameter) new_parameters += old_positional_parameters[1:] # Append *args if the old signature had it if old_var_positional_parameter is not None: new_parameters.append(old_var_positional_parameter) # Append the old keyword only parameters new_parameters += old_keyword_only_parameters # Append trait names as keyword only parameters in the signature new_parameters += [ Parameter(name, kind=Parameter.KEYWORD_ONLY, default=default) for name, default in traits if name not in old_parameter_names ] # Append **kwargs new_parameters.append(old_var_keyword_parameter) cls.__signature__ = Signature(new_parameters) return cls
def _decorate_fixture_plus( fixture_func, scope="function", # type: str autouse=False, # type: bool name=None, # type: str unpack_into=None, # type: Iterable[str] hook=None, # type: Callable[[Callable], Callable] _caller_module_offset_when_unpack=3, # type: int **kwargs): """ decorator to mark a fixture factory function. Identical to `@pytest.fixture` decorator, except that - it supports multi-parametrization with `@pytest.mark.parametrize` as requested in https://github.com/pytest-dev/pytest/issues/3960. As a consequence it does not support the `params` and `ids` arguments anymore. - it supports a new argument `unpack_into` where you can provide names for fixtures where to unpack this fixture into. :param scope: the scope for which this fixture is shared, one of "function" (default), "class", "module" or "session". :param autouse: if True, the fixture func is activated for all tests that can see it. If False (the default) then an explicit reference is needed to activate the fixture. :param name: the name of the fixture. This defaults to the name of the decorated function. Note: If a fixture is used in the same module in which it is defined, the function name of the fixture will be shadowed by the function arg that requests the fixture; one way to resolve this is to name the decorated function ``fixture_<fixturename>`` and then use ``@pytest.fixture(name='<fixturename>')``. :param unpack_into: an optional iterable of names, or string containing coma-separated names, for additional fixtures to create to represent parts of this fixture. See `unpack_fixture` for details. :param hook: an optional hook to apply to each fixture function that is created during this call. The hook function will be called everytime a fixture is about to be created. It will receive a single argument (the function implementing the fixture) and should return the function to use. For example you can use `saved_fixture` from `pytest-harvest` as a hook in order to save all such created fixtures in the fixture store. :param kwargs: other keyword arguments for `@pytest.fixture` """ if name is not None: # Compatibility for the 'name' argument if LooseVersion(pytest.__version__) >= LooseVersion('3.0.0'): # pytest version supports "name" keyword argument kwargs['name'] = name elif name is not None: # 'name' argument is not supported in this old version, use the __name__ trick. fixture_func.__name__ = name # if unpacking is requested, do it first if unpack_into is not None: # get the future fixture name if needed if name is None: name = fixture_func.__name__ # get caller module to create the symbols caller_module = get_caller_module( frame_offset=_caller_module_offset_when_unpack) _make_unpack_fixture(caller_module, unpack_into, name, hook=hook) # (1) Collect all @pytest.mark.parametrize markers (including those created by usage of @cases_data) parametrizer_marks = get_pytest_parametrize_marks(fixture_func) if len(parametrizer_marks) < 1: # make the fixture union-aware wrapped_fixture_func = ignore_unused(fixture_func) # transform the created wrapper into a fixture return pytest_fixture(scope=scope, autouse=autouse, hook=hook, **kwargs)(wrapped_fixture_func) else: if 'params' in kwargs: raise ValueError( "With `fixture_plus` you cannot mix usage of the keyword argument `params` and of " "the pytest.mark.parametrize marks") # (2) create the huge "param" containing all params combined # --loop (use the same order to get it right) params_names_or_name_combinations = [] params_values = [] params_ids = [] params_marks = [] for pmark in parametrizer_marks: # -- pmark is a single @pytest.parametrize mark. -- # check number of parameter names in this parameterset if len(pmark.param_names) < 1: raise ValueError( "Fixture function '%s' decorated with '@fixture_plus' has an empty parameter " "name in a @pytest.mark.parametrize mark") # remember the argnames params_names_or_name_combinations.append(pmark.param_names) # analyse contents, extract marks and custom ids, apply custom ids _paramids, _pmarks, _pvalues = analyze_parameter_set(pmark=pmark, check_nb=True) # Finally store the ids, marks, and values for this parameterset params_ids.append(_paramids) params_marks.append(tuple(_pmarks)) params_values.append(tuple(_pvalues)) # (3) generate the ids and values, possibly reapplying marks if len(params_names_or_name_combinations) == 1: # we can simplify - that will be more readable final_ids = params_ids[0] final_marks = params_marks[0] final_values = list(params_values[0]) # reapply the marks for i, marks in enumerate(final_marks): if marks is not None: final_values[i] = make_marked_parameter_value( (final_values[i], ), marks=marks) else: final_values = list(product(*params_values)) final_ids = combine_ids(product(*params_ids)) final_marks = tuple(product(*params_marks)) # reapply the marks for i, marks in enumerate(final_marks): ms = [m for mm in marks if mm is not None for m in mm] if len(ms) > 0: final_values[i] = make_marked_parameter_value( (final_values[i], ), marks=ms) if len(final_values) != len(final_ids): raise ValueError( "Internal error related to fixture parametrization- please report") # (4) wrap the fixture function so as to remove the parameter names and add 'request' if needed all_param_names = tuple(v for pnames in params_names_or_name_combinations for v in pnames) # --create the new signature that we want to expose to pytest old_sig = signature(fixture_func) for p in all_param_names: if p not in old_sig.parameters: raise ValueError( "parameter '%s' not found in fixture signature '%s%s'" "" % (p, fixture_func.__name__, old_sig)) new_sig = remove_signature_parameters(old_sig, *all_param_names) # add request if needed func_needs_request = 'request' in old_sig.parameters if not func_needs_request: new_sig = add_signature_parameters( new_sig, first=Parameter('request', kind=Parameter.POSITIONAL_OR_KEYWORD)) # --common routine used below. Fills kwargs with the appropriate names and values from fixture_params def _map_arguments(*_args, **_kwargs): request = _kwargs['request'] if func_needs_request else _kwargs.pop( 'request') # populate the parameters if len(params_names_or_name_combinations) == 1: _params = [request.param] # remove the simplification else: _params = request.param for p_names, fixture_param_value in zip( params_names_or_name_combinations, _params): if len(p_names) == 1: # a single parameter for that generated fixture (@pytest.mark.parametrize with a single name) _kwargs[p_names[0]] = get_lazy_args(fixture_param_value) else: # several parameters for that generated fixture (@pytest.mark.parametrize with several names) # unpack all of them and inject them in the kwargs for old_p_name, old_p_value in zip(p_names, fixture_param_value): _kwargs[old_p_name] = get_lazy_args(old_p_value) return _args, _kwargs # --Finally create the fixture function, a wrapper of user-provided fixture with the new signature if not isgeneratorfunction(fixture_func): # normal function with return statement @wraps(fixture_func, new_sig=new_sig) def wrapped_fixture_func(*_args, **_kwargs): if not is_used_request(_kwargs['request']): return NOT_USED else: _args, _kwargs = _map_arguments(*_args, **_kwargs) return fixture_func(*_args, **_kwargs) else: # generator function (with a yield statement) @wraps(fixture_func, new_sig=new_sig) def wrapped_fixture_func(*_args, **_kwargs): if not is_used_request(_kwargs['request']): yield NOT_USED else: _args, _kwargs = _map_arguments(*_args, **_kwargs) for res in fixture_func(*_args, **_kwargs): yield res # transform the created wrapper into a fixture _make_fix = pytest_fixture(scope=scope, params=final_values, autouse=autouse, hook=hook, ids=final_ids, **kwargs) return _make_fix(wrapped_fixture_func)
def prepare_args(raw_response) -> Mapping[str, Parameter]: args = re.findall(r"{(\d+)[^:}]*(:[^.}]*)?[^}]*\}", raw_response) default = [("ctx", Parameter("ctx", Parameter.POSITIONAL_OR_KEYWORD))] if not args: return OrderedDict(default) allowed_builtins = { "bool": bool, "complex": complex, "float": float, "frozenset": frozenset, "int": int, "list": list, "set": set, "str": str, "tuple": tuple, "query": quote_plus, } indices = [int(a[0]) for a in args] low = min(indices) indices = [a - low for a in indices] high = max(indices) if high > 9: raise ArgParseError(_("Too many arguments!")) gaps = set(indices).symmetric_difference(range(high + 1)) if gaps: raise ArgParseError( _("Arguments must be sequential. Missing arguments: ") + ", ".join(str(i + low) for i in gaps)) fin = [ Parameter("_" + str(i), Parameter.POSITIONAL_OR_KEYWORD) for i in range(high + 1) ] for arg in args: index = int(arg[0]) - low anno = arg[1][1:] # strip initial colon if anno.lower().endswith("converter"): anno = anno[:-9] if not anno or anno.startswith("_"): # public types only name = "{}_{}".format("text", index if index < high else "final") fin[index] = fin[index].replace(name=name) continue # allow type hinting only for discord.py and builtin types try: anno = getattr(discord, anno) # force an AttributeError if there's no discord.py converter getattr(commands, anno.__name__ + "Converter") except AttributeError: anno = allowed_builtins.get(anno.lower(), Parameter.empty) if (anno is not Parameter.empty and fin[index].annotation is not Parameter.empty and anno != fin[index].annotation): raise ArgParseError( _('Conflicting colon notation for argument {index}: "{name1}" and "{name2}".' ).format( index=index + low, name1=fin[index].annotation.__name__, name2=anno.__name__, )) if anno is not Parameter.empty: fin[index] = fin[index].replace(annotation=anno) # consume rest fin[-1] = fin[-1].replace(kind=Parameter.KEYWORD_ONLY) # name the parameters for the help text for i, param in enumerate(fin): anno = param.annotation name = "{}_{}".format( "text" if anno is Parameter.empty else anno.__name__.lower(), i if i < high else "final", ) fin[i] = fin[i].replace(name=name) # insert ctx parameter for discord.py parsing fin = default + [(p.name, p) for p in fin] return OrderedDict(fin)
def test_instance_method() -> None: """Ensure instance methods' signatures.""" assert hasattr(lmp.util.dset.FastTensorDset, '__getitem__') assert inspect.isfunction(lmp.util.dset.FastTensorDset.__getitem__) assert inspect.signature( lmp.util.dset.FastTensorDset.__getitem__) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='idx', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=int, ), ], return_annotation=torch.Tensor, ) assert hasattr(lmp.util.dset.FastTensorDset, '__init__') assert inspect.isfunction(lmp.util.dset.FastTensorDset.__init__) assert inspect.signature( lmp.util.dset.FastTensorDset.__init__) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='dset', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=BaseDset, ), Parameter( name='max_seq_len', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=int, ), Parameter( name='tknzr', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=BaseTknzr, ), ], return_annotation=Signature.empty, ) assert hasattr(lmp.util.dset.FastTensorDset, '__iter__') assert inspect.isfunction(lmp.util.dset.FastTensorDset.__iter__) assert inspect.signature( lmp.util.dset.FastTensorDset.__iter__) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), ], return_annotation=Iterator[torch.Tensor], ) assert hasattr(lmp.util.dset.FastTensorDset, '__len__') assert inspect.isfunction(lmp.util.dset.FastTensorDset.__len__) assert inspect.signature( lmp.util.dset.FastTensorDset.__len__) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), ], return_annotation=int, ) assert hasattr(lmp.util.dset.SlowTensorDset, '__getitem__') assert inspect.isfunction(lmp.util.dset.SlowTensorDset.__getitem__) assert inspect.signature( lmp.util.dset.SlowTensorDset.__getitem__) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='idx', kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=int, ), ], return_annotation=torch.Tensor, ) assert hasattr(lmp.util.dset.SlowTensorDset, '__init__') assert inspect.isfunction(lmp.util.dset.SlowTensorDset.__init__) assert inspect.signature( lmp.util.dset.SlowTensorDset.__init__) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='dset', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=BaseDset, ), Parameter( name='max_seq_len', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=int, ), Parameter( name='tknzr', kind=Parameter.KEYWORD_ONLY, default=Parameter.empty, annotation=BaseTknzr, ), ], return_annotation=Signature.empty, ) assert hasattr(lmp.util.dset.SlowTensorDset, '__iter__') assert inspect.isfunction(lmp.util.dset.SlowTensorDset.__iter__) assert inspect.signature( lmp.util.dset.SlowTensorDset.__iter__) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), ], return_annotation=Iterator[torch.Tensor], ) assert hasattr(lmp.util.dset.SlowTensorDset, '__len__') assert inspect.isfunction(lmp.util.dset.SlowTensorDset.__len__) assert inspect.signature( lmp.util.dset.SlowTensorDset.__len__) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), ], return_annotation=int, )
# -*- coding: utf-8 -*- # 函数强制参数签名 from inspect import Signature, Parameter params = [Parameter('x', Parameter.POSITIONAL_ONLY, default=42), Parameter('y', Parameter.POSITIONAL_ONLY, default=1), Parameter('z', Parameter.KEYWORD_ONLY, default=None)] sig = Signature(params) def my(*args, **kwargs): bound_values = sig.bind(*args, **kwargs) for name, value in bound_values.arguments.items(): print(name, value) my('xxx')
def test_viewable_signature(viewable): from inspect import Parameter, signature parameters = signature(viewable).parameters assert 'params' in parameters assert parameters['params'] == Parameter('params', Parameter.VAR_KEYWORD)
def _generate_signature(cls): from inspect import Signature, Parameter keywords = ['backend', 'fig', 'holomap', 'widgets', 'fps', 'max_frames', 'size', 'dpi', 'filename', 'info', 'css', 'widget_location'] return Signature([Parameter(kw, Parameter.KEYWORD_ONLY) for kw in keywords])
def test_instance_method(subclss_tknzr): r"""Ensure instance methods' signature.""" assert hasattr(BaseTknzr, '__init__') assert inspect.ismethod(subclss_tknzr.__init__) assert inspect.signature(BaseTknzr.__init__) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='is_uncased', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=bool, ), Parameter( name='max_vocab', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=int, ), Parameter( name='min_count', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=int, ), Parameter( name='tk2id', kind=Parameter.KEYWORD_ONLY, default=None, annotation=Optional[Dict[str, int]], ), Parameter( name='kwargs', kind=Parameter.VAR_KEYWORD, annotation=Optional[Dict], ), ], return_annotation=Signature.empty, ) assert hasattr(BaseTknzr, 'batch_enc') assert inspect.ismethod(subclss_tknzr.batch_enc) assert inspect.signature(BaseTknzr.batch_enc) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='batch_txt', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=Sequence[str], ), Parameter( name='max_seq_len', kind=Parameter.KEYWORD_ONLY, default=-1, annotation=int, ), ], return_annotation=List[List[int]], ) assert hasattr(BaseTknzr, 'batch_dec') assert inspect.ismethod(subclss_tknzr.batch_dec) assert inspect.signature(BaseTknzr.batch_dec) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='batch_tkids', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=Sequence[Sequence[int]], ), Parameter( name='rm_sp_tks', kind=Parameter.KEYWORD_ONLY, default=False, annotation=bool, ), ], return_annotation=List[str], ) assert hasattr(BaseTknzr, 'build_vocab') assert inspect.ismethod(subclss_tknzr.build_vocab) assert inspect.signature(BaseTknzr.build_vocab) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='batch_txt', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=Sequence[str], ), ], return_annotation=None, ) assert hasattr(BaseTknzr, 'dec') assert inspect.ismethod(subclss_tknzr.dec) assert inspect.signature(BaseTknzr.dec) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='tkids', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=Sequence[int], ), Parameter( name='rm_sp_tks', kind=Parameter.KEYWORD_ONLY, default=False, annotation=Optional[bool], ), ], return_annotation=str, ) assert hasattr(BaseTknzr, 'dtknz') assert inspect.ismethod(subclss_tknzr.dtknz) assert inspect.signature(BaseTknzr.dtknz) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='tks', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=Sequence[str], ), ], return_annotation=str, ) assert hasattr(BaseTknzr, 'enc') assert inspect.ismethod(subclss_tknzr.enc) assert inspect.signature(BaseTknzr.enc) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='txt', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=str, ), Parameter( name='max_seq_len', kind=Parameter.KEYWORD_ONLY, default=-1, annotation=Optional[int], ), ], return_annotation=List[int], ) assert hasattr(BaseTknzr, 'norm') assert inspect.ismethod(subclss_tknzr.norm) assert inspect.signature(BaseTknzr.norm) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='txt', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=str, ), ], return_annotation=str, ) assert hasattr(BaseTknzr, 'save') assert inspect.ismethod(subclss_tknzr.save) assert inspect.signature(BaseTknzr.save) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='exp_name', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=str, ), ], return_annotation=None, ) assert hasattr(BaseTknzr, 'tknz') assert inspect.ismethod(subclss_tknzr.tknz) assert inspect.signature(BaseTknzr.tknz) == Signature( parameters=[ Parameter( name='self', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, ), Parameter( name='txt', kind=Parameter.POSITIONAL_OR_KEYWORD, default=Parameter.empty, annotation=str, ), ], return_annotation=List[str], )
def make_sig(*names): parms = [ Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names ] return Signature(parms)
def _preprocess_data(func=None, *, replace_names=None, label_namer=None): """ A decorator to add a 'data' kwarg to a function. When applied:: @_preprocess_data() def func(ax, *args, **kwargs): ... the signature is modified to ``decorated(ax, *args, data=None, **kwargs)`` with the following behavior: - if called with ``data=None``, forward the other arguments to ``func``; - otherwise, *data* must be a mapping; for any argument passed in as a string ``name``, replace the argument by ``data[name]`` (if this does not throw an exception), then forward the arguments to ``func``. In either case, any argument that is a `MappingView` is also converted to a list. Parameters ---------- replace_names : list of str or None, default: None The list of parameter names for which lookup into *data* should be attempted. If None, replacement is attempted for all arguments. label_namer : str, default: None If set e.g. to "namer" (which must be a kwarg in the function's signature -- not as ``**kwargs``), if the *namer* argument passed in is a (string) key of *data* and no *label* kwarg is passed, then use the (string) value of the *namer* as *label*. :: @_preprocess_data(label_namer="foo") def func(foo, label=None): ... func("key", data={"key": value}) # is equivalent to func.__wrapped__(value, label="key") """ if func is None: # Return the actual decorator. return functools.partial(_preprocess_data, replace_names=replace_names, label_namer=label_namer) sig = inspect.signature(func) varargs_name = None varkwargs_name = None arg_names = [] params = list(sig.parameters.values()) for p in params: if p.kind is Parameter.VAR_POSITIONAL: varargs_name = p.name elif p.kind is Parameter.VAR_KEYWORD: varkwargs_name = p.name else: arg_names.append(p.name) data_param = Parameter("data", Parameter.KEYWORD_ONLY, default=None) if varkwargs_name: params.insert(-1, data_param) else: params.append(data_param) new_sig = sig.replace(parameters=params) arg_names = arg_names[1:] # remove the first "ax" / self arg assert {*arg_names}.issuperset(replace_names or []) or varkwargs_name, ( "Matplotlib internal error: invalid replace_names ({!r}) for {!r}". format(replace_names, func.__name__)) assert label_namer is None or label_namer in arg_names, ( "Matplotlib internal error: invalid label_namer ({!r}) for {!r}". format(label_namer, func.__name__)) @functools.wraps(func) def inner(ax, *args, data=None, **kwargs): if data is None: return func(ax, *map(sanitize_sequence, args), **kwargs) bound = new_sig.bind(ax, *args, **kwargs) needs_label = (label_namer and "label" not in bound.arguments and "label" not in bound.kwargs) auto_label = (bound.arguments.get(label_namer) or bound.kwargs.get(label_namer)) for k, v in bound.arguments.items(): if k == varkwargs_name: for k1, v1 in v.items(): if replace_names is None or k1 in replace_names: v[k1] = _replacer(data, v1) elif k == varargs_name: if replace_names is None: bound.arguments[k] = tuple(_replacer(data, v1) for v1 in v) else: if replace_names is None or k in replace_names: bound.arguments[k] = _replacer(data, v) bound.apply_defaults() del bound.arguments["data"] if needs_label: all_kwargs = {**bound.arguments, **bound.kwargs} # label_namer will be in all_kwargs as we asserted above that # `label_namer is None or label_namer in arg_names`. label = _label_from_arg(all_kwargs[label_namer], auto_label) if "label" in arg_names: bound.arguments["label"] = label try: bound.arguments.move_to_end(varkwargs_name) except KeyError: pass else: bound.arguments.setdefault(varkwargs_name, {})["label"] = label return func(*bound.args, **bound.kwargs) inner.__doc__ = _add_data_doc(inner.__doc__, replace_names) inner.__signature__ = new_sig return inner
def parameters(cls): ''' Generate Python ``Parameter`` values suitable for functions that are derived from the glyph. Returns: list(Parameter) ''' arg_params = [] no_more_defaults = False for arg in reversed(cls._args): descriptor = cls.lookup(arg) default = descriptor.class_default(cls) if default is None: no_more_defaults = True # simplify field(x) defaults to just present the column name if isinstance(default, dict) and set(default) == {"field"}: default = default["field"] # make sure we don't hold on to references to actual Models if isinstance(default, Model): default = _ModelRepr(default) param = Parameter( name=arg, kind=Parameter.POSITIONAL_OR_KEYWORD, # For positional arg properties, default=None means no default. default=Parameter.empty if no_more_defaults else default ) if default: del default typ = type_link(descriptor.property) arg_params.insert(0, (param, typ, descriptor.__doc__)) # these are not really useful, and should also really be private, just skip them omissions = {'js_event_callbacks', 'js_property_callbacks', 'subscribed_events'} kwarg_params = [] kws = set(cls.properties()) - set(cls._args) - omissions for kw in kws: descriptor = cls.lookup(kw) default = descriptor.class_default(cls) # simplify field(x) defaults to just present the column name if isinstance(default, dict) and set(default) == {"field"}: default = default["field"] # make sure we don't hold on to references to actual Models if isinstance(default, Model): default = _ModelRepr(default) param = Parameter( name=kw, kind=Parameter.KEYWORD_ONLY, default=default ) del default typ = type_link(descriptor.property) kwarg_params.append((param, typ, descriptor.__doc__)) for kw, (typ, doc) in cls._extra_kws.items(): param = Parameter( name=kw, kind=Parameter.KEYWORD_ONLY, ) kwarg_params.append((param, typ, doc)) kwarg_params.sort(key=lambda x: x[0].name) return arg_params + kwarg_params
try: from inspect import Signature, Parameter except ImportError: # py2 from funcsigs import Signature, Parameter import pytest __all__ = ['simplified_test_function', 'ignore_warnings', 'expect_warnings'] # 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",
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 add_arg(name: str, kind: Any, default: Optional[ast.expr]) -> None: default_val = Parameter.empty if default is None else _ValueFormatter( default) parameters.append(Parameter(name, kind, default=default_val))