Ejemplo n.º 1
0
def _get_origin_type(anno: Any, assert_is_type: bool = True) -> Any:
    # this part looks weird but it's working for 3.6-3.8
    if anno is not None and anno.__module__ == "typing":
        if anno is Any:
            return object
        if hasattr(typing, "get_origin"):  # pragma: no cover
            anno = typing.get_origin(anno)  # type: ignore  # 3.8
        elif hasattr(anno, "__extra__"):  # pragma: no cover
            anno = anno.__extra__  # < 3.7
        elif hasattr(anno, "__origin__"):  # pragma: no cover
            anno = anno.__origin__  # 3.7
    if anno is None:  # pragma: no cover
        anno = type(None)
    if assert_is_type:
        assert_or_throw(
            _is_native_type(anno), TypeError(f"Can't find python type for {anno}")
        )
    return anno
Ejemplo n.º 2
0
    def filter_by_type(self, T: Type[AuxObject]) -> List[AuxObject]:
        """Returns all `AuxObject`s with the given type.

        You can pass in Union types as well.
        """

        if get_origin(T) == Union:
            T_raw = get_args(T)
            T = tuple(x for x in T_raw if x is not None)
            # T is a tuple of types

        def chk(x):
            try:
                return isinstance(x, T)
            except Exception:
                return False

        return [x for x in self._key_map.values() if chk(x)]
Ejemplo n.º 3
0
def _check(obj: Any, field: Field) -> None:
    name = field.name
    value = getattr(obj, name)
    actual = type(value)
    expected = get_type_hints(obj)[name]
    origin = get_origin(expected)
    if origin is list:
        pass
    raise NotImplementedError(f"""{expected=}, {is_generic_type(expected)}
           {is_union_type(expected)}
{get_origin(expected)}
        """)
    if is_generic_type(expected):
        raise NotImplementedError(f"{expected=}")
    elif isinstance(expected, type):
        raise SingleDataClassTypeError(name, actual, expected)
    else:
        raise NotImplementedError(f"{expected=}")
Ejemplo n.º 4
0
    def get_args(tp) -> Tuple[Any, ...]:
        """Get type arguments with all substitutions performed.

        For unions, basic simplifications used by Union constructor are performed.
        Examples::
            get_args(Dict[str, int]) == (str, int)
            get_args(int) == ()
            get_args(Union[int, Union[T, int], str][int]) == (int, str)
            get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int])
            get_args(Callable[[], T][int]) == ([], int)
        """
        if isinstance(tp, _GenericAlias):
            res = tp.__args__
            if get_origin(
                    tp) is collections.abc.Callable and res[0] is not Ellipsis:
                res = (list(res[:-1]), res[-1])
            return res
        return ()
Ejemplo n.º 5
0
    def from_nested_dict(cls, d, *, _nontype=type(None)):
        fields = dataclasses.fields(cls)  # cache?
        params = {}
        for f in fields:
            if f.name in d:
                val = d[f.name]
                typ = f.type

                # optional:
                if hasattr(typ, "__origin__") and t.get_origin(typ) == t.Union:
                    args = t.get_args(typ)
                    if len(args) == 2 and _nontype in args:
                        typ = args[1] if args[0] == _nontype else args[0]

                if hasattr(typ, "from_nested_dict"):
                    val = typ.from_nested_dict(val)
                params[f.name] = val
        return cls(**params)
Ejemplo n.º 6
0
def _fromJsonBasic(type, field, value):
    if isinstance(type, SerializableType):
        inst = None
        if value is not None:
            inst = type.fromJson(value)
        return inst
    elif isinstance(type, SerializableEnumType):
        return type(type.fromJson(value))
    elif hasattr(type, 'fromJson'):
        return type.fromJson(value)
    else:
        origin = get_origin(type)
        # cast the type, to allow for integer mappings
        # that can be round-tripped through a json representation
        if origin:
            return origin(value)
        else:
            return type(value)
