Python inspect.Parameter.POSITIONAL_OR_KEYWORD Examples

The following are 23 code examples of inspect.Parameter.POSITIONAL_OR_KEYWORD(). 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 inspect.Parameter , or try the search function .
Example #1
Source File: compat.py    From easy_cache with MIT License 6 votes vote down vote up
def getargspec(func):
        signature = inspect.signature(func)

        args = []
        varargs = None
        keywords = None
        defaults = []

        for param in signature.parameters.values():  # type: Parameter
            if param.kind == Parameter.VAR_POSITIONAL:
                varargs = param.name
            elif param.kind in (
                    Parameter.POSITIONAL_ONLY,
                    Parameter.KEYWORD_ONLY,
                    Parameter.POSITIONAL_OR_KEYWORD):
                args.append(param.name)
            elif param.kind == Parameter.VAR_KEYWORD:
                keywords = param.name

            # noinspection PyProtectedMember
            if param.default is not inspect._empty:
                defaults.append(param.default)

        return ArgSpec(args, varargs, keywords, tuple(defaults)) 
Example #2
Source File: interaction.py    From Carnets with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def _yield_abbreviations_for_parameter(param, kwargs):
    """Get an abbreviation for a function parameter."""
    name = param.name
    kind = param.kind
    ann = param.annotation
    default = param.default
    not_found = (name, empty, empty)
    if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY):
        if name in kwargs:
            value = kwargs.pop(name)
        elif ann is not empty:
            warn("Using function annotations to implicitly specify interactive controls is deprecated. Use an explicit keyword argument for the parameter instead.", DeprecationWarning)
            value = ann
        elif default is not empty:
            value = default
        else:
            yield not_found
        yield (name, value, default)
    elif kind == Parameter.VAR_KEYWORD:
        # In this case name=kwargs and we yield the items in kwargs with their keys.
        for k, v in kwargs.copy().items():
            kwargs.pop(k)
            yield k, v, empty 
Example #3
Source File: interaction.py    From pySINDy with MIT License 6 votes vote down vote up
def _yield_abbreviations_for_parameter(param, kwargs):
    """Get an abbreviation for a function parameter."""
    name = param.name
    kind = param.kind
    ann = param.annotation
    default = param.default
    not_found = (name, empty, empty)
    if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY):
        if name in kwargs:
            value = kwargs.pop(name)
        elif ann is not empty:
            warn("Using function annotations to implicitly specify interactive controls is deprecated. Use an explicit keyword argument for the parameter instead.", DeprecationWarning)
            value = ann
        elif default is not empty:
            value = default
        else:
            yield not_found
        yield (name, value, default)
    elif kind == Parameter.VAR_KEYWORD:
        # In this case name=kwargs and we yield the items in kwargs with their keys.
        for k, v in kwargs.copy().items():
            kwargs.pop(k)
            yield k, v, empty 
Example #4
Source File: _resources.py    From civis-python with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def create_signature(args, optional_args):
    """ Dynamically create a signature for a function from strings.

    This function can be used to create a signature for a dynamically
    generated function without generating a string representation of
    the function code and making an explicit eval call.

    Parameters
    ----------
    args : list
        List of strings that name the required arguments of a function.
    optional_args : list
        List of strings that name the optional arguments of a function.

    Returns
    -------
    Signature(p) : inspect.Signature instance
        A Signature object that can be used to validate arguments in
        a dynamically created function.
    """
    p = [Parameter(x, Parameter.POSITIONAL_OR_KEYWORD) for x in args]
    p += [Parameter(x, Parameter.KEYWORD_ONLY, default='DEFAULT')
          for x in optional_args]
    return Signature(p) 
Example #5
Source File: _dynamic.py    From pipelines with Apache License 2.0 5 votes vote down vote up
def __init__(self, name, default=Parameter.empty, annotation=Parameter.empty):
        super().__init__(name, Parameter.POSITIONAL_OR_KEYWORD, default=default, annotation=annotation) 
