Exemple #1
0
def is_leq_informative(left, right):
    if not (is_type(left) and is_type(right)):
        raise ValueError('Both parameters need to be types')
    if (get_origin(left) is Generic or get_origin(right) is Generic):
        raise ValueError("typing Generic not supported")
    if left is right:
        result = True
    elif left is Unknown:
        result = True
    elif right is Unknown:
        result = False
    elif right is Any:
        result = True
    elif left is Any:
        result = False
    elif is_union_type(right):
        result = is_leq_informative_union(left, right)
    elif is_union_type(left):
        result = False
    elif is_parameterized(right):
        result = is_leq_informative_parameterized_right(left, right)
    elif is_parametrical(right):
        if is_parameterized(left):
            left = get_origin(left)
        result = issubclass(left, right)
    elif is_parametrical(left) or is_parameterized(left):
        result = False
    elif left in type_order and right in type_order[left]:
        result = True
    else:
        result = issubclass(left, right)

    return result
Exemple #2
0
def _is_instance_of_dict_type(_object: Any, required_dict_type: Type) -> bool:
    key_type, value_type = get_args(required_dict_type)
    if is_optional_type(key_type) or is_union_type(key_type):
        key_type = get_args(key_type)
    if is_optional_type(value_type) or is_union_type(value_type):
        value_type = get_args(value_type)

    return not (not isinstance(_object, dict) or any(
        not isinstance(k, key_type)
        for k in _object.keys()) or any(not isinstance(v, value_type)
                                        for v in _object.values()))
    def __init__(
        self,
        dependency: Union[T, str],
        *,
        namespace: str = None,
        group: str = None,
        exclude_groups: Sequence[str] = None,
        lazy: bool = False,
    ):
        optional = False
        multiple = False

        if typing_inspect.is_optional_type(dependency):
            dependency = typing_inspect.get_args(dependency, evaluate=True)[0]
            optional = True
        elif typing_inspect.is_union_type(dependency):
            raise TypeError(
                f"Autowired Union can only be used to indicate"
                f" optional autowiring in the forms 'Union[T, None]' or"
                f" 'Optional[T]'")

        if is_sequence(typing_inspect.get_origin(dependency) or dependency):
            subscripted_types = typing_inspect.get_args(dependency,
                                                        evaluate=True)
            if subscripted_types == typing_inspect.get_args(Sequence):
                raise TypeError(f"Type not defined for Autowired list")
            subscripted_type = subscripted_types[0]
            if typing_inspect.is_optional_type(subscripted_type):
                raise TypeError(
                    f"List of Optional is invalid for autowiring. Use"
                    f" 'Autowired(Optional[List[...]])' instead.")
            elif typing_inspect.is_union_type(subscripted_type):
                raise TypeError(
                    f"Only one type should be defined for Autowired list")
            dependency = subscripted_type
            multiple = True
        elif is_raw_sequence(dependency):
            if len(dependency) != 1:
                raise TypeError(
                    f"Only one type should be defined for Autowired"
                    f" {dependency.__class__.__qualname__}")
            dependency = dependency[0]
            multiple = True

        self.optional = optional
        self.multiple = multiple
        self.dependency = sanitize_if_forward_ref(dependency)
        self.namespace = namespace
        self.group = group
        self.exclude_groups = exclude_groups
        self.lazy = lazy
Exemple #4
0
def collapse_unions(obj1, obj2, union_rewriter=None):
    if not union_rewriter:
        union_rewriter = IdentityUnionRewriter()

    union = make_union([obj1, obj2])
    union = union_rewriter.rewrite(union)
    if not typing_inspect.is_union_type(union):
        return union

    for obj in [obj1, obj2]:
        if typing_inspect.is_union_type(obj) and len(union.__args__) <= len(
                obj.__args__):
            return union

    return NOT_SIMPLIFIED