Ejemplo n.º 7
0
def readstr(str_value: str, target):
    if isinstance(target, type) and issubclass(target, Enum):
        # noinspection PyUnresolvedReferences
        enum_value = target.__members__.get(str_value) \
                     or target.__members__.get(str_value.upper()) \
                     or target.__members__.get(str_value.lower())
        if enum_value is not None:
            return enum_value
    if target in _READERS:
        return _READERS[target](str_value)
    origin = ty.get_origin(target)
    if origin is not None and origin in _READERS:
        return _READERS[origin](str_value, ty.get_args(target))
    try:
        return target(str_value)
    except Exception as exc:
        raise ValueError(
            f'no way to convert into {target}: "{str_value}"') from exc
Ejemplo n.º 8
0
    def recurse(t):
        if isinstance(t, str):
            raise _StringForwardRefError(forward_ref=t)
        elif isinstance(t, ForwardRef):
            if t.__forward_evaluated__:
                t = t.__forward_value__
            else:
                raise _UnevaluatedForwardRefError(forward_ref=t)

        args = get_args(t)
        is_literal = Literal is not None and get_origin(t) is Literal
        if is_literal:
            yield Literal
        elif args:
            for arg in args:
                yield from recurse(arg)
        else:
            yield t
Ejemplo n.º 9
0
 def __set_generic_types(cls: type, annotations: dict) -> None:
     for n, v in annotations.items():
         if type(v) is TypeVar:
             annotations[n] = TypeInspect.__get_generic_type(cls)
             continue
         origin_v = get_origin(v)
         if origin_v is not None:
             if issubclass(origin_v,
                           List) and type(v.__args__[0]) is TypeVar:
                 generic_type = TypeInspect.__get_generic_type(cls)
                 v.__args__ = (generic_type,
                               )  # make List[~T] to List[generic_type]
             if issubclass(origin_v,
                           Dict) and type(v.__args__[1]) is TypeVar:
                 generic_type = TypeInspect.__get_generic_type(cls)
                 v.__args__ = (
                     v.__args__[0], generic_type
                 )  # make Dict[Any, ~T] to Dict[Any, genericType]
def get_type_representation(type_):
    type_origin = typing.get_origin(type_)
    if type_origin in (dict, list, tuple):
        type_ = type_origin
    elif type_origin is typing.Union:
        type_args = list(typing.get_args(type_))
        try:
            type_args.remove(type(None))
        except ValueError:
            pass
        if len(type_args) == 1:
            type_ = type_args[0]

    try:
        type_str = type_.__name__
    except AttributeError:
        return ''
    return TYPE_NAME_MAP.get(type_str, type_str)
Ejemplo n.º 11
0
def get_json_type(type_: Type) -> Dict[str, Union[str, List, Dict]]:
    r"""
	Get the type for the JSON schema that corresponds to the given Python type.

	:param type\_:
	"""

    if type_ in json_type_lookup:
        return {"type": json_type_lookup[type_]}

    elif get_origin(type_) is Union:
        return {"type": [get_json_type(t)["type"] for t in type_.__args__]}

    elif check_type(type_, list, List):
        args = get_args(type_)

        if args:
            items = get_json_type(args[0])

            if items is NotImplemented:
                return {"type": "array"}
            elif "type" in items:
                return {"type": "array", "items": items}
            elif "enum" in items:
                return {"type": "array", "items": items}
            else:
                return {"type": "array"}

        return {"type": "array"}

    elif check_type(type_, dict, Dict):
        return {"type": "object"}

    elif check_type(type_, Literal) or is_literal_type(type_):  # type: ignore
        return {"enum": [x for x in get_literal_values(type_)]}

    elif isinstance(type_, EnumMeta):
        return {"enum": [x._value_ for x in type_]}

    elif type_ is bool:
        return {"type": ["boolean", "string"]}

    else:
        return NotImplemented