Example #6
Source File: app.py    From chi with MIT License 5 votes vote down vote up
def parse_args_and_run(self, args=None):
    args = args or sys.argv
    import argparse
    parser = argparse.ArgumentParser(description=self.f.__name__)

    for n, p in self.params.items():
      d = p.default == Parameter.empty
      t = str if d else type(p.default)
      if t is bool:
        g = parser.add_mutually_exclusive_group(required=False)
        g.add_argument('--' + n, dest=n, action='store_true')
        g.add_argument('--no-' + n, dest=n, action='store_false')
        parser.set_defaults(**{n: Parameter.empty})
      elif p.kind == Parameter.POSITIONAL_OR_KEYWORD:
        g = parser.add_mutually_exclusive_group(required=d)
        g.add_argument(n, nargs='?', type=t, default=Parameter.empty)
        g.add_argument('--' + n, dest='--' + n, type=t, default=Parameter.empty, help=argparse.SUPPRESS)
      elif p.kind == Parameter.KEYWORD_ONLY:
        parser.add_argument('--' + n, type=type(p.default), default=p.default)

    ag = vars(parser.parse_args())
    parsed = {}
    for n, p in self.params.items():
      a, b, c = ag[n], ag.get('--' + n, Parameter.empty), p.default
      v = a if a != Parameter.empty else b if b != Parameter.empty else c
      parsed.update({n: v})

    result = self.run(**parsed)

    from chi.logger import logger
    logger.info('Finishing with ' + str(result))

    sys.exit(result) 
Example #7
Source File: interact.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def _yield_abbreviations_for_parameter(parameter, kwargs):
    """Get an abbreviation for a function parameter."""
    name = parameter.name
    kind = parameter.kind
    ann = parameter.annotation
    default = parameter.default
    not_found = (name, empty, empty)
    if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY):
        if name in kwargs:
            value = kwargs.pop(name)
        elif ann is not empty:
            param.main.warning("Using function annotations to implicitly specify interactive controls is deprecated. "
                               "Use an explicit keyword argument for the parameter instead.", DeprecationWarning)
            value = ann
        elif default is not empty:
            value = default
            if isinstance(value, (Iterable, Mapping)):
                value = fixed(value)
        else:
            yield not_found
        yield (name, value, default)
    elif kind == Parameter.VAR_KEYWORD:
        # In this case name=kwargs and we yield the items in kwargs with their keys.
        for k, v in kwargs.copy().items():
            kwargs.pop(k)
            yield k, v, empty 
Example #8
Source File: test_base.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_pane_signature(pane):
    from inspect import Parameter, signature
    parameters = signature(pane).parameters
    assert len(parameters) == 2
    assert 'object' in parameters
    assert parameters['object'] == Parameter('object', Parameter.POSITIONAL_OR_KEYWORD, default=None) 
Example #9
Source File: collections.py    From rlpyt with MIT License 5 votes vote down vote up
def __init__(self, typename, fields):
        if not isinstance(typename, str):
            raise TypeError(f"type name must be string, not {type(typename)}")

        if isinstance(fields, str):
            spaces = any([whitespace in fields for whitespace in string.whitespace])
            commas = "," in fields
            if spaces and commas:
                raise ValueError(f"Single string fields={fields} cannot have both spaces and commas.")
            elif spaces:
                fields = fields.split()
            elif commas:
                fields = fields.split(",")
            else:
                # If there are neither spaces nor commas, then there is only one field.
                fields = (fields,)
        fields = tuple(fields)

        for field in fields:
            if not isinstance(field, str):
                raise ValueError(f"field names must be strings: {field}")
            if field.startswith("_"):
                raise ValueError(f"field names cannot start with an "
                                 f"underscore: {field}")
            if field in ("index", "count"):
                raise ValueError(f"can't name field 'index' or 'count'")
        self.__dict__["_typename"] = typename
        self.__dict__["_fields"] = fields
        self.__dict__["_signature"] = Sig(Param(field,
            Param.POSITIONAL_OR_KEYWORD) for field in fields) 
