soia-client 1.0.4__py3-none-any.whl → 1.0.5__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.

Potentially problematic release.


This version of soia-client might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: soia-client
3
- Version: 1.0.4
3
+ Version: 1.0.5
4
4
  Author-email: Tyler Fibonacci <gepheum@gmail.com>
5
5
  License: MIT License
6
6
 
@@ -1,22 +1,24 @@
1
- soialib/__init__.py,sha256=5sEAu3ATaiMVbXE_8yb6Ikd5-ilj21tQ8zoQ2Uh2pBM,178
1
+ soialib/__init__.py,sha256=h_ENkLJEdrh1mGhCoKgIadDasSulW3zK9_qhEsTviXY,429
2
2
  soialib/keyed_items.py,sha256=q7MCn82obf-0jh7FcAhuw4eh9-wtuHIpkEFcSfc8EaY,338
3
- soialib/module_initializer.py,sha256=d2Y-u1Jddva9-v25Yc4xlX7ifaMXoO4WurF1r6QxBaU,3289
3
+ soialib/method.py,sha256=2qWG4jMqYhS3hA8y8YDu3iqzhXA_AKebpB38RWNmsYQ,452
4
+ soialib/module_initializer.py,sha256=dDdYtlWlN7kEWlxuI0lguPsI-7zXAShswjw9j-_-AWY,4229
4
5
  soialib/never.py,sha256=bYU63XyNX4e2wOUXQHhHWGO-an4IFr9_ur1ut6GmGN0,47
5
- soialib/serializer.py,sha256=quFXOYjj7sjfjQIVZPa0NPvKtO4LmYrRtNeFlZy_Aio,2599
6
- soialib/spec.py,sha256=eUw9iISeQd-utq2Rl_FTnXKXpawg7piWkFL92FfQCik,3440
6
+ soialib/serializer.py,sha256=2R1BYEvpG3eDYMFXSKljPTMweOiuu8OMq7Xf1Bv2Wsk,3008
7
+ soialib/serializers.py,sha256=7zmCdtaUkuy1vIGP1OBn06x8FryYep15bujrFoeGw9A,2572
8
+ soialib/spec.py,sha256=w-eMMUqOchOlCJaXppyAa2JpSBrMo9lrMvqz8VaEX4I,3699
7
9
  soialib/timestamp.py,sha256=6VNKAJs7EwxBm3tEEk1Cy1FhAD6lSNdlB3K2Sg6QHIA,4065
8
10
  soialib/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- soialib/impl/arrays.py,sha256=YFDT5WG4Lpmbt0d5-9_dML8kIL9AS3LfJvlA0tr5J4A,4970
11
+ soialib/impl/arrays.py,sha256=NOKIfD3tvYnWycVk00aaf4m5Nx4_G5sVxdh2cwu4-l0,4902
10
12
  soialib/impl/encoding.py,sha256=8k2j0nhGloFIBUEZLiiHANwhopusaQcDRePPS4sUhPc,1413
11
13
  soialib/impl/enums.py,sha256=o3KylHoh66jcb1TUHeOorjaxHPoqHkbk7PXR5hKldrI,14121
12
14
  soialib/impl/function_maker.py,sha256=PYqHqnZf8nELfEnRcoyyUbPAHyr99ROHhmHGj9ldB6U,5684
13
- soialib/impl/optionals.py,sha256=8ImqyGbQPsOQd0155Irytzzza-t4b2qH4Swk78HZD8Q,2114
15
+ soialib/impl/optionals.py,sha256=QUcxx0i7oAQl7IcnxKyNW11xi7fbs2hmuSP1pfrTSTY,2120
14
16
  soialib/impl/primitives.py,sha256=X_ywRmVZI_Q5tatb1Qil6Xvdyh1J4ElfI-LOCn671Zk,5975
15
17
  soialib/impl/repr.py,sha256=z-_jGNKuY__DfwQKW40xzZFf_eG6wGMJvuY_2hJrETA,1441
16
18
  soialib/impl/structs.py,sha256=pXPn6SeyZH-FwQXbvUG_uoc5DZ8oZgDQ5v_jx8Uf5aY,23576
17
19
  soialib/impl/type_adapter.py,sha256=IP3jF3wPgwKhWd7LKMmbbv1qUTv1HBAyMdpVrIg0_S0,2063