Ejemplo n.º 12
0
def isinstance_(x, test_type):
    """ native isinstance_ with the test for typing.Union overridden """
    # TODO: TypeVar instances are treated as Any for the time being
    if test_type is Any or isinstance(test_type, TypeVar):
        return True

    if is_union(test_type):
        return any(isinstance_(x, t) for t in get_args(test_type))

    if is_dict(test_type):
        if isinstance(x, dict):
            dict_args = get_args(test_type)
            return all(
                isinstance_(k, dict_args[0]) and isinstance_(v, dict_args[1])
                for k, v in x.items()) if dict_args else True
        else:
            return False

    if is_list(test_type):
        if isinstance(x, list) or isinstance(x, UserList):
            list_type = get_args(test_type)
            return all(isinstance_(t, list_type[0])
                       for t in x) if list_type else True
        else:
            return False

    if is_tuple(test_type):
        if isinstance(x, tuple):
            tuple_args = get_args(test_type)
            return all(
                isinstance_(xv, tv)
                for xv, tv in zip(x, tuple_args)) if tuple_args else True
        else:
            return False

    if is_set(test_type):
        if isinstance(x, set):
            set_type = get_args(test_type)
            return all(isinstance_(e, set_type[0])
                       for e in x) if set_type else True
        else:
            return False

    return get_origin(test_type) is None and isinstance(x, test_type)
    def __init_subclass__(cls, *args, **kwargs) -> None:
        """
		Combines annotations & default values of this class with the one defined in sub-classes.
		Has similarities with the newly introduced typing.get_type_hints() function.
		"""
        super().__init_subclass__(*args, **kwargs)  # type: ignore

        joined_ann = {
            k: v
            for k, v in cls._annots.items()
            if not (k[0] == '_' or 'ClassVar' in str(v))
        }
        joined_defaults = cls._defaults.copy()
        joined_sks = cls._sks.copy()
        joined_aks = cls._aks.copy()

        for base in reversed(cls.mro()):
            if ann := getattr(base, '__annotations__', {}):
                defs = getattr(base, '__dict__', {})
                for k, v in ann.items():
                    if k == '__slots__' or k[0] == '_' or 'ClassVar' in str(v):
                        continue
                    joined_ann[k] = v  # update merged annotations
                    joined_aks.add(k)  # update set of known attribute names
                    if k in defs:
                        if type(defs[k]) is MemberDescriptorType:  # is a slot
                            if k in cls._slot_defaults:
                                joined_defaults[k] = cls._slot_defaults[k]
                            continue
                        joined_defaults[k] = base.__dict__[k]
                    # if None |  with no default
                    elif get_origin(v) in (
                            Union, UnionType
                    ) and NoneType in get_args(
                            v
                    ) and k not in joined_defaults:  # type: ignore[misc]
                        joined_defaults[k] = None
                    elif k in cls._slot_defaults:
                        joined_defaults[k] = cls._slot_defaults[k]

            # allow subclasses to change default value without supplying a new annotation
            for k, v in getattr(base, '__dict__', {}).items():
                if k in joined_ann and not k in ann:
                    joined_defaults[k] = v
Ejemplo n.º 14
0
 def _maybe_fill_missing(
     cls,
     ctx: commands.Context,
     parameters: Dict[str, inspect.Parameter],
     kwargs: Dict[str, Any],
 ):
     ignore_optional_for_conversion = ctx.command.ignore_optional_for_conversion
     for name, param in parameters.items():
         if param.default is not param.empty:
             continue
         anno = param.annotation
         if (not ignore_optional_for_conversion
                 and get_origin(anno) is Union
                 and type(None) in get_args(anno)):
             kwargs[name] = None
         elif cls.__total__:
             raise commands.MissingRequiredArgument(param)
         else:
             kwargs[name] = cls.MISSING
def assert_instance_is_binarized(instance, dict_):  # noqa: C901
    for field_name in instance.get_field_names():
        dict_value = dict_.get(ck(field_name), SENTINEL)
        if dict_value is SENTINEL:
            continue

        instance_value = getattr(instance, field_name)
        field_type = instance.get_field_type(field_name)
        if issubclass(field_type, SerializableMixin):
            assert_instance_is_binarized(instance_value, dict_value)
        else:
            origin = typing.get_origin(field_type)
            if origin and issubclass(origin, list):
                (item_type, ) = typing.get_args(field_type)
                for index, item in enumerate(dict_value):
                    if issubclass(item_type, SerializableMixin):
                        assert_instance_is_binarized(instance_value[index],
                                                     item)
                    elif issubclass(item_type, hexstr):
                        assert isinstance(
                            item,
                            bytes), f'{item} of {field_name} is not binarized'
            if origin and issubclass(origin, dict):
                (item_key_type, item_value_type) = typing.get_args(field_type)
                for item_key, item_value in dict_value.items():
                    if issubclass(item_key_type, hexstr):
                        assert isinstance(
                            item_key, bytes
                        ), f'{item_key} of {field_name} is not binarized'

                    instance_item_key = hexstr.from_bytes(
                        item_key) if isinstance(item_key, bytes) else item_key
                    if issubclass(item_value_type, SerializableMixin):
                        assert_instance_is_binarized(
                            instance_value[instance_item_key], item_value)
                    elif issubclass(item_value_type, hexstr):
                        assert isinstance(item_value, bytes), (
                            f'{item_value} of {item_key} key of {field_name} is not binarized'
                        )
            elif issubclass(field_type, hexstr):
                assert isinstance(
                    dict_value,
                    bytes), f'{field_name} of {instance} is not binarized'
