Example #1
0
 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
Example #2
0
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
Example #3
0
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__)
Example #4
0
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)
Example #5
0
 def ept_par():  # Return none signature parameter.
     name = Token('none')
     return name, Parameter(name, _POSITIONAL_OR_KEYWORD)
Example #6
0
def make_signature(names):
    return Signature(
        Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names)
Example #7
0

# 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
Example #8
0
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)
Example #9
0
 def _ctor_bind_args(self, args, kw):
     sig = Signature([Parameter("doinit", Parameter.POSITIONAL_OR_KEYWORD)])
     return sig.bind(*args, **kw).arguments
Example #10
0
 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,
    )
Example #13
0
    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
Example #14
0
class WeirdSig:
    __signature__ = Signature(
        parameters=[Parameter(name="args", kind=Parameter.VAR_POSITIONAL)]
    )
Example #15
0
def make_signature(names):
    args = [Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names]
    signature_object = Signature(args)
    return signature_object
Example #16
0
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,
    )
Example #17
0
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)
Example #19
0
 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)
Example #20
0
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,
        )
Example #21
0
# -*- 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')
Example #22
0
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)
Example #23
0
 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])
Example #24
0
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],
    )
Example #25
0
def make_sig(*names):
    parms = [
        Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names
    ]
    return Signature(parms)
Example #26
0
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
Example #27
0
    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
Example #28
0
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",
Example #29
0
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)
Example #30
0
 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))