soia-client 1.0.10__tar.gz → 1.0.12__tar.gz

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.
Files changed (34) hide show
  1. {soia_client-1.0.10 → soia_client-1.0.12}/PKG-INFO +1 -1
  2. {soia_client-1.0.10 → soia_client-1.0.12}/pyproject.toml +1 -1
  3. {soia_client-1.0.10 → soia_client-1.0.12}/soia_client.egg-info/PKG-INFO +1 -1
  4. {soia_client-1.0.10 → soia_client-1.0.12}/soia_client.egg-info/SOURCES.txt +4 -0
  5. soia_client-1.0.12/soialib/_.py +3 -0
  6. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/__init__.py +2 -0
  7. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/impl/arrays.py +20 -1
  8. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/impl/enums.py +34 -2
  9. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/impl/optionals.py +13 -0
  10. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/impl/primitives.py +62 -0
  11. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/impl/structs.py +33 -1
  12. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/impl/type_adapter.py +8 -0
  13. soia_client-1.0.12/soialib/reflection.py +343 -0
  14. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/serializer.py +12 -0
  15. soia_client-1.0.12/soialib/service.py +147 -0
  16. soia_client-1.0.12/soialib/service_client.py +68 -0
  17. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/spec.py +0 -2
  18. {soia_client-1.0.10 → soia_client-1.0.12}/tests/test_module_initializer.py +254 -4
  19. {soia_client-1.0.10 → soia_client-1.0.12}/tests/test_serializers.py +12 -0
  20. {soia_client-1.0.10 → soia_client-1.0.12}/LICENSE +0 -0
  21. {soia_client-1.0.10 → soia_client-1.0.12}/README +0 -0
  22. {soia_client-1.0.10 → soia_client-1.0.12}/setup.cfg +0 -0
  23. {soia_client-1.0.10 → soia_client-1.0.12}/soia_client.egg-info/dependency_links.txt +0 -0
  24. {soia_client-1.0.10 → soia_client-1.0.12}/soia_client.egg-info/top_level.txt +0 -0
  25. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/impl/__init__.py +0 -0
  26. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/impl/function_maker.py +0 -0
  27. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/impl/repr.py +0 -0
  28. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/keyed_items.py +0 -0
  29. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/method.py +0 -0
  30. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/module_initializer.py +0 -0
  31. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/never.py +0 -0
  32. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/serializers.py +0 -0
  33. {soia_client-1.0.10 → soia_client-1.0.12}/soialib/timestamp.py +0 -0
  34. {soia_client-1.0.10 → soia_client-1.0.12}/tests/test_timestamp.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: soia-client
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Author-email: Tyler Fibonacci <gepheum@gmail.com>
5
5
  License: MIT License
6
6
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "soia-client"
7
- version = "1.0.10"
7
+ version = "1.0.12"
8
8
  description = ""
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Tyler Fibonacci", email = "gepheum@gmail.com" }]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: soia-client
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Author-email: Tyler Fibonacci <gepheum@gmail.com>
5
5
  License: MIT License
6
6
 
@@ -5,13 +5,17 @@ soia_client.egg-info/PKG-INFO
5
5
  soia_client.egg-info/SOURCES.txt
6
6
  soia_client.egg-info/dependency_links.txt
7
7
  soia_client.egg-info/top_level.txt
8
+ soialib/_.py
8
9
  soialib/__init__.py
9
10
  soialib/keyed_items.py
10
11
  soialib/method.py
11
12
  soialib/module_initializer.py
12
13
  soialib/never.py
14
+ soialib/reflection.py
13
15
  soialib/serializer.py
14
16
  soialib/serializers.py
17
+ soialib/service.py
18
+ soialib/service_client.py
15
19
  soialib/spec.py
16
20
  soialib/timestamp.py
17
21
  soialib/impl/__init__.py
@@ -0,0 +1,3 @@
1
+ from typing import Any, Final
2
+
3
+ _: Final[Any] = None
@@ -6,12 +6,14 @@ from soialib.serializers import (
6
6
  optional_serializer,
7
7
  primitive_serializer,
8
8
  )
9
+ from soialib.service_client import ServiceClient
9
10
  from soialib.timestamp import Timestamp
10
11
 