Ejemplo n.º 16
0
def extract_initable(t: type, inst=None) -> Optional[Callable[..., type]]:
    """Extract e.g `dict` from `Optional[dict]`.
    Returns None if non-extractable.

    >>> from typing import Optional, Dict, List
    >>> ei = extract_initable

    >>> ei(List[str]) is ei(List) is ei(list) is ei(Optional[List[str]]) is list
    True

    >>> ei(Dict[str,int]) is ei(Dict) is ei(dict) is ei(Optional[Dict[str,int]]) is dict
    True

    >>> class Foo: ...
    >>> ei(Foo) is Foo
    True
    """
    if isinstance(t, ForwardRef):
        evaluated = resolve_forwardref(t, inst.__class__)
        return extract_initable(evaluated)
        # breakpoint()
        # return evaluated
    origin = typing.get_origin(t)
    if origin is None:  # Any
        if inspect.getmodule(t) is typing:
            return None
        return t

    type_args = typing.get_args(t)
    if origin is not typing.Union:
        if issubclass(origin, Iterable) and type_args:
            if len(type_args) > 1:
                raise NotImplementedError(
                    f"{t = }, {type_args = }, more than 1 type_args")
            return lambda *args: origin(map(type_args[0], *args))
        return origin

    # origin is Union or Optional[foo]
    origins = [a for a in typing.get_args(t) if a != type(None)]
    if len(origins) == 1:
        origin = origins[0]
        return extract_initable(origin)
    return None
Ejemplo n.º 17
0
def GetUnionUnderlyingType(typeToCheck, matchingType=None):
    ''' This retrieves the underlying types behind a unioned type by appropriately
        passing in the required matching type in the matchingType input argument.

        If that is 'None' (not to be confused with NoneType), then it will retrieve
        the 'real' type behind the union, i.e not Nullable && not None
    '''
    if (not(typing.get_origin(typeToCheck) == typing.Union)):
        return None

    for t in typing.get_args(typeToCheck):
        if (matchingType is None):
            if (t != type(None) and t != Nullable):
                return t
        else:
            if (t == matchingType):
                return t

    return None
Ejemplo n.º 18
0
    def __handle_type_hint_args(cls_set: Set[type]) -> Set[type]:
        for cls in cls_set.copy():
            cls_str = str(cls)
            if cls_str.startswith('typing.Optional') \
                    or cls_str.startswith('typing.Union'):
                cls_set.remove(cls)
                cls_set.update(
                    __handle_type_hint_args(set(typing.get_args(cls))))
            elif cls_str.startswith('typing.Any'):
                cls_set.remove(cls)
                cls_set.update({object, type(None)})
            elif cls_str.startswith('typing.'):

                tmp = typing.get_origin(cls)
                if tmp is not None:
                    cls_set.remove(cls)
                    cls_set.update({tmp})

        return cls_set
Ejemplo n.º 19
0
 async def _transform_identifier(
         ctx: commands.Context, parameters: Dict[str, inspect.Parameter],
         kwargs: Dict[str, Any]) -> Optional[inspect.Parameter]:
     arg: str = await ctx.command.transform(ctx, _ident_param)
     try:
         parameter = parameters.pop(arg)
     except KeyError:
         if arg in kwargs:
             raise commands.BadArgument(
                 f"Multiple values provided for argument `{arg}`") from None
         raise commands.BadArgument(
             f"No such setting by the name of `{arg}`") from None
     anno = parameter.annotation
     if get_origin(anno) is Union:
         # since a name was passed, suppress d.py's typing.Optional behavior
         parameter = parameter.replace(annotation=Union[tuple(
             filter(_not_nonetype, get_args(anno)))]  # type: ignore
                                       )
     return parameter