Exemple #5
0
def _obtain_referred_type(type_) -> List[type]:
    """
    Obtain the type referred by the type hint.

    Example.:
        class A()
            first: List[str]
            second: List[Foo]
            third: Union[Foo, Bar]
            fourth: List[Union[Foo, Bar]]
            fifth: Union[str, int]

    Running `_ObtainReferredType` on each field will return:
        first => [str]
        second => [Foo]
        third => [Foo, Bar]
        fourth => [Foo, Bar]
        fifth => [str, int]

    If type_ is not either a List or Union, an TypeError exception will be raised.
    """

    if is_list(type_):
        type_ = typing_inspect.get_args(type_)[0]
        return (_obtain_referred_type(type_)
                if _is_from_typing_module(type_) else [type_])

    if typing_inspect.is_union_type(type_):
        return [i for i in type_.__args__ if i is not None.__class__]

    if is_dict(type_):
        return type_.__args__[1]

    raise TypeError(
        f"type_ must be a List or Union referring other types, got {type_}")
Exemple #6
0
    def _parse_annotation(self, raw_annotation: Type) -> None:
        """Parse key information from annotation.

        :param annotation: A subscripted type.
        :returns: Annotation
        """
        self.raw_annotation = raw_annotation
        self.origin = self.arg = None

        self.optional = typing_inspect.is_optional_type(raw_annotation)
        if self.optional and typing_inspect.is_union_type(raw_annotation):
            # Annotated with Optional or Union[..., NoneType]
            # get_args -> (pandera.typing.Index[str], <class 'NoneType'>)
            raw_annotation = typing_inspect.get_args(raw_annotation)[0]

        self.origin = typing_inspect.get_origin(raw_annotation)
        # Replace empty tuple returned from get_args by None
        args = typing_inspect.get_args(raw_annotation) or None
        self.arg = args[0] if args else args

        self.metadata = getattr(self.arg, "__metadata__", None)
        if self.metadata:
            self.arg = typing_inspect.get_args(self.arg)[0]

        self.literal = typing_inspect.is_literal_type(self.arg)
        if self.literal:
            self.arg = typing_inspect.get_args(self.arg)[0]

        self.default_dtype = getattr(raw_annotation, "default_dtype", None)
Exemple #7
0
def _generate_field_schema(field_name: str, field: Field,
                           schemas: Dict[str, Schema]) -> Tuple[bool, Schema]:
    is_optional, annotation = extract_optional_annotation(field.annotation)
    if is_schema(annotation):
        field_schema_name = _generate_schema(annotation, schemas)
        field_schema = Schema(ref=_make_ref_path(field_schema_name))

    elif is_generic_type(annotation):
        origin = get_origin(annotation)
        if origin in _LIST_TYPES:
            arguments = get_args(annotation)
            if arguments and is_schema(arguments[0]):
                item_schema_name = _generate_schema(arguments[0], schemas)
                field_schema = Schema("array",
                                      items=_make_schema_ref(item_schema_name))

            else:
                field_schema = _generate_primitive_schema(annotation)

        elif origin in _DICT_TYPES:
            # TODO: Add support for additionalFields.
            field_schema = _generate_primitive_schema(dict)

        else:  # pragma: no cover
            raise ValueError(
                f"Unsupported type {origin} for field {field.name!r}.")

    elif is_union_type(annotation):
        sub_schemas = []
        for arg in get_args(annotation):
            _, sub_schema = _generate_field_schema("", Field(annotation=arg),
                                                   schemas)
            sub_schemas.append(dump_schema(sub_schema, sparse=True))

        field_schema = Schema(any_of=sub_schemas)

    else:
        field_schema = _generate_primitive_schema(annotation)

    if field_schema is not None:
        field_schema.description = field.description

        if field.request_name != field.response_name:
            if field_name == field.request_name:
                field_schema.write_only = True

            else:
                field_schema.read_only = True

        elif field.response_only:
            field_schema.read_only = True

        elif field.request_only:
            field_schema.write_only = True

        for option, value in field.validator_options.items():
            if option in Schema._FIELDS:
                setattr(field_schema, option, value)

    return is_optional, field_schema
