Exemplo n.º 1
0
def tests_should_deserialize_any():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test_any: Any

    typed_dict1 = as_typed_dict({'test_any': 0.1}, FakeTypedDict)
    any_object = object()
    typed_dict2 = as_typed_dict({'test_any': any_object}, FakeTypedDict)

    assert typed_dict1 == {'test_any': 0.1}
    assert typed_dict2 == {'test_any': any_object}
Exemplo n.º 2
0
        async def get(self, task_id: str, finished_task_cls: Type[Any]) -> Any:
            value = await self.data_source.get(self.build_key(task_id))

            if value:
                value = orjson.loads(value)

                if value['status'] == TaskStatusType.RUNNING.value:
                    return as_typed_dict(value, TaskInfo)

                if value['status'] == TaskStatusType.FINISHED.value or (
                        value['status'] == TaskStatusType.ERROR.value):
                    return as_typed_dict(value, finished_task_cls)

            raise KeyError(self.build_key(task_id))
Exemplo n.º 3
0
def as_request(
    request_cls: Type[Request],
    body: bytes,
    path_args: AsgiPathArgs = {},
    query_dict: AsgiQueryDict = {},
    headers: AsgiHeaders = [],
) -> Request:
    annotations = getattr(request_cls, '__annotations__', {})
    path_args_cls = annotations.get('path_args', PathArgs)
    query_cls = annotations.get('query', Query)
    headers_cls = annotations.get('headers', Headers)
    body_cls = annotations.get('body', Body)
    request_path_args = as_typed_dict(path_args, path_args_cls)
    request_query = get_query(query_cls, query_dict)
    request_headers = get_headers(headers_cls, headers)
    content_type = request_headers.get('content_type')
    parsed_body: Any = None

    if content_type is None or content_type is ContentType.APPLICATION_JSON:
        parsed_body = orjson.loads(body) if body else {}
        parsed_body = as_typed_dict_field(parsed_body, 'body', body_cls)
    else:
        parsed_body = body.decode()

    return asdataclass(  # type: ignore
        dict(
            path_args=request_path_args,
            query=request_query,
            headers=request_headers,
            body=parsed_body if parsed_body else None,
        ),
        request_cls,
        skip_fields=('body', ),
    )
Exemplo n.º 4
0
def tests_should_raise_error_when_deserializing_invalid_tuple_size():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test: str

    @jsondaora
    class FakeTypedDict2(TypedDict):
        fakes: Tuple[FakeTypedDict, int]
        fakeint: int

    fakes_data = [{'test': 'fake11'}, '1', None]

    with pytest.raises(DeserializationError) as exc_info:
        as_typed_dict({'fakes': fakes_data, 'fakeint': '1'}, FakeTypedDict2)

    assert exc_info.value.args == (
        f'Invalid type={Tuple[FakeTypedDict, int]} for field=fakes', )
Exemplo n.º 5
0
def tests_should_deserialize_union_args():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test_union: Union[int, str]

    typed_dict = as_typed_dict({'test_union': b'1'}, FakeTypedDict)

    assert typed_dict == {'test_union': 1}
Exemplo n.º 6
0
def tests_should_deserialize_tuple_args_limited():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test_tuple: Tuple[int, str]

    typed_dict_tuple = as_typed_dict({'test_tuple': [b'1', 2]}, FakeTypedDict)

    assert typed_dict_tuple == {'test_tuple': (1, '2')}
Exemplo n.º 7
0
def tests_should_deserialize_bytes_to_string():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test_union: str

    typed_dict = as_typed_dict({'test_union': b'test'}, FakeTypedDict)

    assert typed_dict == {'test_union': 'test'}
Exemplo n.º 8
0
def tests_should_deserialize_list_args():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test_list: List[int]

    typed_dict = as_typed_dict({'test_list': [b'1', '2', 3]}, FakeTypedDict)

    assert typed_dict == {'test_list': [1, 2, 3]}
Exemplo n.º 9
0
def tests_should_choose_fields_to_deserialize():
    @jsondaora(deserialize_fields=('test2',))
    class FakeTypedDict(TypedDict):
        test: int
        test2: str

    typed_dict = as_typed_dict({'test': '1', 'test2': 2}, FakeTypedDict)

    assert typed_dict == {'test': '1', 'test2': '2'}