Ejemplo n.º 20
0
def _check_special_type(tp, name):
    """checking if the type is a container: ty.List, ty.Dict or ty.Union"""
    if sys.version_info.minor >= 8:
        return ty.get_origin(tp), ty.get_args(tp)
    else:
        if isinstance(tp, type):  # simple type
            return None, ()
        else:
            if tp._name == "List":
                return list, tp.__args__
            elif tp._name == "Dict":
                return dict, tp.__args__
            elif tp.__origin__ is ty.Union:
                return ty.Union, tp.__args__
            else:
                warnings.warn(
                    f"not type check for {name} field, type check not implemented for type {tp}"
                )
                return None, ()
Ejemplo n.º 21
0
def best_match(val, types):
    # Best match : casting litterals
    is_litteral = tuple(typing.get_origin(t) is typing.Literal for t in types)
    casted = tuple(can_cast(val, t) for t in types)
    match = is_litteral and casted
    if any(match):
        index = match.index(max(match))
        return index, types[index]
    # then instance
    match = tuple(matching_instance(val, t) for t in types)
    if any(match):
        index = match.index(max(match))
        return index, types[index]
    # then can_cast
    match = casted
    if any(match):
        index = match.index(max(match))
        return index, types[index]
    raise ValueError("No match for val {} and types {}".format(val, types))
Ejemplo n.º 22
0
def is_dict(type_value):
    """Check if a type is a dict type."""

    if type_value is dict:
        return True

    if not is_typing_type(type_value):
        return False

    if not hasattr(type_value, "__origin__"):
        return False

    if sys.version_info < (3, 7):
        return type_value.__origin__ == typing.Dict

    if sys.version_info < (3, 8):
        return type_value.__origin__ == dict

    return typing.get_origin(type_value) == dict
    def __detect_type_vars(cls,
                           generic_cls: TAlias_generic_cls) \
            -> list[TypeVar]:
        from typing import TypeVar, Generic, get_args, get_origin

        type_vars: list[TypeVar] = []

        for orig_base in generic_cls.__orig_bases__:
            if get_origin(orig_base) is Generic:
                base_type_args = get_args(orig_base)

                if len(base_type_args) > 0:
                    for type_arg in base_type_args:
                        if isinstance(type_arg, TypeVar):
                            type_vars.append(type_arg)
                else:
                    type_vars += cls.__detect_type_vars(generic_cls=orig_base)

        return type_vars
Ejemplo n.º 24
0
def function_operator(
        function: t.Callable[..., t.Optional[Term]]) -> FunctionOperator:
    import inspect

    signature = inspect.signature(function)
    type_hints = t.get_type_hints(function)

    types: t.Dict[str, t.Type[Term]] = {}
    optionals: t.Set[str] = set()

    for parameter in signature.parameters.values():
        typ = type_hints.get(parameter.name, Term)
        origin = t.get_origin(typ)
        args = t.get_args(typ)
        optional = False
        if origin is t.Union and len(args) == 2 and args[1] is type(None):
            typ = args[0]
            optional = True
        if not isinstance(typ, type) or not issubclass(typ, Term):
            raise InvalidParameterTypeError(
                f"invalid type annotation {typ} for parameter {parameter.name}"
            )
        types[parameter.name] = typ
        if optional:
            optionals.add(parameter.name)

    def implementation(arguments: Arguments) -> t.Optional[Term]:
        try:
            bound_arguments = signature.bind(*arguments)
        except TypeError:
            return None
        else:
            for parameter in signature.parameters.values():
                argument = bound_arguments.arguments.get(parameter.name, None)
                if argument is None:
                    if parameter.name not in optionals:
                        return None
                elif not isinstance(argument, types[parameter.name]):
                    return None
            return function(*arguments)

    return FunctionOperator(implementation,
                            name=getattr(function, "__name__", None))