11
12
  __all__ = [
12
13
  "KeyedItems",
13
14
  "Method",
14
15
  "Serializer",
16
+ "ServiceClient",
15
17
  "Timestamp",
16
18
  "array_serializer",
17
19
  "optional_serializer",
@@ -3,6 +3,7 @@ from dataclasses import FrozenInstanceError
3
3
  from typing import Generic, Optional
4
4
  from weakref import WeakValueDictionary
5
5
 
6
+ import soialib.reflection
6
7
  from soialib import spec
7
8
  from soialib.impl.function_maker import Any, Expr, ExprLike, Line, make_function
8
9
  from soialib.impl.type_adapter import TypeAdapter
@@ -18,7 +19,7 @@ def get_array_adapter(
18
19
  listuple_class = _new_keyed_items_class(key_attributes, default_expr)
19
20
  else:
20
21
  listuple_class = _new_listuple_class()
21
- array_adapter = _ArrayAdapter(item_adapter, listuple_class)
22
+ array_adapter = _ArrayAdapter(item_adapter, listuple_class, key_attributes)
22
23
  return _item_to_array_adapter.setdefault(
23
24
  (item_adapter, key_attributes), array_adapter
24
25
  )
@@ -28,6 +29,7 @@ class _ArrayAdapter(TypeAdapter):
28
29
  __slots__ = (
29
30
  "item_adapter",
30
31
  "listuple_class",
32
+ "key_attributes",
31
33
  "empty_listuple",
32
34
  )
33
35
 
@@ -39,9 +41,11 @@ class _ArrayAdapter(TypeAdapter):
39
41
  self,
40
42
  item_adapter: TypeAdapter,
41
43
  listuple_class: type,
44
+ key_attributes: tuple[str, ...],
42
45
  ):
43
46
  self.item_adapter = item_adapter
44
47
  self.listuple_class = listuple_class
48
+ self.key_attributes = key_attributes
45
49
  self.empty_listuple = listuple_class()
46
50
 
47
51
  def default_expr(self) -> ExprLike:
@@ -104,6 +108,21 @@ class _ArrayAdapter(TypeAdapter):
104
108
  ) -> None:
105
109
  self.item_adapter.finalize(resolve_type_fn)
106
110
 
111
+ def get_type(self) -> soialib.reflection.Type:
112
+ return soialib.reflection.ArrayType(
113
+ kind="array",
114
+ value=soialib.reflection.ArrayType.Array(
115
+ item=self.item_adapter.get_type(),
116
+ key_chain=self.key_attributes,
117
+ ),
118
+ )
119
+
120
+ def register_records(
121
+ self,
122
+ registry: dict[str, soialib.reflection.Record],
123
+ ) -> None:
124
+ self.item_adapter.register_records(registry)
125
+
107
126
 
108
127
  _ItemAndKeyAttributes = tuple[TypeAdapter, tuple[str, ...]]
109
128
  _ItemToArrayAdapter = WeakValueDictionary[_ItemAndKeyAttributes, _ArrayAdapter]
@@ -3,6 +3,7 @@ from collections.abc import Callable, Sequence
3
3
  from dataclasses import FrozenInstanceError, dataclass
4
4
  from typing import Any, Final, Union
5
5
 
6
+ import soialib.reflection
6
7
  from soialib import spec as _spec
7
8
  from soialib.impl.function_maker import BodyBuilder, Expr, ExprLike, Line, make_function
8
9
  from soialib.impl.repr import repr_impl
@@ -15,6 +16,7 @@ class EnumAdapter(TypeAdapter):
15
16
  "gen_class",
16
17
  "private_is_enum_attr",
17
18
  "finalization_state",
19
+ "value_fields",
18
20
  )
19
21
 
20
22
  spec: Final[_spec.Enum]
@@ -22,6 +24,7 @@ class EnumAdapter(TypeAdapter):
22
24
  private_is_enum_attr: Final[str]
23
25
  # 0: has not started; 1: in progress; 2: done
24
26
  finalization_state: int
27
+ value_fields: tuple["_ValueField", ...]
25
28
 
26
29
  def __init__(self, spec: _spec.Enum):
27
30
  self.finalization_state = 0