Example #10
Source File: signature.py    From ray with Apache License 2.0 5 votes vote down vote up
def _convert_to_parameter_kind(value):
    if value == 0:
        return Parameter.POSITIONAL_ONLY
    if value == 1:
        return Parameter.POSITIONAL_OR_KEYWORD
    if value == 2:
        return Parameter.VAR_POSITIONAL
    if value == 3:
        return Parameter.KEYWORD_ONLY
    if value == 4:
        return Parameter.VAR_KEYWORD 
Example #11
Source File: signature.py    From ray with Apache License 2.0 5 votes vote down vote up
def _convert_from_parameter_kind(kind):
    if kind == Parameter.POSITIONAL_ONLY:
        return 0
    if kind == Parameter.POSITIONAL_OR_KEYWORD:
        return 1
    if kind == Parameter.VAR_POSITIONAL:
        return 2
    if kind == Parameter.KEYWORD_ONLY:
        return 3
    if kind == Parameter.VAR_KEYWORD:
        return 4 
Example #12
Source File: commandextras.py    From DueUtil with GNU General Public License v3.0 5 votes vote down vote up
def dict_command(**spec):

    def wrap(command_func):

        expected = expand_spec(spec.get("expected", {}))
        optional = expand_spec(spec.get("optional", {}))

        @wraps(command_func)
        async def wrapped_command(ctx, *args, **details):
            # Find the last positional. That is where the dict_args will be passed.
            args_spec = inspect.signature(command_func)
            params = list(args_spec.parameters.values())
            args_dict_param = next((param for param in reversed(params)
                                    if param.kind is Parameter.POSITIONAL_OR_KEYWORD))

            # Get all args after and including the position of the arg for the dict_args
            # Those will be processed into a dict.
            arg_dict_index = params.index(args_dict_param) - 1  # -1 to ignore ctx arg
            dict_args = determine_dict_args(list(args[arg_dict_index:]), wrapped_command, ctx,
                                            expected=expected, optional=optional)

            if dict_args is False:
                # Invalid
                await util.get_client(ctx.server.id).add_reaction(ctx, emojis.QUESTION_REACT)
            else:
                # Run command.
                kwargs = details
                kwargs[args_dict_param.name] = dict_args
                await command_func(ctx, *args[:arg_dict_index], **kwargs)

        return wrapped_command

    return wrap 
Example #13
Source File: compat.py    From pytest with MIT License 5 votes vote down vote up
def get_default_arg_names(function: Callable[..., Any]) -> Tuple[str, ...]:
    # Note: this code intentionally mirrors the code at the beginning of getfuncargnames,
    # to get the arguments which were excluded from its result because they had default values
    return tuple(
        p.name
        for p in signature(function).parameters.values()
        if p.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY)
        and p.default is not Parameter.empty
    ) 
Example #14
Source File: signature.py    From mockito-python with MIT License 5 votes vote down vote up
def positional_arguments(sig):
    return len([p for n, p in sig.parameters.items()
                if p.kind in (Parameter.POSITIONAL_ONLY,
                              Parameter.POSITIONAL_OR_KEYWORD)]) 
Example #15
Source File: compat.py    From python-netsurv with MIT License 5 votes vote down vote up
def get_default_arg_names(function):
    # Note: this code intentionally mirrors the code at the beginning of getfuncargnames,
    # to get the arguments which were excluded from its result because they had default values
    return tuple(
        p.name
        for p in signature(function).parameters.values()
        if p.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY)
        and p.default is not Parameter.empty
    ) 
