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}
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))
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', ), )
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', )
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}
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')}
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'}
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]}
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'}
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}
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')}
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'}}
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'}}
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"}', ]
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}
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
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
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()
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}
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, }
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, }
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, }
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))
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
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, }