@@ -51,10 +54,10 @@ class EnumAdapter(TypeAdapter):
51
54
  base_class = self.gen_class
52
55
 
53
56
  # Resolve the type of every value field.
54
- value_fields = [
57
+ self.value_fields = value_fields = tuple(
55
58
  _make_value_field(f, resolve_type_fn(f.type), base_class)
56
59
  for f in self.spec.value_fields
57
- ]
60
+ )
58
61
 
59
62
  # Aim to have dependencies finalized *before* the dependent. It's not always
60
63
  # possible, because there can be cyclic dependencies.
@@ -116,6 +119,35 @@ class EnumAdapter(TypeAdapter):
116
119
  Expr.local("_cls?", self.gen_class), f".{fn_name}(", json_expr, ")"
117
120
  )
118
121
 
122
+ def get_type(self) -> soialib.reflection.Type:
123
+ return soialib.reflection.RecordType(
124
+ kind="record",
125
+ value=self.spec.id,
126
+ )
127
+
128
+ def register_records(
129
+ self,
130
+ registry: dict[str, soialib.reflection.Record],
131
+ ) -> None:
132
+ record_id = self.spec.id
133
+ if record_id in registry:
134
+ return
135
+ registry[record_id] = soialib.reflection.Record(
136
+ kind="enum",
137
+ id=record_id,
138
+ fields=tuple(
139
+ soialib.reflection.Field(
140
+ name=field.spec.name,
141
+ number=field.spec.number,
142
+ type=field.field_type.get_type(),
143
+ )
144
+ for field in self.value_fields
145
+ ),
146
+ removed_fields=self.spec.removed_numbers,
147
+ )
148
+ for field in self.value_fields:
149
+ field.field_type.register_records(registry)
150
+
119
151
 
120
152
  def _make_base_class(spec: _spec.Enum) -> type:
121
153
  record_hash = hash(spec.id)
@@ -3,6 +3,7 @@ from dataclasses import dataclass
3
3
  from typing import TypeVar
4
4
  from weakref import WeakValueDictionary
5
5
 
6
+ import soialib.reflection
6
7
  from soialib import spec
7
8
  from soialib.impl.function_maker import Expr, ExprLike
8
9
  from soialib.impl.type_adapter import TypeAdapter
@@ -67,6 +68,18 @@ class _OptionalAdapter(TypeAdapter):
67
68
  ) -> None:
68
69
  self.other_adapter.finalize(resolve_type_fn)
69
70
 
71
+ def get_type(self) -> soialib.reflection.Type:
72
+ return soialib.reflection.OptionalType(
73
+ kind="optional",
74
+ value=self.other_adapter.get_type(),
75
+ )
76
+
77
+ def register_records(
78
+ self,
79
+ registry: dict[str, soialib.reflection.Record],
80
+ ) -> None:
81
+ self.other_adapter.register_records(registry)
82
+
70
83
 
71
84
  _other_adapter_to_optional_adapter: WeakValueDictionary[TypeAdapter, TypeAdapter] = (
72
85
  WeakValueDictionary()
@@ -2,6 +2,7 @@ from collections.abc import Callable
2
2
  from dataclasses import dataclass
3
3
  from typing import Any, Final, final
4
4
 
5
+ import soialib.reflection
5
6
  from soialib import spec
6
7
  from soialib.impl.function_maker import Expr, ExprLike
7
8
  from soialib.impl.type_adapter import TypeAdapter
@@ -16,6 +17,13 @@ class AbstractPrimitiveAdapter(TypeAdapter):
16
17
  ) -> None:
17
18
  pass
18
19
 
20
+ @final
21
+ def register_records(
22
+ self,
23
+ records: dict[str, soialib.reflection.Record],
24
+ ) -> None:
25
+ pass
26
+
19
27
 
20
28
  class _BoolAdapter(AbstractPrimitiveAdapter):
21
29
  def default_expr(self) -> ExprLike:
@@ -40,6 +48,12 @@ class _BoolAdapter(AbstractPrimitiveAdapter):
40
48
  def from_json_expr(self, json_expr: ExprLike) -> Expr:
41
49
  return Expr.join("(True if ", json_expr, " else False)")
42
50
 