Exemple #8
0
    async def generate_signature_error(self, ctx, error):
        command = ctx.command
        argument = ""
        found = False

        def check_converter(_error):
            if isinstance(_error, commands.BadArgument):
                frames = [*traceback.walk_tb(_error.__traceback__)]
                last_trace = frames[-1]
                frame = last_trace[0]
                converter = frame.f_locals["self"]
                return getattr(
                    discord,
                    converter.__class__.__name__.replace("Converter", ""))

        if _class := getattr(error, "converter", check_converter(error)):
            signature = inspect.signature(command.callback).parameters
            for typing in signature.values():
                if typing_inspect.is_union_type(typing):
                    checking = typing.annotation.__args__
                else:
                    checking = (typing.annotation, )
                for convert in checking:
                    if convert is _class:
                        found = True
                        argument = typing.name
                        break
Exemple #9
0
    def _parse_annotation(self, raw_annotation: Type) -> None:
        """Parse key information from annotation.

        :param annotation: A subscripted type.
        :returns: Annotation
        """
        self.raw_annotation = raw_annotation
        self.origin = self.arg = None

        self.optional = typing_inspect.is_optional_type(raw_annotation)
        if self.optional and typing_inspect.is_union_type(raw_annotation):
            # Annotated with Optional or Union[..., NoneType]
            if LEGACY_TYPING:  # pragma: no cover
                # get_args -> ((pandera.typing.Index, <class 'str'>), <class 'NoneType'>)
                self.origin, self.arg = typing_inspect.get_args(
                    raw_annotation)[0]
            # get_args -> (pandera.typing.Index[str], <class 'NoneType'>)
            raw_annotation = typing_inspect.get_args(raw_annotation)[0]

        if not (self.optional and LEGACY_TYPING):
            self.origin = typing_inspect.get_origin(raw_annotation)
            args = typing_inspect.get_args(raw_annotation)
            self.arg = args[0] if args else args

        self.metadata = getattr(self.arg, "__metadata__", None)
        if self.metadata:
            self.arg = typing_inspect.get_args(self.arg)[0]

        self.literal = typing_inspect.is_literal_type(self.arg)
        if self.literal:
            self.arg = typing_inspect.get_args(self.arg)[0]
Exemple #10
0
def is_instance_of_type(_object: Any, required_type: Type) -> Optional[bool]:
    """
    Check if `object` is of type `required_type`.

    Works same as `isinstance`, but also has limited support of typing
    generics (such as Union, Optional, etc).

    Works on small subset of types, can fail on complex types.
    See tests (tests/tests_unit/test_type_utils.py) for examples.
    """
    type_to_check_first = required_type
    if is_optional_type(required_type) or is_union_type(required_type):
        type_to_check_first = get_args(required_type)
    try:
        return isinstance(_object, type_to_check_first)
    except TypeError:
        pass

    if is_optional_type(required_type):
        if _object is None:
            return True
        required_type = type_to_check_first[0]  # content of Optional[...]

    type_to_checker_map = {
        list: _is_instance_of_list_type,
        dict: _is_instance_of_dict_type,
        Mapping: _is_instance_of_dict_type,
    }
    if get_origin(required_type) in type_to_checker_map:
        return type_to_checker_map[get_origin(required_type)](_object,
                                                              required_type)
    return None
Exemple #11
0
def is_matching_type(_type: Type, annotation: Any) -> bool:
    """Return whether a specified type matches an annotation.

    This function does a bit more than a simple comparison, and performs the following
    extra checks:

        - If the :param`annotation` is a union, then the union is unwrapped and each of
          its types is compared against :param:`_type`.
        - If the specified :param:`_type` is generic, it will verify that all of its
          parameters match those of a matching annotation.

    """
    # Look for an easy win.
    if _type == annotation:
        return True

    # If annotation is Union, we unwrap it to check against each of the possible inner
    # types.
    if is_union_type(annotation):
        if any(_type == tt for tt in get_args(annotation, evaluate=True)):
            return True

    # If both the global type and the argument annotation can be reduced to
    # the same base type, and have equivalent argument tuples, we can
    # assume that they are equivalent.
    # TODO
    return False
