Esempio n. 1
0
def required_args(target, args=(), kwargs=()):
    """Return a set of names of required args to target that were not supplied
    in args or kwargs.

    This is used in builds() to determine which arguments to attempt to
    fill from type hints.  target may be any callable (including classes
    and bound methods).  args and kwargs should be as they are passed to
    builds() - that is, a tuple of values and a dict of names: values.
    """
    # We start with a workaround for NamedTuples, which don't have nice inits
    if inspect.isclass(target) and is_typed_named_tuple(target):
        provided = set(kwargs) | set(target._fields[:len(args)])
        return set(target._fields) - provided
    # Then we try to do the right thing with inspect.getfullargspec
    # Note that for classes we inspect the __init__ method, *unless* the class
    # has an explicit __signature__ attribute.  This allows us to support
    # runtime-generated constraints on **kwargs, as for e.g. Pydantic models.
    try:
        spec = inspect.getfullargspec(
            getattr(target, "__init__", target) if inspect.isclass(target)
            and not hasattr(target, "__signature__") else target)
    except TypeError:  # pragma: no cover
        return set()
    # self appears in the argspec of __init__ and bound methods, but it's an
    # error to explicitly supply it - so we might skip the first argument.
    skip_self = int(inspect.isclass(target) or inspect.ismethod(target))
    # Start with the args that were not supplied and all kwonly arguments,
    # then remove all positional arguments with default values, and finally
    # remove kwonly defaults and any supplied keyword arguments
    return (set(spec.args[skip_self + len(args):] + spec.kwonlyargs) -
            set(spec.args[len(spec.args) - len(spec.defaults or ()):]) -
            set(spec.kwonlydefaults or ()) - set(kwargs))
Esempio n. 2
0
def required_args(target, args=(), kwargs=()):
    """Return a set of names of required args to target that were not supplied
    in args or kwargs.

    This is used in builds() to determine which arguments to attempt to
    fill from type hints.  target may be any callable (including classes
    and bound methods).  args and kwargs should be as they are passed to
    builds() - that is, a tuple of values and a dict of names: values.
    """
    # We start with a workaround for NamedTuples, which don't have nice inits
    if inspect.isclass(target) and is_typed_named_tuple(target):
        provided = set(kwargs) | set(target._fields[:len(args)])
        return set(target._fields) - provided
    # Then we try to do the right thing with inspect.signature
    try:
        sig = get_signature(target)
    except (ValueError, TypeError):
        return set()
    return {
        name
        for name, param in list(sig.parameters.items())[len(args):]
        if arg_is_required(param) and name not in kwargs
    }