Python funcsigs.Parameter() Examples

The following are 20 code examples of funcsigs.Parameter(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module funcsigs , or try the search function .
Example #1
Source File: reflection.py    From oslo.utils with Apache License 2.0 6 votes vote down vote up
def get_callable_args(function, required_only=False):
    """Get names of callable arguments.

    Special arguments (like ``*args`` and ``**kwargs``) are not included into
    output.

    If required_only is True, optional arguments (with default values)
    are not included into output.
    """
    sig = get_signature(function)
    function_args = list(six.iterkeys(sig.parameters))
    for param_name, p in six.iteritems(sig.parameters):
        if (p.kind in (Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD) or
                (required_only and p.default is not Parameter.empty)):
            function_args.remove(param_name)
    return function_args 
Example #2
Source File: fit.py    From symfit with GNU General Public License v2.0 6 votes vote down vote up
def _make_parameters(model, none_allowed=None):
        """
        Based on a model, return the inspect.Parameter objects
        needed to satisfy all the variables of this model.

        :param model: instance of model
        :param none_allowed: If provided, this has to be a sequence of
            :class:`symfit.core.argument.Variable` whose values are set to
            ``None`` by default. If not provided, this will be set to sigma
            variables only.
        :return: list of  :class:`inspect.Parameter` corresponding to all the
            external variables of the model.
        """
        if none_allowed is None:
            none_allowed = model.sigmas.values()
        parameters = [
            inspect_sig.Parameter(
                var.name,
                kind=inspect_sig.Parameter.POSITIONAL_OR_KEYWORD,
                default=None if var in none_allowed else inspect_sig.Parameter.empty
            )
            for var in model.vars
        ]
        return parameters 
Example #3
Source File: models.py    From symfit with GNU General Public License v2.0 6 votes vote down vote up
def vars_as_functions(self):
        """
        :return: Turn the keys of this model into
            :class:`~sympy.core.function.Function`
            objects. This is done recursively so the chain rule can be applied
            correctly. This is done on the basis of `connectivity_mapping`.

            Example: for ``{y: a * x, z: y**2 + a}`` this returns
            ``{y: y(x, a), z: z(y(x, a), a)}``.
        """
        vars2functions = {}
        key = lambda arg: [isinstance(arg, Parameter), str(arg)]
        # Iterate over all symbols in this model in topological order, turning
        # each one into a function object recursively.
        for symbol in self.ordered_symbols:
            if symbol in self.connectivity_mapping:
                dependencies = self.connectivity_mapping[symbol]
                # Replace the dependency by it's function if possible
                dependencies = [vars2functions.get(dependency, dependency)
                               for dependency in dependencies]
                # sort by vars first, then params, and alphabetically within
                # each group
                dependencies = sorted(dependencies, key=key)
                vars2functions[symbol] = sympy.Function(symbol.name)(*dependencies)
        return vars2functions 
Example #4
Source File: models.py    From symfit with GNU General Public License v2.0 6 votes vote down vote up
def __str__(self):
        """
        Printable representation of a Mapping model.

        :return: str
        """
        template = "{}({}; {}) = {}"
        parts = []
        for var, expr in self.items():
            # Print every component as a function of only the dependencies it
            # has. We can deduce these from the connectivity mapping.
            params_sorted = sorted((x for x in self.connectivity_mapping[var]
                                    if isinstance(x, Parameter)),
                                   key=lambda x: x.name)
            vars_sorted = sorted((x for x in self.connectivity_mapping[var]
                                  if x not in params_sorted),
                                 key=lambda x: x.name)
            parts.append(template.format(
                    var,
                    ', '.join([x.name for x in vars_sorted]),
                    ', '.join([x.name for x in params_sorted]),
                    expr
                )
            )
        return '[{}]'.format(",\n ".join(parts)) 
Example #5
Source File: models.py    From symfit with GNU General Public License v2.0 6 votes vote down vote up
def numerical_components(self):
        """
        :return: lambda functions of each of the analytical components in
            model_dict, to be used in numerical calculation.
        """
        # All components must feature the independent vars and params, that's
        # the API convention. But for those components which also contain
        # interdependence, we add those vars
        components = []
        for var, expr in self.items():
            dependencies = self.connectivity_mapping[var]
            # vars first, then params, and alphabetically within each group
            key = lambda arg: [isinstance(arg, Parameter), str(arg)]
            ordered = sorted(dependencies, key=key)
            components.append(sympy_to_py(expr, ordered))
        return ModelOutput(self.keys(), components) 
Example #6
Source File: models.py    From symfit with GNU General Public License v2.0 6 votes vote down vote up
def jacobian(self):
        """
        :return: Jacobian filled with the symbolic expressions for all the
            partial derivatives. Partial derivatives are of the components of
            the function with respect to the Parameter's, not the independent
            Variable's. The return shape is a list over the models components,
            filled with tha symbolical jacobian for that component, as a list.
        """
        jac = []
        for var, expr in self.items():
            jac_row = []
            for param in self.params:
                partial_dv = D(var, param)
                jac_row.append(self.jacobian_model[partial_dv])
            jac.append(jac_row)
        return jac 
Example #7
Source File: models.py    From symfit with GNU General Public License v2.0 5 votes vote down vote up
def hessian(self):
        """
        :return: Hessian filled with the symbolic expressions for all the
            second order partial derivatives. Partial derivatives are taken with
            respect to the Parameter's, not the independent Variable's.
        """
        return [[[sympy.diff(partial_dv, param) for param in self.params]
                 for partial_dv in comp] for comp in self.jacobian] 
Example #8
Source File: reflection.py    From oslo.utils with Apache License 2.0 5 votes vote down vote up
def accepts_kwargs(function):
    """Returns ``True`` if function accepts kwargs otherwise ``False``."""
    sig = get_signature(function)
    return any(p.kind == Parameter.VAR_KEYWORD
               for p in six.itervalues(sig.parameters)) 
Example #9
Source File: minimizers.py    From symfit with GNU General Public License v2.0 5 votes vote down vote up
def __init__(self, objective, parameters):
        """
        :param objective: Objective function to be used.
        :param parameters: List of :class:`~symfit.core.argument.Parameter` instances
        """
        self.parameters = parameters
        self._fixed_params = [p for p in parameters if p.fixed]
        self.objective = self._baseobjective_from_callable(objective)

        # Mapping which we use to track the original, to be used upon pickling
        self._pickle_kwargs = {'parameters': parameters, 'objective': objective}
        self.params = [p for p in parameters if not p.fixed] 
Example #10
Source File: support.py    From symfit with GNU General Public License v2.0 5 votes vote down vote up
def __init__(self, **kwonly_arguments):
        self.kwonly_arguments = kwonly_arguments
        # Mark which are required
        self.required_keywords = {
            kw for kw, value in kwonly_arguments.items() if value is RequiredKeyword
        }
        # Transform all into keywordonly inspect.Parameter objects.
        self.keywordonly_parameters = OrderedDict(
            (kw, inspect_sig.Parameter(kw,
                                       kind=inspect_sig.Parameter.KEYWORD_ONLY,
                                       default=value)
             )
            for kw, value in kwonly_arguments.items()
        ) 
Example #11
Source File: support.py    From symfit with GNU General Public License v2.0 5 votes vote down vote up
def seperate_symbols(func):
    """
    Seperate the symbols in symbolic function func. Return them in alphabetical
    order.

    :param func: scipy symbolic function.
    :return: (vars, params), a tuple of all variables and parameters, each 
        sorted in alphabetical order.
    :raises TypeError: only symfit Variable and Parameter are allowed, not sympy
        Symbols.
    """
    params = []
    vars = []
    for symbol in func.free_symbols:
        if not isidentifier(str(symbol)):
            continue  # E.g. Indexed objects might print to A[i, j]
        if isinstance(symbol, Parameter):
            params.append(symbol)
        elif isinstance(symbol, Idx):
            # Idx objects are not seen as parameters or vars.
            pass
        elif isinstance(symbol, (MatrixExpr, Expr)):
            vars.append(symbol)
        else:
            raise TypeError('model contains an unknown symbol type, {}'.format(type(symbol)))

    for der in func.atoms(sympy.Derivative):
        # Used by jacobians and hessians, where derivatives are treated as
        # Variables. This way of writing it is purposefully discriminatory
        # against derivatives wrt variables, since such derivatives should be
        # performed explicitly in the case of jacs/hess, and are treated
        # differently in the case of ODEModels.
        if der.expr in vars and all(isinstance(s, Parameter) for s in der.variables):
            vars.append(der)

    params.sort(key=lambda symbol: symbol.name)
    vars.sort(key=lambda symbol: symbol.name)
    return vars, params 
Example #12
Source File: utils.py    From trax with Apache License 2.0 5 votes vote down vote up
def _np_signature(f):
  """An enhanced funcsigs.signature that can handle numpy.ufunc."""
  if not isinstance(f, np.ufunc):
    return funcsigs.signature(f)
  def names_from_num(prefix, n):
    if n <= 0:
      return []
    elif n == 1:
      return [prefix]
    else:
      return [prefix + str(i + 1) for i in range(n)]
  input_names = names_from_num('x', f.nin)
  output_names = names_from_num('out', f.nout)
  keyword_only_params = [
      ('where', True),
      ('casting', 'same_kind'),
      ('order', 'K'),
      ('dtype', None),
      ('subok', True),
      ('signature', None),
      ('extobj', None)]
  params = []
  params += [funcsigs.Parameter(name, funcsigs.Parameter.POSITIONAL_ONLY)
             for name in input_names]
  if f.nout > 1:
    params += [funcsigs.Parameter(name, funcsigs.Parameter.POSITIONAL_ONLY,
                                  default=None)
               for name in output_names]
  params += [funcsigs.Parameter(
      'out', funcsigs.Parameter.POSITIONAL_OR_KEYWORD,
      default=None if f.nout == 1 else (None,) * f.nout)]
  params += [funcsigs.Parameter(name, funcsigs.Parameter.KEYWORD_ONLY,
                                default=default)
             for name, default in keyword_only_params]
  return funcsigs.Signature(params)


# Python 2 doesn't allow keyword-only argument. Python prior to 3.8 doesn't
# allow positional-only argument. So we conflate positional-only, keyword-only
# and positional-or-keyword arguments here. 
Example #13
Source File: models.py    From symfit with GNU General Public License v2.0 5 votes vote down vote up
def _init_from_dict(self, model_dict):
        """
        Initiate self from a model_dict to make sure attributes such as vars, params are available.

        Creates lists of alphabetically sorted independent vars, dependent vars, sigma vars, and parameters.
        Finally it creates a signature for this model so it can be called nicely. This signature only contains
        independent vars and params, as one would expect.

        :param model_dict: dict of (dependent_var, expression) pairs.
        """
        sort_func = lambda symbol: symbol.name
        self.model_dict = OrderedDict(sorted(model_dict.items(),
                                             key=lambda i: sort_func(i[0])))
        # Everything at the bottom of the toposort is independent, at the top
        # dependent, and the rest interdependent.
        ordered = list(toposort(self.connectivity_mapping))
        independent = sorted(ordered.pop(0), key=sort_func)
        self.dependent_vars = sorted(ordered.pop(-1), key=sort_func)
        self.interdependent_vars = sorted(
            [item for items in ordered for item in items],
            key=sort_func
        )
        # `independent` contains both params and vars, needs to be separated
        self.independent_vars = [s for s in independent if
                                 not isinstance(s, Parameter) and not s in self]
        self.params = [s for s in independent if isinstance(s, Parameter)]

        try:
            assert not any(isinstance(var, Parameter)
                           for var in self.dependent_vars)
            assert not any(isinstance(var, Parameter)
                           for var in self.interdependent_vars)
        except AssertionError:
            raise ModelError('`Parameter`\'s can not feature in the role '
                             'of `Variable`')
        # Make Variable object corresponding to each depedent var.
        self.sigmas = {var: Variable(name='sigma_{}'.format(var.name))
                       for var in self.dependent_vars} 
Example #14
Source File: keywordonly.py    From symfit with GNU General Public License v2.0 5 votes vote down vote up
def __init__(self, **kwonly_arguments):
        self.kwonly_arguments = kwonly_arguments
        # Mark which are required
        self.required_keywords = {
            kw for kw, value in kwonly_arguments.items() if value is RequiredKeyword
        }
        # Transform all into keywordonly inspect.Parameter objects.
        self.keywordonly_parameters = OrderedDict(
            (kw, inspect_sig.Parameter(kw,
                                       kind=inspect_sig.Parameter.KEYWORD_ONLY,
                                       default=value)
             )
            for kw, value in kwonly_arguments.items()
        ) 
Example #15
Source File: method.py    From molecular-design-toolkit with Apache License 2.0 5 votes vote down vote up
def __signature__(self):
        if hasattr(self, '__customsig'):
            return self.__customsig

        kwargs = []
        for param in self.PARAMETERS:
            kwargs.append(funcsigs.Parameter(param.name,
                                             default=param.default,
                                             kind=funcsigs.Parameter.POSITIONAL_OR_KEYWORD))

        self.__customsig = funcsigs.Signature(kwargs, __validate_parameters__=True)
        return self.__customsig 
Example #16
Source File: utils.py    From trax with Apache License 2.0 5 votes vote down vote up
def _is_compatible_param_kind(a, b):
  def relax(k):
    if k in (funcsigs.Parameter.POSITIONAL_ONLY,
             funcsigs.Parameter.KEYWORD_ONLY):
      return funcsigs.Parameter.POSITIONAL_OR_KEYWORD
    return k
  return relax(a) == relax(b) 
Example #17
Source File: support.py    From symfit with GNU General Public License v2.0 4 votes vote down vote up
def sympy_to_py(func, args):
    """
    Turn a symbolic expression into a Python lambda function,
    which has the names of the variables and parameters as it's argument names.

    :param func: sympy expression
    :param args: variables and parameters in this model
    :return: lambda function to be used for numerical evaluation of the model.
    """
    # replace the derivatives with printable variables.
    derivatives = {var: Variable(var.name) for var in args
                   if isinstance(var, sympy.Derivative)}
    func = func.xreplace(derivatives)
    args = [derivatives[var] if isinstance(var, sympy.Derivative) else var
            for var in args]
    lambdafunc = lambdify(args, func, dummify=False)
    # Check if the names of the lambda function are what we expect
    signature = inspect_sig.signature(lambdafunc)
    sig_parameters = OrderedDict(signature.parameters)
    for arg, lambda_arg in zip(args, sig_parameters):
        if arg.name != lambda_arg:
            break
    else:  # Lambdifying succesful!
        return lambdafunc

    # If we are here (very rare), then one of the lambda arg is still a Dummy.
    # In this case we will manually handle the naming.
    lambda_names = sig_parameters.keys()
    arg_names = [arg.name for arg in args]
    conversion = dict(zip(arg_names, lambda_names))

    # Wrap the lambda such that arg names are translated into the correct dummy
    # symbol names
    @wraps(lambdafunc)
    def wrapped_lambdafunc(*ordered_args, **kwargs):
        converted_kwargs = {conversion[k]: v for k, v in kwargs.items()}
        return lambdafunc(*ordered_args, **converted_kwargs)

    # Update the signature of wrapped_lambdafunc to math our args
    new_sig_parameters = OrderedDict()
    for arg_name, dummy_name in conversion.items():
        if arg_name == dummy_name:  # Already has the correct name
            new_sig_parameters[arg_name] = sig_parameters[arg_name]
        else:  # Change the dummy inspect.Parameter to the correct name
            param = sig_parameters[dummy_name]
            param = param.replace(name=arg_name)
            new_sig_parameters[arg_name] = param

    wrapped_lambdafunc.__signature__ = signature.replace(
        parameters=new_sig_parameters.values()
    )
    return wrapped_lambdafunc 
Example #18
Source File: support.py    From symfit with GNU General Public License v2.0 4 votes vote down vote up
def __call__(self, func):
        """
        Returns a decorated version of `func`, who's signature now includes the
        keyword-only arguments.

        :param func: the function to be decorated
        :return: the decorated function
        """
        sig = inspect_sig.signature(func)
        params = []
        # A var keyword has to be found for this function to be decorated
        for name, param in sig.parameters.items():
            if param.kind == param.VAR_KEYWORD:
                # Keyword only's go before the **kwargs parameter.
                params.extend(self.keywordonly_parameters.values())
                params.append(param)
                break
            params.append(param)
        else:
            raise RequiredKeywordError(
                'The keywordonly decorator requires the function to '
                'accept a **kwargs argument.'
            )
        # Update signature
        sig = sig.replace(parameters=params)
        func.__signature__ = sig

        @wraps(func)
        def wrapped_func(*args, **kwargs):
            """
            :param args: args used to call the function
            :param kwargs: kwargs used to call the function
            :return: Wrapped function which behaves like it has keyword-only arguments.
            :raises: ``RequiredKeywordError`` if not all required keywords were specified.
            """
            bound_args = func.__signature__.bind(*args, **kwargs)
            # Apply defaults
            for param in sig.parameters.values():
                if param.name not in bound_args.arguments:
                    if param.default is RequiredKeyword:
                        raise RequiredKeywordError(
                            'Keyword `{}` is a required keyword. '
                            'Please provide a value.'.format(param.name)
                        )
                    elif param.kind == inspect_sig.Parameter.VAR_KEYWORD:
                        bound_args.arguments[param.name] = {}
                    elif param.kind == inspect_sig.Parameter.VAR_POSITIONAL:
                        bound_args.arguments[param.name] = tuple()
                    else:
                        bound_args.arguments[param.name] = param.default
            return func(*bound_args.args, **bound_args.kwargs)
        return wrapped_func 
Example #19
Source File: operators.py    From symfit with GNU General Public License v2.0 4 votes vote down vote up
def call(self, *values, **named_values):
    """
    Call an expression to evaluate it at the given point.

    Future improvements: I would like if func and signature could be buffered after the
    first call so they don't have to be recalculated for every call. However, nothing
    can be stored on self as sympy uses __slots__ for efficiency. This means there is no
    instance dict to put stuff in! And I'm pretty sure it's ill advised to hack into the
    __slots__ of Expr.

    However, for the moment I don't really notice a performance penalty in running tests.

    p.s. In the current setup signature is not even needed since no introspection is possible
    on the Expr before calling it anyway, which makes calculating the signature absolutely useless.
    However, I hope that someday some monkey patching expert in shining armour comes by and finds
    a way to store it in __signature__ upon __init__ of any ``symfit`` expr such that calling
    inspect_sig.signature on a symbolic expression will tell you which arguments to provide.

    :param self: Any subclass of sympy.Expr
    :param values: Values for the Parameters and Variables of the Expr.
    :param named_values: Values for the vars and params by name. ``named_values`` is
        allowed to contain too many values, as this sometimes happens when using
        \*\*fit_result.params on a submodel. The irrelevant params are simply ignored.
    :return: The function evaluated at ``values``. The type depends entirely on the input.
        Typically an array or a float but nothing is enforced.
    """
    independent_vars, params = seperate_symbols(self)
    # Convert to a pythonic function
    func = sympy_to_py(self, independent_vars + params)

    # Handle args and kwargs according to the allowed names.
    parameters = [  # Note that these are inspect_sig.Parameter's, not symfit parameters!
        inspect_sig.Parameter(arg.name, inspect_sig.Parameter.POSITIONAL_OR_KEYWORD)
            for arg in independent_vars + params
    ]

    arg_names = [arg.name for arg in independent_vars + params]
    relevant_named_values = {
        name: value for name, value in named_values.items() if name in arg_names
    }

    signature = inspect_sig.Signature(parameters=parameters)
    bound_arguments = signature.bind(*values, **relevant_named_values)

    return func(**bound_arguments.arguments)


# # Expr.__eq__ = eq
# # Expr.__ne__ = ne 
Example #20
Source File: keywordonly.py    From symfit with GNU General Public License v2.0 4 votes vote down vote up
def __call__(self, func):
        """
        Returns a decorated version of `func`, who's signature now includes the
        keyword-only arguments.

        :param func: the function to be decorated
        :return: the decorated function
        """
        sig = inspect_sig.signature(func)
        params = []
        # A var keyword has to be found for this function to be decorated
        for name, param in sig.parameters.items():
            if param.kind == param.VAR_KEYWORD:
                # Keyword only's go before the **kwargs parameter.
                params.extend(self.keywordonly_parameters.values())
                params.append(param)
                break
            params.append(param)
        else:
            raise RequiredKeywordError(
                'The keywordonly decorator requires the function to '
                'accept a **kwargs argument.'
            )
        # Update signature
        sig = sig.replace(parameters=params)
        func.__signature__ = sig

        @wraps(func)
        def wrapped_func(*args, **kwargs):
            """
            :param args: args used to call the function
            :param kwargs: kwargs used to call the function
            :return: Wrapped function which behaves like it has keyword-only arguments.
            :raises: ``RequiredKeywordError`` if not all required keywords were specified.
            """
            bound_args = func.__signature__.bind(*args, **kwargs)
            # Apply defaults
            for param in sig.parameters.values():
                if param.name not in bound_args.arguments:
                    if param.default is RequiredKeyword:
                        raise RequiredKeywordError(
                            'Keyword `{}` is a required keyword. '
                            'Please provide a value.'.format(param.name)
                        )
                    elif param.kind == inspect_sig.Parameter.VAR_KEYWORD:
                        bound_args.arguments[param.name] = {}
                    elif param.kind == inspect_sig.Parameter.VAR_POSITIONAL:
                        bound_args.arguments[param.name] = tuple()
                    else:
                        bound_args.arguments[param.name] = param.default
            return func(*bound_args.args, **bound_args.kwargs)
        return wrapped_func