Exemple #12
0
    def _add_callable_dependencies(
        self, call: GenericCallableAccessibleObject, recursion_level: int
    ) -> None:
        """Add required dependencies.

        Args:
            call: The object whose parameter types should be added as dependencies.
            recursion_level: The current level of recursion of the search
        """
        self._logger.debug("Find dependencies for %s", call)
        if recursion_level > config.INSTANCE.max_cluster_recursion:
            self._logger.debug("Reached recursion limit. No more dependencies added.")
            return
        for param_name, type_ in call.inferred_signature.parameters.items():
            self._logger.debug("Resolving '%s' (%s)", param_name, type_)
            types = {type_}
            if is_union_type(type_):
                types = set(get_args(type_))

            for elem in types:
                if is_primitive_type(elem):
                    self._logger.debug("Not following primitive argument.")
                    continue
                if inspect.isclass(elem):
                    assert elem
                    self._logger.debug("Adding dependency for class %s", elem)
                    self._dependencies_to_solve.add(
                        DependencyPair(elem, recursion_level)
                    )
                else:
                    self._logger.debug("Found typing annotation %s, skipping", elem)
def robust_isinstance(inst, typ) -> bool:
    """
    Similar to isinstance, but if 'typ' is a parametrized generic Type, it is first transformed into its base generic
    class so that the instance check works. It is also robust to Union and Any.

    :param inst:
    :param typ:
    :return:
    """
    if typ is Any:
        return True
    if is_typevar(typ):
        if hasattr(typ, '__constraints__') and typ.__constraints__ is not None:
            typs = get_args(typ, evaluate=True)
            return any(robust_isinstance(inst, t) for t in typs)
        elif hasattr(typ, '__bound__') and typ.__bound__ is not None:
            return robust_isinstance(inst, typ.__bound__)
        else:
            # a raw TypeVar means 'anything'
            return True
    else:
        if is_union_type(typ):
            typs = get_args(typ, evaluate=True)
            return any(robust_isinstance(inst, t) for t in typs)
        else:
            return isinstance(inst, get_base_generic_type(typ))
def is_valid_pep484_type_hint(typ_hint, allow_forward_refs: bool = False):
    """
    Returns True if the provided type is a valid PEP484 type hint, False otherwise.

    Note: string type hints (forward references) are not supported by default, since callers of this function in
    parsyfiles lib actually require them to be resolved already.

    :param typ_hint:
    :param allow_forward_refs:
    :return:
    """
    # most common case first, to be faster
    try:
        if isinstance(typ_hint, type):
            return True
    except:
        pass

    # optionally, check forward reference
    try:
        if allow_forward_refs and is_forward_ref(typ_hint):
            return True
    except:
        pass

    # finally check unions and typevars
    try:
        return is_union_type(typ_hint) or is_typevar(typ_hint)
    except:
        return False
def is_collection(object_type, strict: bool = False) -> bool:
    """
    Utility method to check if a type is a subclass of typing.{List,Dict,Set,Tuple}
    or of list, dict, set, tuple.

    If strict is set to True, the method will return True only if the class IS directly one of the base collection
    classes

    :param object_type:
    :param strict: if set to True, this method will look for a strict match.
    :return:
    """
    if object_type is None or object_type is Any or is_union_type(
            object_type) or is_typevar(object_type):
        return False
    elif strict:
        return object_type == dict \
               or object_type == list \
               or object_type == tuple \
               or object_type == set \
               or get_base_generic_type(object_type) == Dict \
               or get_base_generic_type(object_type) == List \
               or get_base_generic_type(object_type) == Set \
               or get_base_generic_type(object_type) == Tuple
    else:
        return issubclass(object_type, Dict) \
               or issubclass(object_type, List) \
               or issubclass(object_type, Set) \
               or issubclass(object_type, Tuple) \
               or issubclass(object_type, dict) \
               or issubclass(object_type, list) \
               or issubclass(object_type, tuple) \
               or issubclass(object_type, set)