18
- soia_client-1.0.4.dist-info/LICENSE,sha256=SaAftKkX6hfSOiPdENQPS70tifH3PDHgazq8eK2Pwfw,1064
19
- soia_client-1.0.4.dist-info/METADATA,sha256=DN8YpGeiXalIL0SpGElb6ByIoWQZC6gbbUFoNU1X3oc,1645
20
- soia_client-1.0.4.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
21
- soia_client-1.0.4.dist-info/top_level.txt,sha256=2vPmAo5G0SrCxYrNdJKJJVdpalYppgjO2mmz2PtsFUI,8
22
- soia_client-1.0.4.dist-info/RECORD,,
20
+ soia_client-1.0.5.dist-info/LICENSE,sha256=SaAftKkX6hfSOiPdENQPS70tifH3PDHgazq8eK2Pwfw,1064
21
+ soia_client-1.0.5.dist-info/METADATA,sha256=JWD4wSPRLd1uz_nCM37-Y2DAKnf_5gO-QcHye3hYmMw,1645
22
+ soia_client-1.0.5.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
23
+ soia_client-1.0.5.dist-info/top_level.txt,sha256=2vPmAo5G0SrCxYrNdJKJJVdpalYppgjO2mmz2PtsFUI,8
24
+ soia_client-1.0.5.dist-info/RECORD,,
soialib/__init__.py CHANGED
@@ -1,5 +1,19 @@
1
1
  from soialib.keyed_items import KeyedItems
2
+ from soialib.method import Method
2
3
  from soialib.serializer import Serializer
4
+ from soialib.serializers import (
5
+ array_serializer,
6
+ optional_serializer,
7
+ primitive_serializer,
8
+ )
3
9
  from soialib.timestamp import Timestamp
4
10
 
5
- __all__ = ["KeyedItems", "Serializer", "Timestamp"]
11
+ __all__ = [
12
+ "KeyedItems",
13
+ "Method",
14
+ "Serializer",
15
+ "Timestamp",
16
+ "array_serializer",
17
+ "optional_serializer",
18
+ "primitive_serializer",
19
+ ]
soialib/impl/arrays.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from collections.abc import Callable
2
2
  from dataclasses import FrozenInstanceError
3
3
  from typing import Generic, Optional
4
- from weakref import WeakKeyDictionary
4
+ from weakref import WeakValueDictionary
5
5
 
6
6
  from soialib import spec
7
7
  from soialib.impl.function_maker import Any, Expr, ExprLike, Line, make_function