Ejemplo n.º 25
0
def is_type_hint_instance_of(type_hint, mcs) -> bool:
    """Check if `type_hint` contains a `mcs` instance.

    This is an utilitarian function for `BaseResourceMeta`.

    ###### Parameters ######

    * `type_hint`: type hint to check
    * `mcs`: metaclass to check

    For a given class `C`, instance of metaclass `MC`, all following expressions
    are evaluated to `True`:

    ```python
    is_type_hint_instance_of(C, MC)
    is_type_hint_instance_of(Iterable[C], MC)
    is_type_hint_instance_of(Optional[C], MC)
    is_type_hint_instance_of(Union[C, None], MC)
    is_type_hint_instance_of(Optional[Iterable[C]], MC)
    is_type_hint_instance_of(Union[Iterable[C], None], MC)
    ```

    ###### Returned value ######

    `True` in the shown cases, `Fasle` otherwise.
    """
    if isinstance(type_hint, mcs):
        return True
    origin = typing.get_origin(type_hint)
    if origin is None:
        return False
    type_args = typing.get_args(type_hint)
    if origin is Union:
        # in case of Optional field, check if it is Union[BaseResourceMeta, None]
        if len(type_args) != 2:
            return False
        if type(None) not in type_args:
            return False
        return is_type_hint_instance_of(type_args[0], mcs)
    if origin is collections.abc.Iterable:
        # in case of an iterable, check if it is a BaseResource
        return is_type_hint_instance_of(type_args[0], mcs)
    return False
Ejemplo n.º 26
0
    def convert(
        self,
        game: Game,
        type_: Union[NoneType, Type[GameObject]],
        obj: Optional[Any],
    ) -> Optional[GameObject]:
        """Convert `obj` to the given `type_`, in the context of the `game`."""

        if (type_ is None) or (type_ is NoneType):
            if obj is None:
                return None
            raise TypeError(f"obj must be None, got {obj!r}")

        if isinstance(obj, type_):  # also works if None, NoneType :)
            return obj

        _t_origin = get_origin(type_)
        _t_args = get_args(type_)

        if _t_origin is Union:  # Union or Optional
            for arg in _t_args:
                try:
                    return self.convert(game, arg, obj)
                except Exception:
                    pass
            # We went through all args - couldn't convert.
            raise MafiaConverterError(obj, type_)
        elif _t_origin is not None:
            raise TypeError(f"{_t_origin!r} is not supported for conversion.")

        # Find the function - try direct match, or using first subclass that works
        func_map = self._map[type_]
        func = func_map.get(type(obj))
        if func is not None:
            return func(game, obj)
        for t, f in func_map.items():
            if isinstance(obj, t):
                try:
                    return f(game, obj)
                except Exception:
                    logger.exception(f"Couldn't convert using {f!r}, trying again.")
        raise MafiaConverterError(obj, type_)
Ejemplo n.º 27
0
def list_algorithm_params(resolver, abstract_pathname: str, **kwargs):
    types = list_types(resolver)
    sig = resolver.abstract_algorithms[abstract_pathname].__signature__

    def resolve_parameter(p) -> OrderedDict:
        result: OrderedDict
        p_class = p if type(p) is type else p.__class__
        if p_class is Combo:
            resolved = [resolve_parameter(psub) for psub in p.types]
            combo_type = " or ".join(r["type"] for r in resolved)
            choices = [c for r in resolved for c in r["choices"]]
            if p.optional:
                combo_type += " or None"
                choices.append("NoneType")
            result = OrderedDict([("type", combo_type), ("choices", choices)])
        elif issubclass(p_class, AbstractType):
            choices = list(types[p_class.__name__]["children"].keys())
            result = OrderedDict([("type", p_class.__name__),
                                  ("choices", choices)])
        elif typing.get_origin(p) == collections.abc.Callable:
            result = OrderedDict([("type", p._name), ("choices", [p._name])])
        elif p is typing.Any:
            result = OrderedDict([("type", "Any"), ("choices", ["Any"])])
        else:
            result = OrderedDict([("type", p_class.__name__),
                                  ("choices", [p_class.__name__])])
        return result

    params = OrderedDict()
    for pname, p in sig.parameters.items():
        params[pname] = resolve_parameter(p.annotation)

    returns = []
    if typing.get_origin(sig.return_annotation) is tuple:
        for ret in typing.get_args(sig.return_annotation):
            returns.append(resolve_parameter(ret))
    else:
        returns.append(resolve_parameter(sig.return_annotation))
    return {
        "parameters": params,
        "returns": returns,
    }
