soia-client 1.0.4__py3-none-any.whl → 1.0.6__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.6
4
4
  Author-email: Tyler Fibonacci <gepheum@gmail.com>
5
5
  License: MIT License
6
6
 
@@ -0,0 +1,24 @@
1
+ soialib/__init__.py,sha256=h_ENkLJEdrh1mGhCoKgIadDasSulW3zK9_qhEsTviXY,429
2
+ soialib/keyed_items.py,sha256=q7MCn82obf-0jh7FcAhuw4eh9-wtuHIpkEFcSfc8EaY,338
3
+ soialib/method.py,sha256=2qWG4jMqYhS3hA8y8YDu3iqzhXA_AKebpB38RWNmsYQ,452
4
+ soialib/module_initializer.py,sha256=dDdYtlWlN7kEWlxuI0lguPsI-7zXAShswjw9j-_-AWY,4229
5
+ soialib/never.py,sha256=bYU63XyNX4e2wOUXQHhHWGO-an4IFr9_ur1ut6GmGN0,47
6
+ soialib/serializer.py,sha256=2R1BYEvpG3eDYMFXSKljPTMweOiuu8OMq7Xf1Bv2Wsk,3008
7
+ soialib/serializers.py,sha256=7zmCdtaUkuy1vIGP1OBn06x8FryYep15bujrFoeGw9A,2572
8
+ soialib/spec.py,sha256=w-eMMUqOchOlCJaXppyAa2JpSBrMo9lrMvqz8VaEX4I,3699
9
+ soialib/timestamp.py,sha256=6VNKAJs7EwxBm3tEEk1Cy1FhAD6lSNdlB3K2Sg6QHIA,4065
10
+ soialib/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ soialib/impl/arrays.py,sha256=NOKIfD3tvYnWycVk00aaf4m5Nx4_G5sVxdh2cwu4-l0,4902
12
+ soialib/impl/encoding.py,sha256=8k2j0nhGloFIBUEZLiiHANwhopusaQcDRePPS4sUhPc,1413
13
+ soialib/impl/enums.py,sha256=o3KylHoh66jcb1TUHeOorjaxHPoqHkbk7PXR5hKldrI,14121
14
+ soialib/impl/function_maker.py,sha256=PYqHqnZf8nELfEnRcoyyUbPAHyr99ROHhmHGj9ldB6U,5684
15
+ soialib/impl/optionals.py,sha256=QUcxx0i7oAQl7IcnxKyNW11xi7fbs2hmuSP1pfrTSTY,2120
16
+ soialib/impl/primitives.py,sha256=X_ywRmVZI_Q5tatb1Qil6Xvdyh1J4ElfI-LOCn671Zk,5975
17
+ soialib/impl/repr.py,sha256=z-_jGNKuY__DfwQKW40xzZFf_eG6wGMJvuY_2hJrETA,1441
18
+ soialib/impl/structs.py,sha256=jF-R89-k1lQKWjClhOPVIkJTKQcFyuF92DiVCWCB5dI,24018
19
+ soialib/impl/type_adapter.py,sha256=IP3jF3wPgwKhWd7LKMmbbv1qUTv1HBAyMdpVrIg0_S0,2063
20
+ soia_client-1.0.6.dist-info/LICENSE,sha256=SaAftKkX6hfSOiPdENQPS70tifH3PDHgazq8eK2Pwfw,1064
21
+ soia_client-1.0.6.dist-info/METADATA,sha256=TkXFJzFY6v1MNEAP_pMEs93vxJuTneiP2ytY7D2W4P4,1645
22
+ soia_client-1.0.6.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
23
+ soia_client-1.0.6.dist-info/top_level.txt,sha256=2vPmAo5G0SrCxYrNdJKJJVdpalYppgjO2mmz2PtsFUI,8
24
+ soia_client-1.0.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.2.0)
2
+ Generator: setuptools (75.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
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/impl/structs.py CHANGED
@@ -146,7 +146,7 @@ class StructAdapter(TypeAdapter):
146
146
  )
147
147
 
148
148
  # Initialize DEFAULT.
149
- self.gen_class.DEFAULT.__init__()
149
+ _init_default(self.gen_class.DEFAULT, fields)
150
150
 
151
151
  # Define mutable getters
152
152
  for field in fields:
@@ -674,6 +674,18 @@ def _adjust_array_len_expr(var: str, removed_numbers: tuple[int, ...]) -> str:
674
674
  return ret
675
675
 
676
676
 
677
+ def _init_default(default: Any, fields: Sequence[_Field]) -> None:
678
+ for field in fields:
679
+ attribute = field.field.attribute
680
+ get_field_default = make_function(
681
+ name="get_default",
682
+ params=(),
683
+ body=(Line.join("return ", field.type.default_expr()),),
684
+ )
685
+ object.__setattr__(default, attribute, get_field_default())
686
+ object.__setattr__(default, "_array_len", 0)
687
+
688
+
677
689
  def _make_mutable_getter(field: _Field) -> Callable[[Any], Any]:
678
690
  # Two cases: the field either has struct type or array type.
679
691
  attribute = field.field.attribute
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
@@ -1,22 +0,0 @@
1
- soialib/__init__.py,sha256=5sEAu3ATaiMVbXE_8yb6Ikd5-ilj21tQ8zoQ2Uh2pBM,178
2
- soialib/keyed_items.py,sha256=q7MCn82obf-0jh7FcAhuw4eh9-wtuHIpkEFcSfc8EaY,338
3
- soialib/module_initializer.py,sha256=d2Y-u1Jddva9-v25Yc4xlX7ifaMXoO4WurF1r6QxBaU,3289
4
- 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
7
- soialib/timestamp.py,sha256=6VNKAJs7EwxBm3tEEk1Cy1FhAD6lSNdlB3K2Sg6QHIA,4065
8
- soialib/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- soialib/impl/arrays.py,sha256=YFDT5WG4Lpmbt0d5-9_dML8kIL9AS3LfJvlA0tr5J4A,4970
10
- soialib/impl/encoding.py,sha256=8k2j0nhGloFIBUEZLiiHANwhopusaQcDRePPS4sUhPc,1413
11
- soialib/impl/enums.py,sha256=o3KylHoh66jcb1TUHeOorjaxHPoqHkbk7PXR5hKldrI,14121
12
- soialib/impl/function_maker.py,sha256=PYqHqnZf8nELfEnRcoyyUbPAHyr99ROHhmHGj9ldB6U,5684
13
- soialib/impl/optionals.py,sha256=8ImqyGbQPsOQd0155Irytzzza-t4b2qH4Swk78HZD8Q,2114
14
- soialib/impl/primitives.py,sha256=X_ywRmVZI_Q5tatb1Qil6Xvdyh1J4ElfI-LOCn671Zk,5975
15
- soialib/impl/repr.py,sha256=z-_jGNKuY__DfwQKW40xzZFf_eG6wGMJvuY_2hJrETA,1441
16
- soialib/impl/structs.py,sha256=pXPn6SeyZH-FwQXbvUG_uoc5DZ8oZgDQ5v_jx8Uf5aY,23576
17
- 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,,