@@ -19,8 +19,9 @@ def get_array_adapter(
19
19
  else:
20
20
  listuple_class = _new_listuple_class()
21
21
  array_adapter = _ArrayAdapter(item_adapter, listuple_class)
22
- key_spec_to_array_adapter = _item_to_array_adapters.setdefault(item_adapter, {})
23
- return key_spec_to_array_adapter.setdefault(key_attributes, array_adapter)
22
+ return _item_to_array_adapter.setdefault(
23
+ (item_adapter, key_attributes), array_adapter
24
+ )
24
25
 
25
26
 
26
27
  class _ArrayAdapter(TypeAdapter):
@@ -107,10 +108,10 @@ class _ArrayAdapter(TypeAdapter):
107
108
  self.item_adapter.finalize(resolve_type_fn)
108
109
 
109
110
 
110
- _KeyAttributesToArrayAdapter = dict[tuple[str, ...], _ArrayAdapter]
111
- _ItemToArrayAdapters = WeakKeyDictionary[TypeAdapter, _KeyAttributesToArrayAdapter]
111
+ _ItemAndKeyAttributes = tuple[TypeAdapter, tuple[str, ...]]
112
+ _ItemToArrayAdapter = WeakValueDictionary[_ItemAndKeyAttributes, _ArrayAdapter]
112
113
 
113
- _item_to_array_adapters: _ItemToArrayAdapters = WeakKeyDictionary()
114
+ _item_to_array_adapter: _ItemToArrayAdapter = WeakValueDictionary()
114
115
 
115
116
 
116
117
  def _new_listuple_class() -> type:
soialib/impl/optionals.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from collections.abc import Callable
2
2
  from dataclasses import dataclass
3
3
  from typing import TypeVar
4
- from weakref import WeakKeyDictionary
4
+ from weakref import WeakValueDictionary
5
5
 
6
6
  from soialib import spec
7
7
  from soialib.impl.encoding import NULL_WIRE
@@ -69,6 +69,6 @@ class _OptionalAdapter(TypeAdapter):
69
69
  self.other_adapter.finalize(resolve_type_fn)
70
70
 
71
71
 
72
- _other_adapter_to_optional_adapter: WeakKeyDictionary[TypeAdapter, TypeAdapter] = (
73
- WeakKeyDictionary()
72
+ _other_adapter_to_optional_adapter: WeakValueDictionary[TypeAdapter, TypeAdapter] = (
73
+ WeakValueDictionary()
74
74
  )
soialib/method.py ADDED
@@ -0,0 +1,17 @@
1
+ from dataclasses import dataclass
2
+ from typing import Generic, TypeVar
3
+
4
+ from soialib.serializer import Serializer
5
+
6
+ Request = TypeVar("Request")
7
+ Response = TypeVar("Response")
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class Method(Generic[Request, Response]):
12
+ """Identifies a procedure (the "P" in "RPC") on both client side and server side."""
13
+
14
+ name: str
15
+ number: int
16
+ request_serializer: Serializer[Request]
17
+ response_serializer: Serializer[Response]
@@ -1,6 +1,6 @@
1
1
  from typing import Any, Union
2
2
 
3
- from soialib import spec
3
+ from soialib import method, spec
4
4
  from soialib.impl import arrays, enums, optionals, primitives, structs
5
5
  from soialib.impl.type_adapter import TypeAdapter
6
6
  from soialib.serializer import make_serializer
@@ -11,8 +11,10 @@ RecordAdapter = Union[structs.StructAdapter, enums.EnumAdapter]
11
11
  _record_id_to_adapter: dict[str, RecordAdapter] = {}
12
12
 
13
13
 
14
- def init_module_classes(
14
+ def init_module(
15
15
  records: tuple[spec.Record, ...],
16
+ methods: tuple[spec.Method, ...],
17
+ constants: tuple[spec.Constant, ...],
16
18
  globals: dict[str, Any],
17
19
  # For testing
18
20
  record_id_to_adapter: dict[str, RecordAdapter] = _record_id_to_adapter,
@@ -77,3 +79,22 @@ def init_module_classes(
77
79
  gen_class._parent_class = None
78
80
  # TODO: comment
79
81
  gen_class.SERIALIZER = make_serializer(adapter)
82
+
83
+ # Now that al the classes have been initialized, create the methods.
84
+ for method_spec in methods:
85
+ var_name = method_spec._var_name or method_spec.name
86
+ request_serializer = make_serializer(resolve_type(method_spec.request_type))
87
+ response_serializer = make_serializer(resolve_type(method_spec.response_type))
88
+ globals[var_name] = method.Method(
89
+ name=method_spec.name,
90
+ number=method_spec.number,
91
+ request_serializer=request_serializer,
92
+ response_serializer=response_serializer,
93
+ )
94
+ del var_name, request_serializer, response_serializer
95
+
96
+ # Create the constants.
97
+ for constant in constants:
98
+ serializer = make_serializer(resolve_type(constant.type))
99
+ globals[constant.name] = serializer.from_json_code(constant.json_code)
100
+ del serializer
soialib/serializer.py CHANGED
@@ -2,6 +2,7 @@ import json as jsonlib
2
2
  from collections.abc import Callable
3
3
  from dataclasses import FrozenInstanceError
4
4
  from typing import Any, Generic, TypeVar, cast, final
5
+ from weakref import WeakValueDictionary
5
6
 
6
7
  from soialib.impl.function_maker import Expr, LineSpan, make_function
7
8
  from soialib.impl.type_adapter import TypeAdapter
@@ -13,17 +14,21 @@ T = TypeVar("T")
13
14
  @final
14
15
  class Serializer(Generic[T]):
15
16
  __slots__ = (
17
+ "__weakref__",
18
+ "_adapter",
16
19
  "_to_dense_json_fn",
17
20
  "_to_readable_json_fn",
18
21
  "_from_json_fn",
19
22
  )
20
23
 
24
+ _adapter: TypeAdapter
21
25
  _to_dense_json_fn: Callable[[T], Any]
22
26
  _to_readable_json_fn: Callable[[T], Any]
23
27
  _from_json_fn: Callable[[Any], T]
24
28
 
25
29
  def __init__(self, adapter: Never):
26
30
  # Use Never (^) as a trick to make the constructor internal.
31
+ object.__setattr__(self, "_adapter", adapter)
27
32
  object.__setattr__(
28
33
  self, "_to_dense_json_fn", _make_to_json_fn(adapter, readable=False)
29
34
  )
@@ -56,8 +61,16 @@ class Serializer(Generic[T]):
56
61
  raise FrozenInstanceError(self.__class__.__qualname__)
57
62
 
58
63
 
64
+ # A cache to make sure we only create one Serializer for each TypeAdapter.
65
+ _type_adapter_to_serializer: WeakValueDictionary[TypeAdapter, Serializer] = (
66
+ WeakValueDictionary()
67
+ )
68
+
69
+
59
70
  def make_serializer(adapter: TypeAdapter) -> Serializer:
60
- return Serializer(cast(Never, adapter))
71
+ return _type_adapter_to_serializer.setdefault(
72
+ adapter, Serializer(cast(Never, adapter))
73
+ )
61
74
 
62
75
 
63
76
  def _make_to_json_fn(adapter: TypeAdapter, readable: bool) -> Callable[[Any], Any]:
soialib/serializers.py ADDED
@@ -0,0 +1,74 @@
1
+ from typing import Final, Literal, Optional, TypeVar, overload
2
+
3
+ from soialib.impl import primitives
4
+ from soialib.impl.arrays import get_array_adapter
5
+ from soialib.impl.optionals import get_optional_adapter
6
+ from soialib.serializer import Serializer, make_serializer
7
+ from soialib.timestamp import Timestamp
8
+
9
+ Item = TypeVar("Item")
10
+ Other = TypeVar("Other")
11
+
12
+
13
+ def array_serializer(item_serializer: Serializer[Item]) -> Serializer[tuple[Item, ...]]:
14
+ return make_serializer(get_array_adapter(item_serializer._adapter, ()))
15
+
16
+
17
+ def optional_serializer(
18
+ other_serializer: Serializer[Other],
19
+ ) -> Serializer[Other | None]:
20
+ return make_serializer(get_optional_adapter(other_serializer._adapter))
21
+
22
+
23
+ @overload
24
+ def primitive_serializer(primitive: Literal["bool"]) -> Serializer[bool]: ...
25
+ @overload
26
+ def primitive_serializer(primitive: Literal["int32"]) -> Serializer[int]: ...
27
+ @overload
28
+ def primitive_serializer(primitive: Literal["int64"]) -> Serializer[int]: ...
29
+ @overload
30
+ def primitive_serializer(primitive: Literal["uint64"]) -> Serializer[int]: ...
31
+ @overload
32
+ def primitive_serializer(primitive: Literal["float32"]) -> Serializer[float]: ...
33
+ @overload
34
+ def primitive_serializer(primitive: Literal["float64"]) -> Serializer[float]: ...
35
+ @overload
36
+ def primitive_serializer(primitive: Literal["timestamp"]) -> Serializer[Timestamp]: ...
37
+ @overload
38
+ def primitive_serializer(primitive: Literal["string"]) -> Serializer[str]: ...
39
+ @overload
40
+ def primitive_serializer(primitive: Literal["bytes"]) -> Serializer[bytes]: ...
41
+ def primitive_serializer(
42
+ primitive: (
43
+ Literal["bool"]
44
+ | Literal["int32"]
45
+ | Literal["int64"]
46
+ | Literal["uint64"]
47
+ | Literal["float32"]
48
+ | Literal["float64"]
49
+ | Literal["timestamp"]
50
+ | Literal["string"]
51
+ | Literal["bytes"]
52
+ ),
53
+ ) -> (
54
+ Serializer[bool]
55
+ | Serializer[int]
56
+ | Serializer[float]
57
+ | Serializer[Timestamp]
58
+ | Serializer[str]
59
+ | Serializer[bytes]
60
+ ):
61
+ return _PRIMITIVE_TO_SERIALIZER[primitive]
62
+
63
+
64
+ _PRIMITIVE_TO_SERIALIZER: Final = {
65
+ "bool": make_serializer(primitives.BOOL_ADAPTER),
66
+ "int32": make_serializer(primitives.INT32_ADAPTER),
67
+ "int64": make_serializer(primitives.INT64_ADAPTER),
68
+ "uint64": make_serializer(primitives.UINT64_ADAPTER),
69
+ "float32": make_serializer(primitives.FLOAT32_ADAPTER),
70
+ "float64": make_serializer(primitives.FLOAT64_ADAPTER),
71
+ "timestamp": make_serializer(primitives.TIMESTAMP_ADAPTER),
72
+ "string": make_serializer(primitives.STRING_ADAPTER),
73
+ "bytes": make_serializer(primitives.BYTES_ADAPTER),
74
+ }
soialib/spec.py CHANGED
@@ -141,3 +141,19 @@ class RecordId:
141
141
  qualname=parent_qualname,
142
142
  name_parts=parent_name_parts,
143
143
  )
144
+
145
+
146
+ @dataclass(frozen=True)
147
+ class Method:
148
+ name: str
149
+ number: int
150
+ request_type: Type
151
+ response_type: Type
152
+ _var_name: str = "" # If different from 'name'
153
+
154
+
155
+ @dataclass(frozen=True)
156
+ class Constant:
157
+ name: str
158
+ type: Type
159
+ json_code: str