How to use the makefun.add_signature_parameters function in makefun

To help you get started, we’ve selected a few makefun examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github smarie / python-pytest-steps / pytest_steps / steps_generator.py View on Github external
def one_fixture_per_step_decorate(fixture_fun):
    """ Implementation of the @one_fixture_per_step decorator, for manual decoration"""

    def _check_scope(request):
        scope = get_scope(request)
        if scope != 'function':
            # session- or module-scope
            raise Exception("The `@one_fixture_per_step` decorator is only useful for function-scope fixtures. `%s`"
                            " seems to have scope='%s'. Consider removing `@one_fixture_per_step` or changing "
                            "the scope to 'function'." % (fixture_fun, scope))

    # We will expose a new signature with additional arguments
    orig_sig = signature(fixture_fun)
    func_needs_request = 'request' in orig_sig.parameters
    if not func_needs_request:
        new_sig = add_signature_parameters(orig_sig, first=Parameter('request', kind=Parameter.POSITIONAL_OR_KEYWORD))
    else:
        new_sig = orig_sig

    if not isgeneratorfunction(fixture_fun):
        @wraps(fixture_fun, new_sig=new_sig)
        def _steps_aware_decorated_function(*args, **kwargs):
            request = kwargs['request'] if func_needs_request else kwargs.pop('request')
            _check_scope(request)
            res = fixture_fun(*args, **kwargs)
            return _OnePerStepFixtureProxy(res)
    else:
        @wraps(fixture_fun, new_sig=new_sig)
        def _steps_aware_decorated_function(*args, **kwargs):
            request = kwargs['request'] if func_needs_request else kwargs.pop('request')
            _check_scope(request)
            gen = fixture_fun(*args, **kwargs)
github smarie / python-pytest-cases / pytest_cases / main_fixtures.py View on Github external
# note: the function automatically registers it in the module
            # note 2: idstyle is set to None because we provide an explicit enough list of ids
            big_param_fixture = _fixture_union(caller_module, fixture_union_name, fixtures_to_union, idstyle=None,
                                               ids=fixtures_to_union_names_for_ids, hook=hook)

            # --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)
            for _first_idx, _n in enumerate(old_sig.parameters):
                if _n in all_param_names:
                    break
            # then remove all parameters that will be replaced by the new fixture
            new_sig = remove_signature_parameters(old_sig, *all_param_names)
            # 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))

            # --Finally create the fixture function, a wrapper of user-provided fixture with the new signature
            def replace_paramfixture_with_values(kwargs):
                # 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(all_param_names):
                        kwargs[p] = encompassing_fixture[i]
                else:
                    kwargs[all_param_names[0]] = encompassing_fixture
                # return
                return kwargs

            if not isgeneratorfunction(test_func):
github smarie / python-pytest-steps / pytest_steps / steps_generator.py View on Github external
# Transform the steps into ids if needed
        step_ids = [create_pytest_param_str_id(f) for f in steps]

        # Create the container that will hold all execution monitors for this function
        # TODO maybe have later a single 'monitor' instance at plugin level... like in pytest-benchmark
        all_monitors = StepMonitorsContainer(test_func, step_ids)

        # Create the function wrapper.
        # We will expose a new signature with additional 'request' arguments if needed, and the test step
        orig_sig = signature(test_func)
        func_needs_request = 'request' in orig_sig.parameters
        additional_params = (Parameter(test_step_argname, kind=Parameter.POSITIONAL_OR_KEYWORD), ) \
                            + ((Parameter('request', kind=Parameter.POSITIONAL_OR_KEYWORD), )
                               if not func_needs_request else ())
        # add request parameter last, as first may be 'self'
        new_sig = add_signature_parameters(orig_sig, last=additional_params)

        # -- first create the logic
        @wraps(test_func, new_sig=new_sig)
        def wrapped_test_function(*args, **kwargs):
            step_name = kwargs.pop(test_step_argname)
            request = kwargs['request'] if func_needs_request else kwargs.pop('request')
            if request is None:
                # we are manually called outside of pytest. let's execute all steps at nce
                if step_name is None:
                    # print("@test_steps - decorated function '%s' is being called manually. The `%s` parameter is set "
                    #       "to None so all steps will be executed in order" % (f, test_step_argname))
                    step_names = step_ids
                else:
                    # print("@test_steps - decorated function '%s' is being called manually. The `%s` parameter is set "
                    #       "to %s so only these steps will be executed in order. Note that the order should be feasible"
                    #       "" % (f, test_step_argname, step_name))
github smarie / python-pytest-cases / pytest_cases / main_fixtures.py View on Github external
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 l in params_names_or_name_combinations for v in l)

    # --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 _get_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]] = fixture_param_value
            else:
                # several parameters for that generated fixture (@pytest.mark.parametrize with several names)
github smarie / python-pytest-steps / pytest_steps / steps.py View on Github external
Implementation of the @cross_steps_fixture decorator, for manual decoration

    :param fixture_fun:
    :param step_param_names: a singleton or iterable containing the names of the test step parameters used in the
        tests. By default the list is `[GENERATOR_MODE_STEP_ARGNAME, TEST_STEP_ARGNAME_DEFAULT]` to cover both
        generator-mode and legacy manual mode.
    :return:
    """
    ref_dct = dict()

    # Create the function wrapper.
    # We will expose a new signature with additional 'request' arguments if needed, and the test step
    orig_sig = signature(fixture_fun)
    func_needs_request = 'request' in orig_sig.parameters
    if not func_needs_request:
        new_sig = add_signature_parameters(orig_sig, first=Parameter('request', kind=Parameter.POSITIONAL_OR_KEYWORD))
    else:
        new_sig = orig_sig

    def _init_and_check(request):
        """
        Checks that the current request is not session but a specific node.
        :param request:
        :return:
        """
        scope = get_scope(request)
        if scope == 'function':
            # function-scope: ok
            id_without_steps = get_pytest_node_hash_id(request.node,
                                                       params_to_ignore=_get_step_param_names_or_default(
                                                       step_param_names))
            return id_without_steps
github smarie / python-pytest-cases / pytest_cases / fixture_core2.py View on Github external
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)
github smarie / python-pytest-cases / pytest_cases / fixture_parametrize_plus.py View on Github external
_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
github smarie / python-decopatch / decopatch / main.py View on Github external
modulename=function_for_metadata.__module__)
        def new_decorator(*no_args, **kwargs):
            """
            Code for your decorator, generated by decopatch to handle the case when it is called without parenthesis
            """
            # this is a parenthesis call, because otherwise a `TypeError` would already have been raised by python.
            return with_parenthesis_usage(decorator_function, *no_args, **kwargs)

        return new_decorator
    elif sig_info.use_signature_trick:
        # no need to modify the signature, we will expose *args, **kwargs
        pass
    else:
        # modify the signature to add a var-positional first
        gen_varpos_param = Parameter(_GENERATED_VARPOS_NAME, kind=Parameter.VAR_POSITIONAL)
        sig_info.exposed_signature = add_signature_parameters(sig_info.exposed_signature, first=[gen_varpos_param])

    # we can fallback to the same case than varpositional
    return create_general_case_decorator(sig_info, decorator_function, disambiguator,
                                         function_for_metadata=function_for_metadata)