def dict_to_alfacase_schema(type_, block_indentation):
    key_type, value_type = (
        typing_inspect.get_last_args(type_)
        if sys.version_info.minor == 6
        else typing_inspect.get_args(type_)
    )
    return f"MapPattern(Str(), {_get_attr_value(value_type)})"
Esempio n. 2
0
def type_match(src_type, tgt_type):
    """
    Compares two type hints to see if they overlap.  This does not require exact matches if the target type

    type_match(

    """

    match = False
    if tgt_type == Any:
        match = True
    elif not issubclass(tgt_type.__class__, typing.GenericMeta):
        # if the target type is not a generic template, see if we have a subclass match
        match = issubclass(src_type, tgt_type)
    else:
        # check classes are the same
        match = src_type.__class__ == tgt_type.__class__

        if match:
            src_origin = typing_inspect.get_last_origin(src_type)
            tgt_origin = typing_inspect.get_last_origin(tgt_type)

            match = typing_inspect.get_origin(Union[src_origin,
                                                    tgt_origin]) != Union

    if not match:
        return False

    src_args = typing_inspect.get_last_args(src_type)
    tgt_args = typing_inspect.get_last_args(tgt_type)

    if len(tgt_args) == 0:
        return True

    if len(src_args) != len(tgt_args):
        return False

    for src_arg, tgt_arg in zip(src_args, tgt_args):
        if not type_match(src_arg, tgt_arg):
            return False

    return True
Esempio n. 3
0
 def test_last_args(self):
     T = TypeVar('T')
     S = TypeVar('S')
     self.assertEqual(get_last_args(int), ())
     self.assertEqual(get_last_args(Union), ())
     self.assertEqual(get_last_args(ClassVar[int]), (int,))
     self.assertEqual(get_last_args(Union[T, int]), (T, int))
     self.assertEqual(get_last_args(Iterable[Tuple[T, S]][int, T]), (int, T))
     self.assertEqual(get_last_args(Callable[[T, S], int]), (T, S, int))
     self.assertEqual(get_last_args(Callable[[], int]), (int,))
Esempio n. 4
0
def auto_any(cls) -> schema.Schema:
    if inspect.isclass(cls):
        if issubclass(cls, bool):
            return schema.BooleanSchema()
        elif issubclass(cls, float):
            return schema.NumberSchema()
        elif issubclass(cls, int):
            return schema.IntSchema()
        elif issubclass(cls, str):
            return schema.StringSchema()
        elif issubclass(cls, datetime):
            return schema.StringSchema(format='date-time')
        elif issubclass(cls, date):
            return schema.StringSchema(format='date')
        elif issubclass(cls, timedelta):
            return schema.NumberSchema(format='double')
        elif issubclass(cls, List):
            vt, = get_args(cls)

            subschema = auto_any(vt)

            return schema.ArraySchema(items=subschema)
        elif issubclass(cls, Dict):
            kt, vt = get_args(cls)

            if not issubclass(kt, str):
                raise NotImplementedError(('class3', cls, kt))

            subschema = auto_any(vt)

            return ObjectSchema(additional=subschema, )
        elif is_dataclass(cls):
            return auto_dataclass(cls)
        else:
            raise NotImplementedError(('class2', cls))
    else:
        if is_optional_type(cls):
            item, _ = get_last_args(cls)

            trc('1').debug('%s %s', item, _)
            r = auto_any(item)

            if isinstance(r, schema.Nullable):
                r.nullable = True
            else:
                raise NotImplementedError('can not be nullable')

            trc('2').debug('%s', r)
            return r
        else:
            raise NotImplementedError(('class', cls))
Esempio n. 5
0
def dict_to_alfacase_schema(type_: type, indent: int) -> str:
    key_type, value_type = (typing_inspect.get_last_args(type_)
                            if sys.version_info.minor == 6 else
                            typing_inspect.get_args(type_))
    body_indent = indent + 1
    value_schema = _get_attr_value(value_type, indent=body_indent)
    if "\n" in value_schema:
        lines = [
            "MapPattern(",
            f"{INDENTANTION * body_indent}Str(),",
            f"{INDENTANTION * body_indent}{value_schema},",
            f"{INDENTANTION * indent})",
        ]
        return "\n".join(lines)
    else:
        return f"MapPattern(Str(), {value_schema})"
Esempio n. 6
0
 def test_last_args(self):
     T = TypeVar('T')
     S = TypeVar('S')
     self.assertEqual(get_last_args(int), ())
     self.assertEqual(get_last_args(Union), ())
     if WITH_CLASSVAR:
         self.assertEqual(get_last_args(ClassVar[int]), (int,))
     self.assertEqual(get_last_args(Union[T, int]), (T, int))
     self.assertEqual(get_last_args(Union[str, int]), (str, int))
     self.assertEqual(get_last_args(Tuple[T, int]), (T, int))
     self.assertEqual(get_last_args(Tuple[str, int]), (str, int))
     self.assertEqual(get_last_args(Generic[T]), (T, ))
     if GENERIC_TUPLE_PARAMETRIZABLE:
         tp = Iterable[Tuple[T, S]][int, T]
         self.assertEqual(get_last_args(tp), (int, T))
     if LEGACY_TYPING:
         self.assertEqual(get_last_args(Callable[[T, S], int]), (T, S))
         self.assertEqual(get_last_args(Callable[[], int]), ())
     else:
         self.assertEqual(get_last_args(Callable[[T, S], int]), (T, S, int))
         self.assertEqual(get_last_args(Callable[[], int]), (int,))