Exemplo n.º 10
0
def tests_should_deserialize_optional_args():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test: str
        test_default: Optional[int] = None

    typed_dict = as_typed_dict(
        {'test': 'test', 'test_default': '1'}, FakeTypedDict
    )

    assert typed_dict == {'test': 'test', 'test_default': 1}
Exemplo n.º 11
0
def tests_should_deserialize_nested_typed_dict_dataclass():
    @jsondaora
    class FakeDataclass:
        test: str

    @jsondaora
    class FakeTypedDict(TypedDict):
        fake: FakeDataclass

    typed_dict = as_typed_dict({'fake': {'test': b'test'}}, FakeTypedDict)

    assert typed_dict == {'fake': FakeDataclass(test='test')}
Exemplo n.º 12
0
def tests_should_deserialize_nested_jsondict():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test: str

    @jsondaora
    class FakeTypedDict2(TypedDict):
        fake: FakeTypedDict

    typed_dict = as_typed_dict({'fake': {'test': b'test'}}, FakeTypedDict2)

    assert typed_dict == {'fake': {'test': 'test'}}
Exemplo n.º 13
0
def tests_should_deserialize_dict_args():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test_dict: Dict[int, str]

    typed_dict = as_typed_dict({'test_dict': {
        b'1': b'1',
        '2': '2',
        3: 3
    }}, FakeTypedDict)

    assert typed_dict == {'test_dict': {1: '1', 2: '2', 3: '3'}}
Exemplo n.º 14
0
def tests_should_serialize_all_fields_with_choosen_deserialize_fields():
    @jsondaora(deserialize_fields=('test2',))
    class FakeTypedDict(TypedDict):
        test: int
        test2: str

    typed_dict = as_typed_dict({'test': '1', 'test2': 2}, FakeTypedDict)

    assert typed_dict_asjson(typed_dict, FakeTypedDict) in [
        b'{"test":"1","test2":"2"}',
        b'{"test2":"2","test":"1"}',
    ]
Exemplo n.º 15
0
def tests_should_deserialize_set_args_nested():
    @jsondaora
    class FakeTypedDict2(TypedDict):
        fakes: Set[Tuple[int, str, float]]
        fakeint: int

    fakes_data = [[1, 2, 3]]
    typed_dict = as_typed_dict({
        'fakes': fakes_data,
        'fakeint': '1'
    }, FakeTypedDict2)

    assert typed_dict == {'fakes': {(1, '2', 3.0)}, 'fakeint': 1}
Exemplo n.º 16
0
def get_headers(cls: Type[Headers], headers: AsgiHeaders) -> Headers:
    jsondict = {}
    annotations = getattr(cls, '__annotations__', {})

    for key in annotations.keys():
        for key_h, value in headers:
            if key == key_h.decode().lower().replace('-', '_'):
                break
        else:
            continue

        jsondict[key] = value.decode()

    return as_typed_dict(jsondict, cls)  # type: ignore
Exemplo n.º 17
0
def get_query(cls: Type[Query], query_dict: AsgiQueryDict) -> Query:
    jsondict: Dict[str, Any] = {}
    annotations = getattr(cls, '__annotations__', {})

    for key in annotations.keys():
        values = query_dict.get(key)

        if values:
            jsondict[key] = (values[0]
                             if isinstance(values, Iterable) else values)
        else:
            jsondict[key] = values

    return as_typed_dict(jsondict, cls)  # type: ignore
Exemplo n.º 18
0
    async def set_calls(self, calls: Iterable[str]) -> None:
        data_source = await self.get_data_source()
        await data_source.delete(self._calls_key)
        await data_source.delete(self._script_key)

        for call_str in calls:
            if not call_str:
                continue

            try:
                calls_group = orjson.loads(call_str)

                if not isinstance(calls_group, list):
                    calls_group = [calls_group]

                for call in calls_group:
                    if 'method' not in call:
                        call['method'] = MethodType.GET.value

                calls_group = orjson.dumps(
                    [as_typed_dict(c, Call) for c in calls_group]
                )
                await data_source.rpush(self._calls_key, calls_group)

            except Exception:
                if call_str.startswith('http'):
                    try:
                        calls_group = orjson.dumps(
                            [
                                Call(
                                    url=call_str,
                                    method=MethodType.GET.value,
                                    headers={},
                                    body=None,
                                )
                            ]
                        )
                        await data_source.rpush(self._calls_key, calls_group)

                    except Exception as error:
                        logger.exception(error)
                        logger.warning(f'Invalid line {call_str}')

                else:
                    logger.warning(f'Invalid line {call_str}')

        data_source.close()
        await data_source.wait_closed()