Exemple #16
0
    def _check_type_get_basemodels(t: type) -> List[Type[BaseModel]]:
        """ Checks if collection type is subclass of BaseModel or Union of them, returns list of BaseModels involved.
        In future untyped collection or Colelction[dict] will be supported.
        :param t: Type of collection.
        :return: List of BaseModels, which collection can hold.
        :raise: TypeError if collection type is improper.
        """
        result = []
        if typing_inspect.is_union_type(t):
            for tt in typing_inspect.get_args(t):
                if not issubclass(tt, BaseModel):
                    raise TypeError(
                        f"Args of Union must be BaseModels, {t} not.")
                result.append(tt)
        else:
            try:
                if issubclass(t, BaseModel): result.append(t)
            except TypeError:
                pass

        from pymotyc import MotycModel
        for tt in [*result]:
            for parent in tt.__mro__:
                if parent in [MotycModel, BaseModel]: break
                if parent not in result: result.append(parent)

        if not result: raise TypeError(f"Improper type {t} of the Collection.")

        return result
Exemple #17
0
def _default_field_for_attribute(cls: type, attribute: attr.Attribute,
                                 tp: type, field_kwargs: Mapping[str, Any],
                                 field_for_attr: FIELD_FOR_ATTR) -> Field:
    origin = get_origin(tp)
    args = get_args(tp)

    if origin == list:
        return marshmallow.fields.List(
            field_for_attr(cls, attribute, args[0], {}), **field_kwargs)
    elif origin == dict:
        return marshmallow.fields.Dict(
            keys=field_for_attr(cls, attribute, args[0], {}),
            values=field_for_attr(cls, attribute, args[1], {}),
            **field_kwargs)
    elif is_union_type(tp):
        return field_for_attr(cls, attribute, args[0], field_kwargs)
    elif hasattr(tp, "Schema"):
        return NestedField(tp.Schema, **field_kwargs)
    # Self reference
    elif tp == cls or isinstance(tp, str) and tp == cls.__name__ \
            or isinstance(tp, ForwardRef) and tp.__forward_arg__ == cls.__name__:
        return NestedField("self", **field_kwargs)
    elif issubclass(tp, Enum):
        return EnumField(tp, **field_kwargs)
    elif issubclass(tp, PurePath):
        return PathField(tp, **field_kwargs)
    else:
        return _SIMPLE_TYPES.get(tp, Raw)(**field_kwargs)
Exemple #18
0
    def _all_subclasses(typ, *, module=None):
        """
        Return all subclasses of a given type.

        The type must be one of

         - :class:`GTScriptAstNode` (returns all subclasses of the given class)
         - :class:`Union` (return the subclasses of the united)
         - :class:`ForwardRef` (resolve the reference given the specified module and return its subclasses)
         - built-in python type: :class:`str`, :class:`int`, `type(None)` (return as is)
        """
        if inspect.isclass(typ) and issubclass(typ,
                                               gtscript_ast.GTScriptASTNode):
            result = {
                typ,
                *typ.__subclasses__(),
                *[
                    s for c in typ.__subclasses__()
                    for s in PyToGTScript._all_subclasses(c)
                    if not inspect.isabstract(c)
                ],
            }
            return result
        elif inspect.isclass(typ) and typ in [
                gtc.common.AssignmentKind,
                gtc.common.UnaryOperator,
                gtc.common.BinaryOperator,
        ]:
            # note: other types in gtc.common, e.g. gtc.common.DataType are not valid leaf nodes here as they
            #  map to symbols in the gtscript ast and are resolved there
            assert issubclass(typ, enum.Enum)
            return {typ}
        elif typing_inspect.is_union_type(typ):
            return {
                sub_cls
                for el_cls in typing_inspect.get_args(typ)
                for sub_cls in PyToGTScript._all_subclasses(el_cls,
                                                            module=module)
            }
        elif isinstance(typ, typing.ForwardRef):
            type_name = typing_inspect.get_forward_arg(typ)
            if not hasattr(module, type_name):
                raise ValueError(
                    f"Reference to type `{type_name}` in `ForwardRef` not found in module {module.__name__}"
                )
            return PyToGTScript._all_subclasses(getattr(module, type_name),
                                                module=module)
        elif typ in [
                type_definitions.StrictStr,
                type_definitions.StrictInt,
                type_definitions.StrictFloat,
                str,
                int,
                float,
                type(None),
        ]:  # TODO(tehrengruber): enhance
            return {typ}

        raise ValueError(f"Invalid field type {typ}")