Ejemplo n.º 28
0
def get_field_type(field_type, metadata):
    simple_types = {
        int: "int",
        str: "str",
        float: "float",
        bool: "bool",
        Path: "path"
    }
    complex_types = {
        list: "list",
        dict: "dict",
        Union: "union",
        tuple: "tuple",
    }
    special_cases = {Coordinate: "coordinate"}
    if field_type in simple_types:
        return handle_simple_types(field_type, metadata)

    elif get_origin(field_type) in complex_types:
        return handle_complex_types(field_type, metadata)

    elif field_type in special_cases:
        return handle_special_cases(field_type, metadata)

    elif issubclass(field_type, Enum):
        return handle_enum(field_type, metadata)

    else:
        try:
            configurable = getattr(dacapo.configurables, field_type.__name__)
            fields = parse_fields(configurable)
            return {
                "type": "configurable",
                "fields": fields,
                "help_text": metadata.get("help_text"),
            }
        except AttributeError:
            pass

    raise ValueError(f"Unsupported type: {field_type}, "
                     f"origin: {get_origin(field_type)}, "
                     f"args: {get_args(field_type)}")
Ejemplo n.º 29
0
    def do_decode(cls, obj: Any, obj_type: Type[DecodableType]) -> Any:
        """Decodes json into the specified type

        Args:
            obj: the json object to decode
            obj_type: a class object which is the type we're decoding into.
        """

        type_origin = get_origin(obj_type)
        type_args = get_args(obj_type)

        if inspect.isclass(obj_type) and issubclass(obj_type, ConjureBeanType):
            return cls.decode_conjure_bean_type(obj, obj_type)

        elif inspect.isclass(obj_type) and issubclass(obj_type,
                                                      ConjureUnionType):
            return cls.decode_conjure_union_type(obj, obj_type)

        elif inspect.isclass(obj_type) and issubclass(obj_type,
                                                      ConjureEnumType):
            return cls.decode_conjure_enum_type(obj, obj_type)

        elif isinstance(obj_type, DictType):
            return cls.decode_dict(obj, obj_type.key_type, obj_type.value_type)

        elif isinstance(obj_type, ListType):
            return cls.decode_list(obj, obj_type.item_type)

        elif isinstance(obj_type, OptionalType):
            return cls.decode_optional(obj, obj_type.item_type)

        elif type_origin is OptionalTypeWrapper:
            return cls.decode_optional(obj, type_args[0])

        elif type_origin is dict:
            (key_type, value_type) = type_args
            return cls.decode_dict(obj, key_type, value_type)

        elif type_origin is list:
            return cls.decode_list(obj, type_args[0])

        return cls.decode_primitive(obj, obj_type)
Ejemplo n.º 30
0
def check_type(name, value, annotation):
    if annotation is inspect._empty or annotation is Any:
        return value

    if type(annotation) is type:
        if type(value) is annotation:
            return value
        else:
            raise InputTypeError(name).from_types(type(value), annotation)

    origin = typing.get_origin(annotation)
    args = typing.get_args(annotation)

    if type(annotation) is TypeVar:
        return check_typevar(name, value, annotation, args)

    if origin is CallableType:
        return check_callable(name, value, args)

    if origin is Union:
        return check_union(name, value, args)

    if origin is list:
        value = check_type(name, value, list)
        return check_list(name, value, args)

    if origin is tuple:
        value = check_type(name, value, tuple)
        return check_tuple(name, value, args)

    if origin is dict:
        value = check_type(name, value, dict)
        return check_dict(name, value, args)

    if origin is Literal:
        return check_literal(name, value, args)

    if issubclass(origin, IsopyType):
        return origin.check_type(name, value, args)

    print('not caught', name, value, annotation, origin, args)
    return value