Esempio n. 7
0
 def get_args(self, xtype):
     return typing_inspect.get_last_args(xtype)
Esempio n. 8
0
    def resolve(self, cls: Type) -> Fac:
        """get a factory given an object cls"""

        # todo this needs to go, and we need to have proper instances of each separate `cls` mapper
        #

        def resolve_list(cls):
            vt, = get_args(cls)

            value = self.resolve(vt)

            if self.name.startswith('json'):
                return JsonAnyList(value)
            else:
                raise NotImplementedError(f'{self.name}')

        def resolve_dict(cls):
            kt, vt = get_args(cls)

            if self.name == 'json_into':
                assert issubclass(kt, str), (kt, )

            key = self.resolve(kt)
            value = self.resolve(vt)

            if self.name.startswith('json'):
                return JsonAnyDict(key, value)
            else:
                raise NotImplementedError(f'{self.name}')

        if isinstance(cls, DeferredWrapper):
            cls = cls.type
            assert is_dataclass(cls), cls
            r: List[Fac] = []

            for item in fields(cls):
                item: Field

                item_type = item.metadata.get(FIELD_OVERRIDE, item.type)
                item_factory = item.metadata.get(FIELD_FACTORY, {})

                if isinstance(item_factory, Fac):
                    pass
                elif isinstance(item_factory, dict):
                    item_factory = item_factory.get(self.name, MISSING)
                else:
                    assert False, repr(item_factory)

                if item_factory is MISSING:
                    item_factory = self.resolve(item_type)

                is_optional = item.default is not MISSING
                # todo support optional

                if self.name == 'json_from':
                    r.append(
                        AnyAnyField(item.name,
                                    AnyAnyItem(item.name, item_factory)))
                elif self.name == 'json_into':
                    r.append(
                        AnyAnyField(item.name,
                                    AnyAnyAttr(item.name, item_factory)))
                else:
                    raise NotImplementedError((self.name, None))

            if self.name == 'json_from':
                return AnyFromStruct(r, cls)
            elif self.name == 'json_into':
                return AnyIntoStruct(
                    r,
                    cls,
                )
            else:
                raise NotImplementedError((self.name, None))
        elif isinstance(cls, Args):
            dx: CallableSerializers = getattr(cls.type, DECL_CALLABLE_ATTR)
            return dx.parameters[self.name]
        elif isinstance(cls, Return):
            dx: CallableSerializers = getattr(cls.type, DECL_CALLABLE_ATTR)
            return dx.return_[self.name]
        elif is_serializable(cls):
            return Ref(self.name, cls.__module__ + '.' + cls.__name__)
        elif inspect.isclass(cls):
            if issubclass(cls, bool):
                return This(bool)
            elif issubclass(cls, float):
                return This(float)
            elif issubclass(cls, int):
                return This(int)
            elif issubclass(cls, str):
                return This(str)
            elif issubclass(cls, datetime):
                if self.name == 'json_from':
                    return JsonFromDateTime()
                elif self.name == 'json_into':
                    return JsonIntoDateTime()
                else:
                    raise NotImplementedError(f'{self.name}')
            elif issubclass(cls, timedelta):
                if self.name == 'json_from':
                    return JsonFromTimeDelta()
                elif self.name == 'json_into':
                    return JsonIntoTimeDelta()
                else:
                    raise NotImplementedError(f'{self.name}')
            elif issubclass(cls, List):
                return resolve_list(cls)
            elif issubclass(cls, Dict):
                return resolve_dict(cls)
            elif issubclass(cls, Enum):
                clss = set(item.value.__class__ for item in cls)

                assert len(clss) == 1, clss

                t = clss.pop()

                fac = self.resolve(t)

                if self.name == 'json_from':
                    return AnyFromEnum(cls, fac)
                elif self.name == 'json_into':
                    return AnyIntoEnum(cls, fac)
                else:
                    raise NotImplementedError(('class4', cls))
            elif is_dataclass(cls):
                return Ref(self.name, cls.__module__ + '.' + cls.__name__)
            else:
                raise NotImplementedError(('class2', cls))
        elif isinstance(cls, ForwardRef):
            if sys.version_info >= (3, 7):
                t = cls._evaluate(self.globals, self.locals)
            else:
                t = cls._eval_type(self.globals, self.locals)
            return self.resolve(t)
        elif isinstance(cls, str):
            code = compile(cls, '<string>', 'eval')
            t = eval(code, self.globals, self.locals)
            return self.resolve(t)
        else:
            if is_optional_type(cls):
                if sys.version_info >= (3, 7):
                    item, _ = get_args(cls)
                else:
                    item, _ = get_last_args(cls)

                value = self.resolve(item)

                if self.name.startswith('json'):
                    return JsonAnyOptional(value)
                else:
                    raise NotImplementedError(f'{self.name}')
            elif sys.version_info >= (3, 7) and hasattr(cls, '__origin__'):
                if cls.__origin__ is list:
                    return resolve_list(cls)
                elif cls.__origin__ is dict:
                    return resolve_dict(cls)
            else:
                raise NotImplementedError(('class', cls, cls.__class__))