Exemplo n.º 19
0
def tests_should_deserialize_list_args_nested():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test: str

    @jsondaora
    class FakeTypedDict2(TypedDict):
        fakes: List[FakeTypedDict]
        fakeint: int

    fakes_data = [{'test': 'fake11'}, {'test': 'fake12'}, {'test': 'fake13'}]
    typed_dict = as_typed_dict(
        {'fakes': fakes_data, 'fakeint': '1'}, FakeTypedDict2
    )

    assert typed_dict == {'fakes': fakes_data, 'fakeint': 1}
Exemplo n.º 20
0
def tests_should_deserialize_any_nested():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test: str

    @jsondaora
    class FakeTypedDict2(TypedDict):
        fakes: Set[Any]
        fakeint: int

    any_object = object()
    fakes_data = [any_object, 0.1]
    typed_dict = as_typed_dict({
        'fakes': fakes_data,
        'fakeint': '1'
    }, FakeTypedDict2)

    assert typed_dict == {
        'fakes': {any_object, 0.1},
        'fakeint': 1,
    }
Exemplo n.º 21
0
def tests_should_deserialize_tuple_args_nested_limited():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test: str

    @jsondaora
    class FakeTypedDict2(TypedDict):
        fakes: Tuple[FakeTypedDict, int]
        fakeint: int

    fakes_data = [{'test': 'fake11'}, '1']
    typed_dict = as_typed_dict({
        'fakes': fakes_data,
        'fakeint': '1'
    }, FakeTypedDict2)

    assert typed_dict == {
        'fakes': ({
            'test': 'fake11'
        }, 1),
        'fakeint': 1,
    }
Exemplo n.º 22
0
def tests_should_deserialize_list_args_nested_typed_dict_dataclass():
    @jsondaora
    class FakeDataclass:
        fakeint: int

    @jsondaora
    class FakeTypedDict(TypedDict):
        fakes: List[FakeDataclass]
        fakefloat: float

    fakes_data = [{'fakeint': '1'}, {'fakeint': '2'}, {'fakeint': '3'}]
    typed_dict = as_typed_dict({
        'fakes': fakes_data,
        'fakefloat': '0.1'
    }, FakeTypedDict)

    assert typed_dict == {
        'fakes': [FakeDataclass(1),
                  FakeDataclass(2),
                  FakeDataclass(3)],
        'fakefloat': 0.1,
    }
Exemplo n.º 23
0
def tests_should_deserialize_dict_args_nested():
    @jsondaora
    class FakeTypedDict(TypedDict):
        test: str

    @jsondaora
    class FakeTypedDict2(TypedDict):
        fakes: Dict[int, List[FakeTypedDict]]
        fakeint: int

    fakes_data = {
        b'1': [{
            'test': 'fake11'
        }, {
            'test': 'fake12'
        }, {
            'test': 'fake13'
        }]
    }
    typed_dict = as_typed_dict({
        'fakes': fakes_data,
        'fakeint': '1'
    }, FakeTypedDict2)

    assert typed_dict == FakeTypedDict2(
        {
            'fakes': {
                1: [{
                    'test': 'fake11'
                }, {
                    'test': 'fake12'
                }, {
                    'test': 'fake13'
                }]
            },
            'fakeint': 1,
        }, )

jsondict = dict(name='John', age=40, musics=[dict(name='Imagine')])
person = asdataclass(jsondict, Person)

print('dataclass:')
print(person)
print(dataclass_asjson(person))
print()

# TypedDict


@jsondaora(serialize_fields=('age'))
class Person(TypedDict):
    name: str
    age: int

    class Music(TypedDict):
        name: str

    musics: List[Music]


jsondict = dict(name=b'John', age='40', musics=[dict(name='Imagine')])
person = as_typed_dict(jsondict, Person)