Exemple #19
0
def _check_annotation(f_type, f_fullname, f_default):
    if typing_inspect.is_tuple_type(f_type):
        if f_default is not None:
            raise RuntimeError(f'invalid type annotation on {f_fullname}: '
                               f'default is defined for tuple type')

        f_default = tuple

    elif typing_inspect.is_union_type(f_type):
        for t in typing_inspect.get_args(f_type, evaluate=True):
            _check_annotation(t, f_fullname, f_default)

    elif typing_inspect.is_generic_type(f_type):
        if f_default is not None:
            raise RuntimeError(f'invalid type annotation on {f_fullname}: '
                               f'default is defined for container type '
                               f'{f_type!r}')

        ot = typing_inspect.get_origin(f_type)
        if ot is None:
            raise RuntimeError(
                f'cannot find origin of a generic type {f_type}')

        if ot in (list, List, collections.abc.Sequence):
            f_default = list
        elif ot in (set, Set):
            f_default = set
        elif ot in (frozenset, FrozenSet):
            f_default = frozenset
        elif ot in (dict, Dict):
            f_default = dict
        else:
            raise RuntimeError(f'invalid type annotation on {f_fullname}: '
                               f'{f_type!r} is not supported')

    elif f_type is not None:
        if f_type is Any:
            f_type = object

        if not isinstance(f_type, type):
            raise RuntimeError(f'invalid type annotation on {f_fullname}: '
                               f'{f_type!r} is not a type')

        if typeutils.is_container_type(f_type):
            if f_default is not None:
                raise RuntimeError(f'invalid type annotation on {f_fullname}: '
                                   f'default is defined for container type '
                                   f'{f_type!r}')
            # Make sure that we can actually construct an empty
            # version of this type before we decide it is the default.
            try:
                f_type()
            except TypeError:
                pass
            else:
                f_default = f_type

    return f_default
 def _is_direct_assignment_possible(self, a: Type[Any], b: Type[Any]) -> bool:
     b = self._resolve_forward_ref(b)
     if b is Any:
         return True
     elif is_union_type(b):
         return any([self._is_direct_assignment_possible(a, t) for t in get_args(b)])
     elif issubclass(a, b):
         return True
     return False
Exemple #21
0
def check_type(obj, tp):
    if is_union_type(tp):
        return any(check_type(obj, a) for a in tp.__args__)
    else:
        origin = get_origin(tp)
        if origin is None or origin == tp:
            return isinstance(obj, tp)
        else:
            return check_type(obj, origin)
Exemple #22
0
def decode_union(decoder, typ, json_value):
    if not inspect.is_union_type(typ):
        return Unsupported
    union_types = inspect.get_args(typ)
    for union_type in union_types:
        try:
            return decoder.decode(union_type, json_value)
        except JsonError:
            pass
    raise JsonError(f'Value {json_value} can not be deserialized as {typ}')
