jmux 0.0.3__py3-none-any.whl → 0.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jmux/demux.py +83 -64
- jmux/helpers.py +25 -11
- jmux/types.py +6 -1
- {jmux-0.0.3.dist-info → jmux-0.0.4.dist-info}/METADATA +1 -1
- jmux-0.0.4.dist-info/RECORD +13 -0
- jmux-0.0.3.dist-info/RECORD +0 -13
- {jmux-0.0.3.dist-info → jmux-0.0.4.dist-info}/WHEEL +0 -0
- {jmux-0.0.3.dist-info → jmux-0.0.4.dist-info}/licenses/LICENSE +0 -0
- {jmux-0.0.3.dist-info → jmux-0.0.4.dist-info}/top_level.txt +0 -0
jmux/demux.py
CHANGED
|
@@ -216,17 +216,11 @@ class JMux(ABC):
|
|
|
216
216
|
pydantic_main_type_set,
|
|
217
217
|
pydantic_subtype_set,
|
|
218
218
|
)
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
wrong_set = (
|
|
225
|
-
jmux_main_type_set if pydantic_wrong else pydantic_main_type_set
|
|
226
|
-
)
|
|
227
|
-
raise ForbiddenTypeHintsError(
|
|
228
|
-
message=(f"Forbidden typing received on {wrong_obj}: {wrong_set}"),
|
|
229
|
-
)
|
|
219
|
+
cls._assert_correct_set_combinations(
|
|
220
|
+
jmux_main_type_set,
|
|
221
|
+
pydantic_main_type_set,
|
|
222
|
+
pydantic_subtype_set,
|
|
223
|
+
)
|
|
230
224
|
|
|
231
225
|
if StreamableValues in jmux_main_type_set:
|
|
232
226
|
cls._assert_is_allowed_streamable_values(
|
|
@@ -252,6 +246,80 @@ class JMux(ABC):
|
|
|
252
246
|
message="Unexpected main type on JMux",
|
|
253
247
|
)
|
|
254
248
|
|
|
249
|
+
@classmethod
|
|
250
|
+
def _assert_correct_set_combinations(
|
|
251
|
+
cls,
|
|
252
|
+
jmux_main_type_set: Set[Type],
|
|
253
|
+
pydantic_main_type_set: Set[Type],
|
|
254
|
+
pydantic_subtype_set: Set[Type],
|
|
255
|
+
):
|
|
256
|
+
if (
|
|
257
|
+
pydantic_wrong := (
|
|
258
|
+
len(pydantic_main_type_set) != 1 and list not in pydantic_main_type_set
|
|
259
|
+
)
|
|
260
|
+
and len(pydantic_subtype_set) > 0
|
|
261
|
+
) or len(jmux_main_type_set) != 1:
|
|
262
|
+
wrong_obj = "pydantic" if pydantic_wrong else "JMux"
|
|
263
|
+
wrong_set = pydantic_main_type_set if pydantic_wrong else jmux_main_type_set
|
|
264
|
+
raise ForbiddenTypeHintsError(
|
|
265
|
+
message=(f"Forbidden typing received on {wrong_obj}: {wrong_set}"),
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
@classmethod
|
|
269
|
+
def _assert_only_allowed_types(
|
|
270
|
+
cls,
|
|
271
|
+
jmux_main_type_set: Set[Type],
|
|
272
|
+
jmux_subtype_set: Set[Type],
|
|
273
|
+
pydantic_main_type_set: Set[Type],
|
|
274
|
+
pydantic_subtype_set: Set[Type],
|
|
275
|
+
) -> None:
|
|
276
|
+
if not all(t in (AwaitableValue, StreamableValues) for t in jmux_main_type_set):
|
|
277
|
+
raise ForbiddenTypeHintsError(
|
|
278
|
+
message=(
|
|
279
|
+
"JMux must have either AwaitableValue or StreamableValues as "
|
|
280
|
+
f"main type, got {jmux_main_type_set}."
|
|
281
|
+
)
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
if not cls._all_elements_in_set_a_are_subclass_of_an_element_in_set_b(
|
|
285
|
+
set_a=jmux_subtype_set,
|
|
286
|
+
set_b={int, float, str, bool, NoneType, JMux, Enum},
|
|
287
|
+
):
|
|
288
|
+
raise ForbiddenTypeHintsError(
|
|
289
|
+
message=(
|
|
290
|
+
"JMux sub type must be one of the emittable types, got: "
|
|
291
|
+
f"{jmux_subtype_set}."
|
|
292
|
+
)
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
if not cls._all_elements_in_set_a_are_subclass_of_an_element_in_set_b(
|
|
296
|
+
set_a=pydantic_subtype_set,
|
|
297
|
+
set_b={int, float, str, bool, NoneType, BaseModel, Enum},
|
|
298
|
+
):
|
|
299
|
+
raise ForbiddenTypeHintsError(
|
|
300
|
+
message=(
|
|
301
|
+
"Pydantic sub type must be one of the primitive, enum or "
|
|
302
|
+
f"BaseModel, got: {pydantic_subtype_set}."
|
|
303
|
+
)
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
if not cls._all_elements_in_set_a_are_subclass_of_an_element_in_set_b(
|
|
307
|
+
set_a=pydantic_main_type_set,
|
|
308
|
+
set_b={int, float, str, bool, list, NoneType, BaseModel, Enum},
|
|
309
|
+
):
|
|
310
|
+
raise ForbiddenTypeHintsError(
|
|
311
|
+
message=(
|
|
312
|
+
"Pydantic main type must be one of the primitive, enum, list "
|
|
313
|
+
f"or BaseModel, got {pydantic_main_type_set}."
|
|
314
|
+
)
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
@classmethod
|
|
318
|
+
def _all_elements_in_set_a_are_subclass_of_an_element_in_set_b(
|
|
319
|
+
cls, set_a: Set[Type], set_b: Set[Type]
|
|
320
|
+
) -> bool:
|
|
321
|
+
return all(any(issubclass(elem, t) for t in set_b) for elem in set_a)
|
|
322
|
+
|
|
255
323
|
@classmethod
|
|
256
324
|
def _assert_is_allowed_streamable_values(
|
|
257
325
|
cls,
|
|
@@ -329,58 +397,6 @@ class JMux(ABC):
|
|
|
329
397
|
),
|
|
330
398
|
)
|
|
331
399
|
|
|
332
|
-
@classmethod
|
|
333
|
-
def _assert_only_allowed_types(
|
|
334
|
-
cls,
|
|
335
|
-
jmux_main_type_set: Set[Type],
|
|
336
|
-
jmux_subtype_set: Set[Type],
|
|
337
|
-
pydantic_main_type_set: Set[Type],
|
|
338
|
-
pydantic_subtype_set: Set[Type],
|
|
339
|
-
) -> None:
|
|
340
|
-
if not all(t in (AwaitableValue, StreamableValues) for t in jmux_main_type_set):
|
|
341
|
-
raise ForbiddenTypeHintsError(
|
|
342
|
-
message=(
|
|
343
|
-
"JMux must have either AwaitableValue or StreamableValues as "
|
|
344
|
-
f"main type, got {jmux_main_type_set}."
|
|
345
|
-
)
|
|
346
|
-
)
|
|
347
|
-
|
|
348
|
-
if not any(
|
|
349
|
-
issubclass(elem, t)
|
|
350
|
-
for t in (int, float, str, bool, NoneType, JMux, Enum)
|
|
351
|
-
for elem in jmux_subtype_set
|
|
352
|
-
):
|
|
353
|
-
raise ForbiddenTypeHintsError(
|
|
354
|
-
message=(
|
|
355
|
-
"JMux sub type must be one of the emittable types: "
|
|
356
|
-
f"{jmux_subtype_set}."
|
|
357
|
-
)
|
|
358
|
-
)
|
|
359
|
-
|
|
360
|
-
if len(pydantic_subtype_set) > 0 and not any(
|
|
361
|
-
issubclass(elem, t)
|
|
362
|
-
for t in (int, float, str, bool, NoneType, BaseModel, Enum)
|
|
363
|
-
for elem in pydantic_subtype_set
|
|
364
|
-
):
|
|
365
|
-
raise ForbiddenTypeHintsError(
|
|
366
|
-
message=(
|
|
367
|
-
"Pydantic sub type must be one of the primitive, enum or "
|
|
368
|
-
f"BaseModel, got: {pydantic_subtype_set}."
|
|
369
|
-
)
|
|
370
|
-
)
|
|
371
|
-
|
|
372
|
-
if not any(
|
|
373
|
-
issubclass(elem, t)
|
|
374
|
-
for t in (int, float, str, bool, list, NoneType, BaseModel, Enum)
|
|
375
|
-
for elem in pydantic_main_type_set
|
|
376
|
-
):
|
|
377
|
-
raise ForbiddenTypeHintsError(
|
|
378
|
-
message=(
|
|
379
|
-
"Pydantic main type must be one of the primitive, enum, list "
|
|
380
|
-
f"or BaseModel, got {pydantic_main_type_set}."
|
|
381
|
-
)
|
|
382
|
-
)
|
|
383
|
-
|
|
384
400
|
async def feed_chunks(self, chunks: str) -> None:
|
|
385
401
|
"""
|
|
386
402
|
Feeds a string of characters to the JMux parser.
|
|
@@ -556,7 +572,10 @@ class JMux(ABC):
|
|
|
556
572
|
await self._parse_primitive()
|
|
557
573
|
await self._sink.close()
|
|
558
574
|
self._decoder.reset()
|
|
559
|
-
|
|
575
|
+
if ch in JSON_WHITESPACE:
|
|
576
|
+
self._pda.set_state(S.EXPECT_COMMA_OR_EOC)
|
|
577
|
+
else:
|
|
578
|
+
self._pda.set_state(S.EXPECT_KEY)
|
|
560
579
|
if ch in OBJECT_CLOSE:
|
|
561
580
|
await self._finalize()
|
|
562
581
|
else:
|
jmux/helpers.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
from types import NoneType
|
|
2
|
-
from typing import Set, Tuple, Type,
|
|
1
|
+
from types import NoneType
|
|
2
|
+
from typing import Set, Tuple, Type, get_args, get_origin
|
|
3
3
|
|
|
4
4
|
from jmux.error import ParsePrimitiveError
|
|
5
|
+
from jmux.types import TYPES_LIKE_NONE, TYPES_LIKE_UNION
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
def str_to_bool(s: str) -> bool:
|
|
@@ -20,8 +21,17 @@ def extract_types_from_generic_alias(UnknownType: Type) -> Tuple[Set[Type], Set[
|
|
|
20
21
|
Origin: Type | None = get_origin(UnknownType)
|
|
21
22
|
if Origin is None:
|
|
22
23
|
return {UnknownType}, set()
|
|
23
|
-
if Origin
|
|
24
|
-
|
|
24
|
+
if Origin in TYPES_LIKE_UNION:
|
|
25
|
+
deconstructed = deconstruct_flat_type(UnknownType)
|
|
26
|
+
maybe_list_types = [
|
|
27
|
+
subtypes for subtypes in deconstructed if get_origin(subtypes) is list
|
|
28
|
+
]
|
|
29
|
+
if len(maybe_list_types) == 1:
|
|
30
|
+
list_based_type = maybe_list_types[0]
|
|
31
|
+
non_list_types = deconstructed - {list_based_type}
|
|
32
|
+
main_type, subtype = extract_types_from_generic_alias(list_based_type)
|
|
33
|
+
return non_list_types | main_type, subtype
|
|
34
|
+
return deconstructed, set()
|
|
25
35
|
|
|
26
36
|
type_args = get_args(UnknownType)
|
|
27
37
|
if len(type_args) != 1:
|
|
@@ -31,7 +41,7 @@ def extract_types_from_generic_alias(UnknownType: Type) -> Tuple[Set[Type], Set[
|
|
|
31
41
|
)
|
|
32
42
|
|
|
33
43
|
Generic: Type = type_args[0]
|
|
34
|
-
type_set =
|
|
44
|
+
type_set = deconstruct_flat_type(Generic)
|
|
35
45
|
if len(type_set) == 1:
|
|
36
46
|
return {Origin}, type_set
|
|
37
47
|
if len(type_set) != 2:
|
|
@@ -46,16 +56,20 @@ def extract_types_from_generic_alias(UnknownType: Type) -> Tuple[Set[Type], Set[
|
|
|
46
56
|
return {Origin}, type_set
|
|
47
57
|
|
|
48
58
|
|
|
49
|
-
def
|
|
59
|
+
def deconstruct_flat_type(UnknownType: Type) -> Set[Type]:
|
|
50
60
|
Origin: Type | None = get_origin(UnknownType)
|
|
51
|
-
if UnknownType
|
|
61
|
+
if UnknownType in TYPES_LIKE_NONE:
|
|
52
62
|
return {NoneType}
|
|
53
63
|
if Origin is None:
|
|
54
64
|
return {UnknownType}
|
|
55
|
-
if
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
if Origin in TYPES_LIKE_UNION:
|
|
66
|
+
type_args = get_args(UnknownType)
|
|
67
|
+
return set(type_args)
|
|
68
|
+
raise TypeError(
|
|
69
|
+
f"Unknown type {UnknownType} is not a Union or optional type, "
|
|
70
|
+
"only only those types and their syntactic sugar are supported "
|
|
71
|
+
"for flat deconstruction."
|
|
72
|
+
)
|
|
59
73
|
|
|
60
74
|
|
|
61
75
|
def get_main_type(type_set: Set[Type]) -> Type:
|
jmux/types.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
-
from
|
|
2
|
+
from types import NoneType, UnionType
|
|
3
|
+
from typing import List, Set, Union
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class State(Enum):
|
|
@@ -56,3 +57,7 @@ JSON_FALSE = "false"
|
|
|
56
57
|
JSON_TRUE = "true"
|
|
57
58
|
JSON_NULL = "null"
|
|
58
59
|
JSON_WHITESPACE = set(" \t\n\r")
|
|
60
|
+
|
|
61
|
+
TYPES_LIKE_UNION = {UnionType, Union}
|
|
62
|
+
TYPES_LIKE_NONE = {NoneType, None}
|
|
63
|
+
TYPES_LIKE_LIST = {List, list}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
jmux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
jmux/awaitable.py,sha256=gceBygIf3fAIWLsN1lWxsz9ExWNasDuk1WaGz8d9FAc,8427
|
|
3
|
+
jmux/decoder.py,sha256=Y6KVryRDLvGV5nBsneXpTvC0WUGhR5Z89Dvqz4HMAgg,1562
|
|
4
|
+
jmux/demux.py,sha256=g9DkMc9sLs31nuVwb7jbGZAjs0KulsKDGfOIM87NuWQ,36317
|
|
5
|
+
jmux/error.py,sha256=VZJYivt8RPfjcF2bs-T7_UkH3dVA3xH-xGbZggQV14k,4665
|
|
6
|
+
jmux/helpers.py,sha256=zOlw1Yk7-sdKAeasswRRcuUOTEBAUbymoAGwBTMaOjg,2902
|
|
7
|
+
jmux/pda.py,sha256=81gnh0eWGsgd_SrHkqjRQy_KkOSlBf5nor7pqKGgYjw,791
|
|
8
|
+
jmux/types.py,sha256=CJhFS9RVgR0cDBNJR8ROAFnxzG4YTYpNZ90hyD2SxsY,1389
|
|
9
|
+
jmux-0.0.4.dist-info/licenses/LICENSE,sha256=y0qnwaAe4bEqzNPyq4M_VZA2I2mQly8MawajyZhqw0k,1169
|
|
10
|
+
jmux-0.0.4.dist-info/METADATA,sha256=vVREVDZvfTC0KadGCOrw7RrSGxXdmZZNHJ8K-Zr3ZLM,13330
|
|
11
|
+
jmux-0.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
12
|
+
jmux-0.0.4.dist-info/top_level.txt,sha256=TF2N6kHqLghfOkCiNlCueMDX4l5rPn_5MSPNtYrS1-o,5
|
|
13
|
+
jmux-0.0.4.dist-info/RECORD,,
|
jmux-0.0.3.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
jmux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
jmux/awaitable.py,sha256=gceBygIf3fAIWLsN1lWxsz9ExWNasDuk1WaGz8d9FAc,8427
|
|
3
|
-
jmux/decoder.py,sha256=Y6KVryRDLvGV5nBsneXpTvC0WUGhR5Z89Dvqz4HMAgg,1562
|
|
4
|
-
jmux/demux.py,sha256=0dKIQibyDQkijuIcT53Za1L2DZbC_Ll0_1mhroqHg9I,35516
|
|
5
|
-
jmux/error.py,sha256=VZJYivt8RPfjcF2bs-T7_UkH3dVA3xH-xGbZggQV14k,4665
|
|
6
|
-
jmux/helpers.py,sha256=DQyPeuwx3AR65aHrET7xpSbfTLTC7ji3CyicyEhqJpk,2226
|
|
7
|
-
jmux/pda.py,sha256=81gnh0eWGsgd_SrHkqjRQy_KkOSlBf5nor7pqKGgYjw,791
|
|
8
|
-
jmux/types.py,sha256=5Ox01s-rGMQ1xGX8NRNBlyWtxvGKwnt9bjexXdESSYc,1233
|
|
9
|
-
jmux-0.0.3.dist-info/licenses/LICENSE,sha256=y0qnwaAe4bEqzNPyq4M_VZA2I2mQly8MawajyZhqw0k,1169
|
|
10
|
-
jmux-0.0.3.dist-info/METADATA,sha256=ZSi9Y5l5FsyaJuTW3N2K199mCNfkMe8_FLmxjIEfSAA,13330
|
|
11
|
-
jmux-0.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
12
|
-
jmux-0.0.3.dist-info/top_level.txt,sha256=TF2N6kHqLghfOkCiNlCueMDX4l5rPn_5MSPNtYrS1-o,5
|
|
13
|
-
jmux-0.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|