Example #16
Source File: compat.py    From python-netsurv with MIT License 5 votes vote down vote up
def get_default_arg_names(function):
    # Note: this code intentionally mirrors the code at the beginning of getfuncargnames,
    # to get the arguments which were excluded from its result because they had default values
    return tuple(
        p.name
        for p in signature(function).parameters.values()
        if p.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY)
        and p.default is not Parameter.empty
    ) 
Example #17
Source File: compat.py    From python-netsurv with MIT License 4 votes vote down vote up
def getfuncargnames(function, is_method=False, cls=None):
    """Returns the names of a function's mandatory arguments.

    This should return the names of all function arguments that:
        * Aren't bound to an instance or type as in instance or class methods.
        * Don't have default values.
        * Aren't bound with functools.partial.
        * Aren't replaced with mocks.

    The is_method and cls arguments indicate that the function should
    be treated as a bound method even though it's not unless, only in
    the case of cls, the function is a static method.

    @RonnyPfannschmidt: This function should be refactored when we
    revisit fixtures. The fixture mechanism should ask the node for
    the fixture names, and not try to obtain directly from the
    function object well after collection has occurred.

    """
    # The parameters attribute of a Signature object contains an
    # ordered mapping of parameter names to Parameter instances.  This
    # creates a tuple of the names of the parameters that don't have
    # defaults.
    try:
        parameters = signature(function).parameters
    except (ValueError, TypeError) as e:
        fail(
            "Could not determine arguments of {!r}: {}".format(function, e),
            pytrace=False,
        )

    arg_names = tuple(
        p.name
        for p in parameters.values()
        if (
            p.kind is Parameter.POSITIONAL_OR_KEYWORD
            or p.kind is Parameter.KEYWORD_ONLY
        )
        and p.default is Parameter.empty
    )
    # If this function should be treated as a bound method even though
    # it's passed as an unbound method or function, remove the first
    # parameter name.
    if is_method or (
        cls and not isinstance(cls.__dict__.get(function.__name__, None), staticmethod)
    ):
        arg_names = arg_names[1:]
    # Remove any names that will be replaced with mocks.
    if hasattr(function, "__wrapped__"):
        arg_names = arg_names[num_mock_patch_args(function) :]
    return arg_names 
Example #18
Source File: registration.py    From pydbus with GNU Lesser General Public License v2.1 4 votes vote down vote up
def call_method(self, connection, sender, object_path, interface_name, method_name, parameters, invocation):
		try:
			try:
				outargs = self.outargs[interface_name + "." + method_name]
				method = getattr(self.object, method_name)
			except KeyError:
				if interface_name == "org.freedesktop.DBus.Properties":
					if method_name == "Get":
						method = self.Get
						outargs = ["v"]
					elif method_name == "GetAll":
						method = self.GetAll
						outargs = ["a{sv}"]
					elif method_name == "Set":
						method = self.Set
						outargs = []
					else:
						raise
				else:
					raise

			sig = signature(method)

			kwargs = {}
			if "dbus_context" in sig.parameters and sig.parameters["dbus_context"].kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY):
				kwargs["dbus_context"] = MethodCallContext(invocation)

			result = method(*parameters, **kwargs)

			if len(outargs) == 0:
				invocation.return_value(None)
			elif len(outargs) == 1:
				invocation.return_value(GLib.Variant("(" + "".join(outargs) + ")", (result,)))
			else:
				invocation.return_value(GLib.Variant("(" + "".join(outargs) + ")", result))

		except Exception as e:
			logger = logging.getLogger(__name__)
			logger.exception("Exception while handling %s.%s()", interface_name, method_name)

			#TODO Think of a better way to translate Python exception types to DBus error types.
			e_type = type(e).__name__
			if not "." in e_type:
				e_type = "unknown." + e_type
			invocation.return_dbus_error(e_type, str(e)) 