Exemple #23
0
    def _validate_generic_return(self, arg_type: Type, value: Any) -> None:
        """Validate List or Dict types.

        :note: we return any here because the calling function also returns any.
        """
        if issubclass(typing_inspect.get_origin(arg_type), list):
            if not isinstance(value, list):
                raise exceptions.ServerError(
                    f"Invalid return value, type needs to be a list. Argument type should be {arg_type}"
                )

            el_type = typing_inspect.get_args(arg_type, evaluate=True)[0]
            if el_type is Any:
                return
            for el in value:
                if typing_inspect.is_union_type(el_type):
                    self._validate_union_return(el_type, el)
                elif not isinstance(el, el_type):
                    raise exceptions.ServerError(f"Element {el} of returned list is not of type {el_type}.")

        elif issubclass(typing_inspect.get_origin(arg_type), dict):
            if not isinstance(value, dict):
                raise exceptions.ServerError(
                    f"Invalid return value, type needs to be a dict. Argument type should be {arg_type}"
                )

            el_type = typing_inspect.get_args(arg_type, evaluate=True)[1]
            if el_type is Any:
                return
            for k, v in value.items():
                if not isinstance(k, str):
                    raise exceptions.ServerError("Keys of return dict need to be strings.")

                if typing_inspect.is_union_type(el_type):
                    self._validate_union_return(el_type, v)
                elif not isinstance(v, el_type):
                    raise exceptions.ServerError(f"Element {v} of returned list is not of type {el_type}.")

        else:
            # This should not happen because of MethodProperties validation
            raise exceptions.BadRequest(
                f"Failed to validate generic type {arg_type} of return value, only List and Dict are supported"
            )
Exemple #24
0
def encode_union(encoder, typ, value):
    if not inspect.is_union_type(typ):
        return Unsupported
    union_types = inspect.get_args(typ)
    for union_type in union_types:
        try:
            return encoder.encode(value, union_type)
        except JsonError:
            pass
    raise JsonError(f'Value {value} can not be deserialized as {typ}')
def issubclass(cls, classinfo):
    if classinfo is dataclass:
        return False

    if classinfo is Union or is_union_type(cls):
        return classinfo is Union and is_union_type(cls)

    if original_isinstance(classinfo, GenericMeta):
        return (original_isinstance(cls, GenericMeta)
                and classinfo.__args__ is None
                and get_origin(cls) is classinfo)

    if original_isinstance(cls, GenericMeta):
        origin = get_origin(cls)
        if isinstance(origin, GenericMeta):
            origin = origin.__base__
        return origin is classinfo

    return original_issubclass(cls, classinfo)
Exemple #26
0
 def __call__(self, tp):
     if inspect.isclass(tp):
         return self.iter_mro(tp)
     if ti.is_optional_type(tp):
         return self.iter_optional(tp)
     if ti.is_tuple_type(tp):
         return self.iter_generic(tp)
     if ti.is_union_type(tp):
         return self.iter_generic(tp)
     if ti.is_generic_type(tp):
         return self.iter_generic(tp)
Exemple #27
0
 def get_args(cls) -> Tuple:
     if typing_inspect.is_union_type(cls):
         try:
             return cls.__union_params__
         except AttributeError:
             pass
         return cls.__args__
     elif issubclass(cls, List):
         return cls.__args__
     else:
         raise ValueError("Cannot get type arguments for {}".format(cls))
Exemple #28
0
def is_leq_informative_union(left, right):
    type_parameters_right = get_args(right)
    if is_union_type(left):
        type_parameters_left = get_args(left)
        return all(
            any(is_leq_informative(l, r) for r in type_parameters_right)
            for l in type_parameters_left)
    else:
        return any(
            is_leq_informative(left, parameter)
            for parameter in get_args(right))
Exemple #29
0
def is_type(type_):
    return (
        isinstance(type_, type) or
        type_ is Unknown or
        type_ is Any or
        is_parameterized(type_) or
        is_parametrical(type_) or
        is_typevar(type_) or
        is_union_type(type_)

    )
Exemple #30
0
 def select_concrete_type(self, select_from: Optional[Type]) -> Optional[Type]:
     """Select a concrete type from the given type.
     This is required e.g. when handling union types.
     Currently only unary types, Any and Union are handled."""
     if select_from == Any:
         return randomness.choice(self.get_all_generatable_types())
     if is_union_type(select_from):
         possible_types = get_args(select_from)
         if possible_types is not None and len(possible_types) > 0:
             return randomness.choice(possible_types)
         return None
     return select_from