51
+ def get_type(self) -> soialib.reflection.Type:
52
+ return soialib.reflection.PrimitiveType(
53
+ kind="primitive",
54
+ value="bool",
55
+ )
56
+
43
57
 
44
58
  BOOL_ADAPTER: Final[TypeAdapter] = _BoolAdapter()
45
59
 
@@ -80,6 +94,12 @@ class _Int32Adapter(_AbstractIntAdapter):
80
94
  " < 2147483647 else 2147483647)",
81
95
  )
82
96
 
97
+ def get_type(self) -> soialib.reflection.Type:
98
+ return soialib.reflection.PrimitiveType(
99
+ kind="primitive",
100
+ value="int32",
101
+ )
102
+
83
103
 
84
104
  def _int64_to_json(i: int) -> int | str:
85
105
  if i < -9007199254740991: # min safe integer in JavaScript
@@ -100,6 +120,12 @@ class _Int64Adapter(_AbstractIntAdapter):
100
120
  def to_json_expr(self, in_expr: ExprLike, readable: bool) -> Expr:
101
121
  return Expr.join(Expr.local("int64_to_json", _int64_to_json), "(", in_expr, ")")
102
122
 
123
+ def get_type(self) -> soialib.reflection.Type:
124
+ return soialib.reflection.PrimitiveType(
125
+ kind="primitive",
126
+ value="int64",
127
+ )
128
+
103
129
 
104
130
  def _uint64_to_json(i: int) -> int | str:
105
131
  if i <= 0:
@@ -119,6 +145,12 @@ class _Uint64Adapter(_AbstractIntAdapter):
119
145
  Expr.local("uint64_to_json", _uint64_to_json), "(", in_expr, ")"
120
146
  )
121
147
 
148
+ def get_type(self) -> soialib.reflection.Type:
149
+ return soialib.reflection.PrimitiveType(
150
+ kind="primitive",
151
+ value="uint64",
152
+ )
153
+
122
154
 
123
155
  INT32_ADAPTER: Final[TypeAdapter] = _Int32Adapter()
124
156
  INT64_ADAPTER: Final[TypeAdapter] = _Int64Adapter()
@@ -149,11 +181,23 @@ class _AbstractFloatAdapter(AbstractPrimitiveAdapter):
149
181
  class _Float32Adapter(_AbstractFloatAdapter):
150
182
  """Type adapter implementation for float32."""
151
183
 
184
+ def get_type(self) -> soialib.reflection.Type:
185
+ return soialib.reflection.PrimitiveType(
186
+ kind="primitive",
187
+ value="float32",
188
+ )
189
+
152
190
 
153
191
  @dataclass(frozen=True)
154
192
  class _Float64Adapter(_AbstractFloatAdapter):
155
193
  """Type adapter implementation for float32."""
156
194
 
195
+ def get_type(self) -> soialib.reflection.Type:
196
+ return soialib.reflection.PrimitiveType(
197
+ kind="primitive",
198
+ value="float64",
199
+ )
200
+
157
201
 
158
202
  FLOAT32_ADAPTER: Final[TypeAdapter] = _Float32Adapter()
159
203
  FLOAT64_ADAPTER: Final[TypeAdapter] = _Float64Adapter()
@@ -192,6 +236,12 @@ class _TimestampAdapter(AbstractPrimitiveAdapter):
192
236
  fn = Expr.local("_timestamp_from_json", _timestamp_from_json)
193
237
  return Expr.join(fn, "(", json_expr, ")")
194
238
 
239
+ def get_type(self) -> soialib.reflection.Type:
240
+ return soialib.reflection.PrimitiveType(
241
+ kind="primitive",
242
+ value="timestamp",
243
+ )
244
+
195
245
 
196
246
  def _timestamp_from_json(json: Any) -> Timestamp:
197
247
  if json.__class__ is int or isinstance(json, int):
@@ -219,6 +269,12 @@ class _StringAdapter(AbstractPrimitiveAdapter):
219
269
  def from_json_expr(self, json_expr: ExprLike) -> Expr:
220
270
  return Expr.join("('' + (", json_expr, " or ''))")
221
271
 
272
+ def get_type(self) -> soialib.reflection.Type:
273
+ return soialib.reflection.PrimitiveType(
274
+ kind="primitive",
275
+ value="string",
276
+ )
277
+
222
278
 