Example #19
Source File: compat.py    From pytest with MIT License 4 votes vote down vote up
def getfuncargnames(
    function: Callable[..., Any],
    *,
    name: str = "",
    is_method: bool = False,
    cls: Optional[type] = None
) -> Tuple[str, ...]:
    """Returns the names of a function's mandatory arguments.

    This should return the names of all function arguments that:
        * Aren't bound to an instance or type as in instance or class methods.
        * Don't have default values.
        * Aren't bound with functools.partial.
        * Aren't replaced with mocks.

    The is_method and cls arguments indicate that the function should
    be treated as a bound method even though it's not unless, only in
    the case of cls, the function is a static method.

    The name parameter should be the original name in which the function was collected.
    """
    # TODO(RonnyPfannschmidt): This function should be refactored when we
    # revisit fixtures. The fixture mechanism should ask the node for
    # the fixture names, and not try to obtain directly from the
    # function object well after collection has occurred.

    # The parameters attribute of a Signature object contains an
    # ordered mapping of parameter names to Parameter instances.  This
    # creates a tuple of the names of the parameters that don't have
    # defaults.
    try:
        parameters = signature(function).parameters
    except (ValueError, TypeError) as e:
        fail(
            "Could not determine arguments of {!r}: {}".format(function, e),
            pytrace=False,
        )

    arg_names = tuple(
        p.name
        for p in parameters.values()
        if (
            p.kind is Parameter.POSITIONAL_OR_KEYWORD
            or p.kind is Parameter.KEYWORD_ONLY
        )
        and p.default is Parameter.empty
    )
    if not name:
        name = function.__name__

    # If this function should be treated as a bound method even though
    # it's passed as an unbound method or function, remove the first
    # parameter name.
    if is_method or (
        cls and not isinstance(cls.__dict__.get(name, None), staticmethod)
    ):
        arg_names = arg_names[1:]
    # Remove any names that will be replaced with mocks.
    if hasattr(function, "__wrapped__"):
        arg_names = arg_names[num_mock_patch_args(function) :]
    return arg_names 
Example #20
Source File: __init__.py    From holoviews with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def _create_builder(cls, element, completions):
        def builder(cls, spec=None, **kws):
            spec = element if spec is None else '%s.%s' % (element, spec)
            prefix = 'In opts.{element}(...), '.format(element=element)
            backend = kws.get('backend', None)
            keys = set(kws.keys())
            if backend:
                allowed_kws = cls._element_keywords(backend,
                                                    elements=[element])[element]
                invalid = keys - set(allowed_kws)
            else:
                mismatched = {}
                all_valid_kws =  set()
                for loaded_backend in Store.loaded_backends():
                    valid = set(cls._element_keywords(loaded_backend).get(element, []))
                    all_valid_kws |= set(valid)
                    if keys <= valid: # Found a backend for which all keys are valid
                        return Options(spec, **kws)
                    mismatched[loaded_backend] = list(keys - valid)

                invalid =  keys - all_valid_kws # Keys not found for any backend
                if mismatched and not invalid:  # Keys found across multiple backends
                    msg = ('{prefix} keywords supplied are mixed across backends. '
                           'Keyword(s) {info}')
                    info = ', '.join('%s are invalid for %s'
                                     % (', '.join(repr(el) for el in v), k)
                                     for k,v in mismatched.items())
                    raise ValueError(msg.format(info=info, prefix=prefix))
                allowed_kws = completions

            reraise = False
            if invalid:
                try:
                    cls._options_error(list(invalid)[0], element, backend, allowed_kws)
                except ValueError as e:
                    msg = str(e)[0].lower() + str(e)[1:]
                    reraise = True

                if reraise:
                    raise ValueError(prefix + msg)

            return Options(spec, **kws)

        filtered_keywords = [k for k in completions if k not in cls._no_completion]
        sorted_kw_set = sorted(set(filtered_keywords))
        if sys.version_info.major == 2:
            kws = ', '.join('{opt}=None'.format(opt=opt) for opt in sorted_kw_set)
            builder.__doc__ = '{element}({kws})'.format(element=element, kws=kws)
        else:
            from inspect import Parameter, Signature
            signature = Signature([Parameter('spec', Parameter.POSITIONAL_OR_KEYWORD)]
                                  + [Parameter(kw, Parameter.KEYWORD_ONLY)
                                     for kw in sorted_kw_set])
            builder.__signature__ = signature
        return classmethod(builder) 
