Ejemplo n.º 1
0
def _argument_to_argparse_input(arg):
    # type: (Any) -> Tuple[List, Dict[str, Any]]

    add_argument_kwargs = {"help": arg.description}
    if arg.positional:
        add_argument_args = [arg.name]
        if arg.extra_names:
            msg = "Aliases are not yet supported for positional arguments @ {}".format(
                arg.name)
            raise ValueError(msg)
        if arg.default_value_set:
            msg = ("Positional arguments with default values are "
                   "not supported @ {}".format(arg.name))
            raise ValueError(msg)
    else:
        add_argument_args = [
            transform_argument_name(x) for x in ([arg.name] + arg.extra_names)
        ]
        add_argument_kwargs["default"] = arg.default_value
        add_argument_kwargs["required"] = not arg.default_value_set

    argument_type = (arg.type if not is_optional_type(arg.type) else
                     get_first_type_argument(arg.type))
    if argument_type in [int, float, str]:
        add_argument_kwargs["type"] = argument_type
        add_argument_kwargs["metavar"] = str(argument_type.__name__).upper()
    elif argument_type == bool or arg.default_value is False:
        add_argument_kwargs["action"] = "store_true"
    elif arg.default_value is True:
        add_argument_kwargs["action"] = "store_false"
    elif is_mapping_type(argument_type):
        add_argument_kwargs["type"] = _parse_dict(argument_type)
        add_argument_kwargs["metavar"] = "DICT[{}: {}]".format(
            *get_dict_kv_arg_type_as_str(argument_type))
    elif is_iterable_type(argument_type):
        add_argument_kwargs["type"] = get_first_type_argument(argument_type)
        add_argument_kwargs["nargs"] = "+"
        add_argument_kwargs["metavar"] = "{}".format(
            get_list_arg_type_as_str(argument_type))
    else:
        add_argument_kwargs["type"] = argument_type

    if arg.choices:
        add_argument_kwargs["choices"] = arg.choices
        add_argument_kwargs["metavar"] = "{{{}}}".format(",".join(
            map(str, arg.choices)))
    if arg.positional and "metavar" in add_argument_kwargs:
        add_argument_kwargs["metavar"] = "{}<{}>".format(
            arg.name, add_argument_kwargs["metavar"])

    return add_argument_args, add_argument_kwargs
Ejemplo n.º 2
0
def get_dict_kv_arg_type_as_str(tp):
    """
    This takes a type (typing.Mapping[str, int]) and returns a tuple (key_type,
    value_type) that contains string representations of the type arguments, or
    "any" if it's not defined
    """
    assert is_mapping_type(tp), f"{tp} is not a mapping type"
    args = getattr(tp, "__args__", None)
    key_type = "any"
    value_type = "any"
    if args and len(args) >= 2:
        key_type = getattr(args[0], "__name__", str(args[0]))
        value_type = getattr(args[1], "__name__", str(args[1]))
    return key_type, value_type
Ejemplo n.º 3
0
def _build_simple_value(string, tp):
    if not tp or issubclass_(tp, str):
        return string
    elif is_mapping_type(tp):
        entries = (re.split(r"\s*[:=]\s*", entry, maxsplit=1)
                   for entry in string.split(";"))
        if is_dict_value_iterable(tp):
            entries = ((k, re.split(r"\s*,\s*", v)) for k, v in entries)
        return {k.strip(): v for k, v in entries}
    elif is_tuple_type(tp):
        return tuple(item for item in string.split(","))
    elif is_iterable_type(tp):
        return [item for item in string.split(",")]
    else:
        return string
Ejemplo n.º 4
0
def get_typing_function(tp):
    func = None

    # TypeVars are a problem as they can defined multiple possible types.
    # While a single type TypeVar is somewhat useless, no reason to deny it
    # though
    if is_typevar(tp):
        if len(tp.__constraints__) == 0:
            # Unconstrained TypeVars may come from generics
            func = _identity_function
        elif len(tp.__constraints__) == 1:
            assert not NEW_TYPING, "Python 3.7+ forbids single constraint for `TypeVar'"
            func = get_typing_function(tp.__constraints__[0])
        else:
            raise ValueError(
                "Cannot resolve typing function for TypeVar({constraints}) "
                "as it declares multiple types".format(constraints=", ".join(
                    getattr(c, "_name", c.__name__)
                    for c in tp.__constraints__)))
    elif tp == typing.Any:
        func = _identity_function
    elif issubclass_(tp, str):
        func = str
    elif is_mapping_type(tp):
        func = _apply_dict_type
    elif is_tuple_type(tp):
        func = _apply_tuple_type
    elif is_iterable_type(tp):
        func = _apply_list_type
    elif is_optional_type(tp):
        func = _apply_optional_type
    elif callable(tp):
        func = tp
    else:
        raise ValueError(
            'Cannot find a function to apply type "{}"'.format(tp))

    args = getattr(tp, "__args__", None)

    if args:
        # this can be a Generic type from the typing module, like
        # List[str], Mapping[int, str] and so on. In that case we need to
        # also deal with the generic typing
        args_types = [get_typing_function(arg) for arg in args]
        func = _partial_builder(args_types)(func)

    return func
Ejemplo n.º 5
0
def is_dict_value_iterable(tp):
    assert is_mapping_type(tp), f"{tp} is not a mapping type"
    args = getattr(tp, "__args__", None)
    if args and len(args) == 2:
        return is_iterable_type(args[1])
    return False