print('TypedDict:')
print(person)
print(typed_dict_asjson(person, Person))
Exemplo n.º 25
0
    def parse_asgi_input(
        path_args: ASGIPathArgs,
        query_dict: ASGIQueryDict,
        headers: ASGIHeaders,
        body: ASGIBody,
        middlewares: Optional[Middlewares] = None,
    ) -> Tuple[Dict[str, Any], Optional[MiddlewareRequest]]:
        kwargs: Dict[str, Any]
        middleware_request: MiddlewareRequest

        if middlewares:
            middleware_request = MiddlewareRequest(path_pattern)

        if annotations_info.has_input:
            if annotations_info.has_path_args:
                kwargs = {
                    name: path_args.get(name)
                    for name in annotations_path_args.keys()
                }

                if middlewares:
                    middleware_request.path_args = {
                        name: deserialize_field(name, type_,
                                                path_args.get(name))
                        for name, type_ in annotations_path_args.items()
                    }

            else:
                kwargs = {}

            if annotations_info.has_query_dict:
                kwargs.update({
                    name: parse_query_args(name, type_, query_dict.get(name))
                    for name, type_ in annotations_query_dict.items()
                })

                if middlewares:
                    middleware_request.query_dict = {
                        name: deserialize_field(
                            name,
                            type_,
                            parse_query_args(name, type_,
                                             query_dict.get(name)),
                        )
                        for name, type_ in annotations_query_dict.items()
                        if name != 'body'
                    }

            if annotations_info.has_headers:
                headers_map = ControllerInput.__headers_name_map__
                headers_dict: Dict[str, Header] = {
                    name:
                    annotations_headers[name](h_value.decode())  # type: ignore
                    for h_name, h_value in headers
                    if (name := headers_map.get(h_name.decode()))  # noqa
                    in annotations_headers
                }
                kwargs.update(headers_dict)

                if middlewares:
                    middleware_request.headers = headers_dict.copy()

            if annotations_info.has_body:
                if isinstance(body_type, type) and issubclass(
                        body_type, GZipFactory):
                    kwargs['body'] = body_type(value=body)

                elif isinstance(body_type, type) and issubclass(
                        body_type, str):
                    kwargs['body'] = body.decode()

                else:
                    kwargs['body'] = make_json_request_body(body, body_type)

            if middlewares:
                middleware_request.body = (deserialize_field(
                    'body', body_type, kwargs['body'])
                                           if 'body' in kwargs else None)

                for middleware in middlewares.pre_execution:
                    middleware(middleware_request)

                return (
                    make_asgi_input_from_requst(middleware_request,
                                                ControllerInput),
                    middleware_request,
                )

            return (
                as_typed_dict(kwargs, ControllerInput),
                None,
            )

        if middlewares:
            for middleware in middlewares.pre_execution:
                middleware(middleware_request)

            return {}, middleware_request

        return {}, None
Exemplo n.º 26
0
def tests_should_deserialize_list_args_deep_nested_typed_dict_dataclass():
    @jsondaora
    class FakeDataclass2:
        fakeint: int

    @jsondaora
    class FakeTypedDict2(TypedDict):
        fakes: List[FakeDataclass2]
        fakefloat: float

    @jsondaora
    class FakeDataclass:
        fakeint: int
        fake: FakeTypedDict2

    @jsondaora
    class FakeTypedDict(TypedDict):
        fakes: List[FakeDataclass]
        fakefloat: float

    fakes_data = [
        {
            'fakeint': '1',
            'fake': {
                'fakefloat': '0.2',
                'fakes': [{
                    'fakeint': '-1'
                }]
            },
        },
        {
            'fakeint': '2',
            'fake': {
                'fakefloat': '0.3',
                'fakes': [{
                    'fakeint': '-2'
                }]
            },
        },
        {
            'fakeint': '3',
            'fake': {
                'fakefloat': '0.4',
                'fakes': [{
                    'fakeint': '0'
                }]
            },
        },
    ]
    typed_dict = as_typed_dict({
        'fakes': fakes_data,
        'fakefloat': '0.1'
    }, FakeTypedDict)

    assert typed_dict == {
        'fakes': [
            FakeDataclass(
                fakeint=1,
                fake={
                    'fakefloat': 0.2,
                    'fakes': [FakeDataclass2(fakeint=-1)]
                },
            ),
            FakeDataclass(
                fakeint=2,
                fake={
                    'fakefloat': 0.3,
                    'fakes': [FakeDataclass2(fakeint=-2)]
                },
            ),
            FakeDataclass(
                fakeint=3,
                fake={
                    'fakefloat': 0.4,
                    'fakes': [FakeDataclass2(fakeint=0)]
                },
            ),
        ],
        'fakefloat':
        0.1,
    }