Example #21
Source File: fixture_core1_unions.py    From python-pytest-cases with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def ignore_unused(fixture_func):
    """
    A decorator for fixture functions so that they are compliant with fixture unions.
    It

     - adds the `request` fixture dependency to their signature if needed
     - filters the calls based on presence of the `NOT_USED` token in the request params.

    IMPORTANT: even if 'params' is not in kwargs, the fixture can be used in a fixture union and therefore a param
    *will* be received on some calls (and the fixture will be called several times - only once for real) - we have to
    handle the NOT_USED.

    :param fixture_func:
    :return:
    """
    old_sig = signature(fixture_func)

    # add request if needed
    func_needs_request = 'request' in old_sig.parameters
    if not func_needs_request:
        new_sig = add_signature_parameters(old_sig,
                                           first=Parameter('request', kind=Parameter.POSITIONAL_OR_KEYWORD))
    else:
        new_sig = old_sig

    if not isgeneratorfunction(fixture_func):
        # normal function with return statement
        @wraps(fixture_func, new_sig=new_sig)
        def wrapped_fixture_func(*args, **kwargs):
            request = kwargs['request'] if func_needs_request else kwargs.pop('request')
            if is_used_request(request):
                return fixture_func(*args, **kwargs)
            else:
                return NOT_USED

    else:
        # generator function (with a yield statement)
        @wraps(fixture_func, new_sig=new_sig)
        def wrapped_fixture_func(*args, **kwargs):
            request = kwargs['request'] if func_needs_request else kwargs.pop('request')
            if is_used_request(request):
                for res in fixture_func(*args, **kwargs):
                    yield res
            else:
                yield NOT_USED

    return wrapped_fixture_func 
Example #22
Source File: utils.py    From pydantic with MIT License 4 votes vote down vote up
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 #23
Source File: compat.py    From python-netsurv with MIT License 4 votes vote down vote up
def getfuncargnames(function, is_method=False, cls=None):
    """Returns the names of a function's mandatory arguments.

    This should return the names of all function arguments that:
        * Aren't bound to an instance or type as in instance or class methods.
        * Don't have default values.
        * Aren't bound with functools.partial.
        * Aren't replaced with mocks.

    The is_method and cls arguments indicate that the function should
    be treated as a bound method even though it's not unless, only in
    the case of cls, the function is a static method.

    @RonnyPfannschmidt: This function should be refactored when we
    revisit fixtures. The fixture mechanism should ask the node for
    the fixture names, and not try to obtain directly from the
    function object well after collection has occurred.

    """
    # The parameters attribute of a Signature object contains an
    # ordered mapping of parameter names to Parameter instances.  This
    # creates a tuple of the names of the parameters that don't have
    # defaults.
    try:
        parameters = signature(function).parameters
    except (ValueError, TypeError) as e:
        fail(
            "Could not determine arguments of {!r}: {}".format(function, e),
            pytrace=False,
        )

    arg_names = tuple(
        p.name
        for p in parameters.values()
        if (
            p.kind is Parameter.POSITIONAL_OR_KEYWORD
            or p.kind is Parameter.KEYWORD_ONLY
        )
        and p.default is Parameter.empty
    )
    # If this function should be treated as a bound method even though
    # it's passed as an unbound method or function, remove the first
    # parameter name.
    if is_method or (
        cls and not isinstance(cls.__dict__.get(function.__name__, None), staticmethod)
    ):
        arg_names = arg_names[1:]
    # Remove any names that will be replaced with mocks.
    if hasattr(function, "__wrapped__"):
        arg_names = arg_names[num_mock_patch_args(function) :]
    return arg_names