223
279
  STRING_ADAPTER: Final[TypeAdapter] = _StringAdapter()
224
280
 
@@ -247,5 +303,11 @@ class _BytesAdapter(AbstractPrimitiveAdapter):
247
303
  Expr.local("fromhex", _BytesAdapter._fromhex_fn), "(", json_expr, ' or "")'
248
304
  )
249
305
 
306
+ def get_type(self) -> soialib.reflection.Type:
307
+ return soialib.reflection.PrimitiveType(
308
+ kind="primitive",
309
+ value="bytes",
310
+ )
311
+
250
312
 
251
313
  BYTES_ADAPTER: Final[TypeAdapter] = _BytesAdapter()
@@ -3,6 +3,7 @@ from collections.abc import Callable, Sequence
3
3
  from dataclasses import FrozenInstanceError, dataclass
4
4
  from typing import Any, Final, Union, cast
5
5
 
6
+ import soialib.reflection
6
7
  from soialib import spec as _spec
7
8
  from soialib.impl.function_maker import (
8
9
  BodyBuilder,
@@ -28,6 +29,7 @@ class StructAdapter(TypeAdapter):
28
29
  "simple_class",
29
30
  "private_is_frozen_attr",
30
31
  "finalization_state",
32
+ "fields",
31
33
  )
32
34
 
33
35
  spec: Final[_spec.Struct]
@@ -40,6 +42,7 @@ class StructAdapter(TypeAdapter):
40
42
 
41
43
  # 0: has not started; 1: in progress; 2: done
42
44
  finalization_state: int
45
+ fields: tuple["_Field", ...]
43
46
 
44
47
  def __init__(self, spec: _spec.Struct):
45
48
  self.finalization_state = 0
@@ -90,7 +93,7 @@ class StructAdapter(TypeAdapter):
90
93
  self.finalization_state = 1
91
94
 
92
95
  # Resolve the type of every field.
93
- fields = tuple(
96
+ self.fields = fields = tuple(
94
97
  sorted(
95
98
  (_Field(f, resolve_type_fn(f.type)) for f in self.spec.fields),
96
99
  key=lambda f: f.field.number,
@@ -198,6 +201,35 @@ class StructAdapter(TypeAdapter):
198
201
  Expr.local("_cls?", self.gen_class), f".{fn_name}(", json_expr, ")"
199
202
  )
200
203
 
204
+ def get_type(self) -> soialib.reflection.Type:
205
+ return soialib.reflection.RecordType(
206
+ kind="record",
207
+ value=self.spec.id,
208
+ )
209
+
210
+ def register_records(
211
+ self,
212
+ registry: dict[str, soialib.reflection.Record],
213
+ ) -> None:
214
+ record_id = self.spec.id
215
+ if record_id in registry:
216
+ return
217
+ registry[record_id] = soialib.reflection.Record(
218
+ kind="struct",
219
+ id=record_id,
220
+ fields=tuple(
221
+ soialib.reflection.Field(
222
+ name=field.field.name,
223
+ number=field.field.number,
224
+ type=field.type.get_type(),
225
+ )
226
+ for field in self.fields
227
+ ),
228
+ removed_fields=self.spec.removed_numbers,
229
+ )
230
+ for field in self.fields:
231
+ field.type.register_records(registry)
232
+
201
233
 
202
234
  class _Frozen:
203
235
  def __setattr__(self, name: str, value: Any):
@@ -1,6 +1,7 @@
1
1
  from collections.abc import Callable
2
2
  from typing import Protocol
3
3
 
4
+ import soialib.reflection
4
5
  from soialib import spec
5
6
  from soialib.impl.function_maker import ExprLike
6
7
 
@@ -53,3 +54,10 @@ class TypeAdapter(Protocol):
53
54
  self,
54
55
  resolve_type_fn: Callable[[spec.Type], "TypeAdapter"],
55
56
  ) -> None: ...
57
+
58
+ def get_type(self) -> soialib.reflection.Type: ...
59
+
60
+ def register_records(
61
+ self,
62
+ registry: dict[str, soialib.reflection.Record],
63
+ ) -> None: ...