tsrkit-types 0.1.0__py3-none-any.whl → 0.1.1__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.
- tsrkit_types/choice.py +8 -3
- tsrkit_types/dictionary.py +3 -2
- tsrkit_types/struct.py +6 -2
- {tsrkit_types-0.1.0.dist-info → tsrkit_types-0.1.1.dist-info}/METADATA +39 -49
- {tsrkit_types-0.1.0.dist-info → tsrkit_types-0.1.1.dist-info}/RECORD +8 -8
- {tsrkit_types-0.1.0.dist-info → tsrkit_types-0.1.1.dist-info}/WHEEL +0 -0
- {tsrkit_types-0.1.0.dist-info → tsrkit_types-0.1.1.dist-info}/licenses/LICENSE +0 -0
- {tsrkit_types-0.1.0.dist-info → tsrkit_types-0.1.1.dist-info}/top_level.txt +0 -0
tsrkit_types/choice.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
from typing import ClassVar, Optional, Union, Tuple, Any
|
|
2
|
-
from typing_extensions import get_args
|
|
1
|
+
from typing import ClassVar, Optional, Union, Tuple, Any
|
|
3
2
|
|
|
4
3
|
from tsrkit_types.integers import Uint
|
|
5
4
|
from tsrkit_types.itf.codable import Codable
|
|
@@ -113,7 +112,13 @@ class Choice(Codable):
|
|
|
113
112
|
|
|
114
113
|
def encode_into(self, buf: bytearray, offset: int = 0) -> int:
|
|
115
114
|
current_offset = offset
|
|
116
|
-
|
|
115
|
+
# Find the first isinstance(self._value, type) for self._choice_types
|
|
116
|
+
for i, t in enumerate(self._choice_types):
|
|
117
|
+
if isinstance(self._value, t):
|
|
118
|
+
current_offset += Uint(i).encode_into(buf, current_offset)
|
|
119
|
+
break
|
|
120
|
+
else:
|
|
121
|
+
raise ValueError(f"Value {self._value} is not a valid choice")
|
|
117
122
|
current_offset += self._value.encode_into(buf, current_offset)
|
|
118
123
|
return current_offset - offset
|
|
119
124
|
|
tsrkit_types/dictionary.py
CHANGED
|
@@ -22,8 +22,9 @@ V = TypeVar("V", bound=Codable)
|
|
|
22
22
|
class DictCheckMeta(abc.ABCMeta):
|
|
23
23
|
"""Meta class to check if the instance is a dictionary with the same key and value types"""
|
|
24
24
|
def __instancecheck__(cls, instance):
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
# TODO - This needs more false positive testing
|
|
26
|
+
_matches_key_type = str(getattr(cls, "_key_type", None)) == str(getattr(instance, "_key_type", None))
|
|
27
|
+
_matches_value_type = str(getattr(cls, "_value_type", None)) == str(getattr(instance, "_value_type", None))
|
|
27
28
|
return isinstance(instance, dict) and _matches_key_type and _matches_value_type
|
|
28
29
|
|
|
29
30
|
|
tsrkit_types/struct.py
CHANGED
|
@@ -3,11 +3,11 @@ from typing import Any, Tuple, Union
|
|
|
3
3
|
from tsrkit_types.itf.codable import Codable
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
def
|
|
6
|
+
def structure(_cls=None, *, frozen=False, **kwargs):
|
|
7
7
|
"""Extension of dataclass to support serialization and json operations.
|
|
8
8
|
|
|
9
9
|
Usage:
|
|
10
|
-
>>> @
|
|
10
|
+
>>> @structure
|
|
11
11
|
>>> class Person:
|
|
12
12
|
>>> name: String = field(metadata={"name": "first_name"})
|
|
13
13
|
>>> age: Uint[8] = field(metadata={"default": 0})
|
|
@@ -80,3 +80,7 @@ def struct(_cls=None, *, frozen=False, **kwargs):
|
|
|
80
80
|
return new_cls
|
|
81
81
|
|
|
82
82
|
return wrap if _cls is None else wrap(_cls)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# Backward compatibility alias
|
|
86
|
+
struct = structure
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tsrkit-types
|
|
3
|
-
Version: 0.1.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Performant Python Typings library for type-safe binary serialization, JSON encoding, and data validation with zero dependencies
|
|
5
5
|
Author-email: chainscore-labs <hello@chainscore.finance>, prasad-kumkar <prasad@chainscore.finance>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/chainscore/tsrkit-types
|
|
@@ -15,6 +15,8 @@ Classifier: Intended Audience :: Developers
|
|
|
15
15
|
Classifier: Intended Audience :: System Administrators
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
21
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
@@ -26,7 +28,7 @@ Classifier: Topic :: Utilities
|
|
|
26
28
|
Classifier: Topic :: System :: Archiving
|
|
27
29
|
Classifier: Topic :: Communications
|
|
28
30
|
Classifier: Typing :: Typed
|
|
29
|
-
Requires-Python: >=3.
|
|
31
|
+
Requires-Python: >=3.10
|
|
30
32
|
Description-Content-Type: text/markdown
|
|
31
33
|
License-File: LICENSE
|
|
32
34
|
Provides-Extra: dev
|
|
@@ -40,7 +42,7 @@ Dynamic: license-file
|
|
|
40
42
|
|
|
41
43
|
# TSRKit Types
|
|
42
44
|
|
|
43
|
-
Performant Python library for type-safe binary serialization, JSON encoding, and data validation with zero dependencies.
|
|
45
|
+
Performant Python Typings library for type-safe binary serialization, JSON encoding, and data validation with zero dependencies.
|
|
44
46
|
|
|
45
47
|
Perfect for network protocols, game state serialization, configuration files, and any application requiring efficient, validated data handling.
|
|
46
48
|
|
|
@@ -62,7 +64,7 @@ pip install tsrkit-types
|
|
|
62
64
|
|
|
63
65
|
## Type Categories
|
|
64
66
|
|
|
65
|
-
### Integer Types
|
|
67
|
+
### Integer Types (extension of Python int)
|
|
66
68
|
|
|
67
69
|
#### Unsigned Integers (`Uint`)
|
|
68
70
|
|
|
@@ -70,13 +72,13 @@ The `Uint` class provides both fixed-size and variable-size unsigned integers.
|
|
|
70
72
|
|
|
71
73
|
**Fixed-Size Integers:**
|
|
72
74
|
```python
|
|
73
|
-
from tsrkit_types.integers import Uint
|
|
75
|
+
from tsrkit_types.integers import Uint
|
|
74
76
|
|
|
75
77
|
# Pre-defined types
|
|
76
|
-
value =
|
|
77
|
-
value =
|
|
78
|
-
value =
|
|
79
|
-
value =
|
|
78
|
+
value = Uint[8](255) # 8-bit unsigned integer (0-255)
|
|
79
|
+
value = Uint[16](65535) # 16-bit unsigned integer (0-65535)
|
|
80
|
+
value = Uint[32](42949) # 32-bit unsigned integer
|
|
81
|
+
value = Uint[64](1844674) # 64-bit unsigned integer
|
|
80
82
|
|
|
81
83
|
# Dynamic size specification
|
|
82
84
|
U128 = Uint[128] # 128-bit unsigned integer
|
|
@@ -96,9 +98,9 @@ encoded = num.encode()
|
|
|
96
98
|
decoded = Uint.decode(encoded)
|
|
97
99
|
|
|
98
100
|
# Arithmetic operations preserve type
|
|
99
|
-
a =
|
|
100
|
-
b =
|
|
101
|
-
result = a + b # result is
|
|
101
|
+
a = Uint[8](10)
|
|
102
|
+
b = Uint[8](20)
|
|
103
|
+
result = a + b # result is Uint[8](30)
|
|
102
104
|
```
|
|
103
105
|
|
|
104
106
|
**Encoding Details:**
|
|
@@ -107,7 +109,7 @@ result = a + b # result is U8(30)
|
|
|
107
109
|
- Values < 2^7 are encoded in 1 byte
|
|
108
110
|
- Larger values use a variable-length prefix encoding
|
|
109
111
|
|
|
110
|
-
### String Types
|
|
112
|
+
### String Types (extension of Python str)
|
|
111
113
|
|
|
112
114
|
#### UTF-8 Strings (`String`)
|
|
113
115
|
|
|
@@ -161,27 +163,11 @@ restored = Bool.from_json("true")
|
|
|
161
163
|
|
|
162
164
|
### Null Types
|
|
163
165
|
|
|
164
|
-
#### Null and Nullable
|
|
165
|
-
|
|
166
166
|
```python
|
|
167
|
-
from tsrkit_types.null import Null
|
|
167
|
+
from tsrkit_types.null import Null
|
|
168
168
|
|
|
169
169
|
# Null type
|
|
170
170
|
null_val = Null # Singleton null value
|
|
171
|
-
|
|
172
|
-
# Nullable wrapper for optional values
|
|
173
|
-
maybe_string = Nullable[String](String("hello"))
|
|
174
|
-
empty_val = Nullable[String]() # Contains null
|
|
175
|
-
|
|
176
|
-
# Check for null
|
|
177
|
-
if maybe_string.is_null():
|
|
178
|
-
print("Value is null")
|
|
179
|
-
else:
|
|
180
|
-
value = maybe_string.unwrap() # Get the wrapped value
|
|
181
|
-
|
|
182
|
-
# Encoding
|
|
183
|
-
encoded = maybe_string.encode() # 1 byte flag + optional value
|
|
184
|
-
decoded = Nullable[String].decode(encoded)
|
|
185
171
|
```
|
|
186
172
|
|
|
187
173
|
### Choice and Option Types
|
|
@@ -219,7 +205,7 @@ encoded = result.encode() # [variant_index][value]
|
|
|
219
205
|
decoded = Result.decode(encoded)
|
|
220
206
|
```
|
|
221
207
|
|
|
222
|
-
#### Option (Optional
|
|
208
|
+
#### Option (Optional Value - T | Null)
|
|
223
209
|
|
|
224
210
|
```python
|
|
225
211
|
from tsrkit_types.option import Option
|
|
@@ -240,7 +226,7 @@ decoded = Option[U32].decode(encoded)
|
|
|
240
226
|
|
|
241
227
|
### Container Types
|
|
242
228
|
|
|
243
|
-
#### Sequences (
|
|
229
|
+
#### Sequences (Extension of Python list)
|
|
244
230
|
|
|
245
231
|
```python
|
|
246
232
|
from tsrkit_types.sequences import Array, Vector, TypedArray, TypedVector
|
|
@@ -274,7 +260,7 @@ decoded = TypedDynamicVector.decode(encoded)
|
|
|
274
260
|
|
|
275
261
|
**Sequence Types:**
|
|
276
262
|
- `Array[N]`: Fixed size, any element type
|
|
277
|
-
- `Vector
|
|
263
|
+
- `Vector`: Variable size, any element type
|
|
278
264
|
- `TypedArray[T, N]`: Fixed size with typed elements
|
|
279
265
|
- `TypedVector[T]`: Variable size with typed elements
|
|
280
266
|
- `BoundedVector[min, max]`: Size constrained vector
|
|
@@ -314,7 +300,7 @@ restored = StringToInt.from_json(json_data)
|
|
|
314
300
|
|
|
315
301
|
### Bytes Types
|
|
316
302
|
|
|
317
|
-
####
|
|
303
|
+
#### Bytes (extension of Python in-built bytes)
|
|
318
304
|
|
|
319
305
|
```python
|
|
320
306
|
from tsrkit_types.bytes import Bytes
|
|
@@ -323,6 +309,10 @@ from tsrkit_types.bytes import Bytes
|
|
|
323
309
|
data = Bytes(b"Hello, binary world!")
|
|
324
310
|
data = Bytes([0x01, 0x02, 0x03, 0x04])
|
|
325
311
|
|
|
312
|
+
# Bytes <-> Bits Operations
|
|
313
|
+
data.to_bits() # [True, False, True, ...]
|
|
314
|
+
Bytes.from_bits([True, False, True, ...])
|
|
315
|
+
|
|
326
316
|
# Operations
|
|
327
317
|
length = len(data) # Byte length
|
|
328
318
|
raw_bytes = bytes(data) # Convert to Python bytes
|
|
@@ -336,7 +326,7 @@ json_str = data.to_json() # "48656c6c6f2c2062696e61727920776f726c6421"
|
|
|
336
326
|
restored = Bytes.from_json(json_str)
|
|
337
327
|
```
|
|
338
328
|
|
|
339
|
-
#### Bit Arrays
|
|
329
|
+
#### Bit Arrays (Sequence of bool)
|
|
340
330
|
|
|
341
331
|
```python
|
|
342
332
|
from tsrkit_types.bits import BitArray
|
|
@@ -361,7 +351,7 @@ encoded = bits.encode() # [length][packed_bits]
|
|
|
361
351
|
decoded = BitArray.decode(encoded)
|
|
362
352
|
```
|
|
363
353
|
|
|
364
|
-
###
|
|
354
|
+
### Enum (Extension of Python Enum, with Codable + JSON support)
|
|
365
355
|
|
|
366
356
|
```python
|
|
367
357
|
from tsrkit_types.enum import Enum
|
|
@@ -391,7 +381,7 @@ restored = Color.from_json("GREEN")
|
|
|
391
381
|
|
|
392
382
|
### Structured Types
|
|
393
383
|
|
|
394
|
-
#### Struct Decorator
|
|
384
|
+
#### Struct Decorator (Extension of dataclasses)
|
|
395
385
|
|
|
396
386
|
```python
|
|
397
387
|
from tsrkit_types.struct import struct
|
|
@@ -399,12 +389,12 @@ from tsrkit_types.string import String
|
|
|
399
389
|
from tsrkit_types.integers import U8, U32
|
|
400
390
|
from dataclasses import field
|
|
401
391
|
|
|
402
|
-
@
|
|
392
|
+
@structure
|
|
403
393
|
class Person:
|
|
404
394
|
name: String
|
|
405
395
|
age: U8
|
|
406
396
|
|
|
407
|
-
@
|
|
397
|
+
@structure
|
|
408
398
|
class Employee:
|
|
409
399
|
person: Person
|
|
410
400
|
employee_id: U32
|
|
@@ -427,7 +417,7 @@ encoded = employee.encode() # Concatenated field encodings
|
|
|
427
417
|
decoded = Employee.decode(encoded)
|
|
428
418
|
|
|
429
419
|
# JSON serialization with custom field names
|
|
430
|
-
@
|
|
420
|
+
@structure
|
|
431
421
|
class CustomPerson:
|
|
432
422
|
name: String = field(metadata={"name": "full_name"})
|
|
433
423
|
age: U8
|
|
@@ -479,7 +469,7 @@ class Point3D(Codable):
|
|
|
479
469
|
|
|
480
470
|
```python
|
|
481
471
|
# Optimize for specific use cases
|
|
482
|
-
@
|
|
472
|
+
@structure(frozen=True) # Immutable structs
|
|
483
473
|
class ImmutableData:
|
|
484
474
|
value: U64
|
|
485
475
|
|
|
@@ -575,8 +565,8 @@ offset += value2.encode_into(buffer, offset)
|
|
|
575
565
|
|
|
576
566
|
### Network Protocol
|
|
577
567
|
|
|
578
|
-
|
|
579
|
-
@
|
|
568
|
+
```**python**
|
|
569
|
+
@structure
|
|
580
570
|
class NetworkPacket:
|
|
581
571
|
packet_type: U8
|
|
582
572
|
session_id: U32
|
|
@@ -601,7 +591,7 @@ received_packet = NetworkPacket.decode(wire_data)
|
|
|
601
591
|
### Configuration File
|
|
602
592
|
|
|
603
593
|
```python
|
|
604
|
-
@
|
|
594
|
+
@structure
|
|
605
595
|
class DatabaseConfig:
|
|
606
596
|
host: String
|
|
607
597
|
port: U16
|
|
@@ -637,19 +627,19 @@ class GameEntityType(Enum):
|
|
|
637
627
|
ENEMY = 1
|
|
638
628
|
ITEM = 2
|
|
639
629
|
|
|
640
|
-
@
|
|
630
|
+
@structure
|
|
641
631
|
class Position:
|
|
642
632
|
x: U16
|
|
643
633
|
y: U16
|
|
644
634
|
|
|
645
|
-
@
|
|
635
|
+
@structure
|
|
646
636
|
class GameEntity:
|
|
647
637
|
entity_type: GameEntityType
|
|
648
638
|
position: Position
|
|
649
639
|
health: U8
|
|
650
640
|
name: String
|
|
651
641
|
|
|
652
|
-
@
|
|
642
|
+
@structure
|
|
653
643
|
class GameState:
|
|
654
644
|
level: U8
|
|
655
645
|
score: U32
|
|
@@ -745,6 +735,6 @@ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for gui
|
|
|
745
735
|
|
|
746
736
|
## Requirements
|
|
747
737
|
|
|
748
|
-
- **Python**: >= 3.
|
|
738
|
+
- **Python**: >= 3.10
|
|
749
739
|
- **Runtime Dependencies**: None (zero dependencies!)
|
|
750
740
|
- **Development Dependencies**: pytest and plugins (see `pyproject.toml`)
|
|
@@ -2,18 +2,18 @@ tsrkit_types/__init__.py,sha256=Vw03Fv9RnfmZGqzBpFhuglyewh4MxKR8T5bdWdal1VU,1870
|
|
|
2
2
|
tsrkit_types/bits.py,sha256=ggx2lDRWtBBIYQBtKEx-XirwYTJdajctCEpd3VmuXrc,3275
|
|
3
3
|
tsrkit_types/bool.py,sha256=anu5RquxV8xdDMj7aIwOOCP3WnK6vMNst4WUPlfeKm4,1460
|
|
4
4
|
tsrkit_types/bytes.py,sha256=t4GeqbYMloKrTu4XyGSRquMhQL4Ayr-S4vgZhZBS9BU,3771
|
|
5
|
-
tsrkit_types/choice.py,sha256=
|
|
6
|
-
tsrkit_types/dictionary.py,sha256=
|
|
5
|
+
tsrkit_types/choice.py,sha256=L4Pb0ZBvaoCW2h9VBLclmmgIJvfO0Yeb2khPniFN2Xo,5113
|
|
6
|
+
tsrkit_types/dictionary.py,sha256=EktyMKH27HVoR1xNhrkV8fW6KfcxpbHiiYPYoCrFdoI,5614
|
|
7
7
|
tsrkit_types/enum.py,sha256=0PZUuydhGVN6zmAscQNzq4Vnn5mUUPIxlDoQBodqf7g,4272
|
|
8
8
|
tsrkit_types/integers.py,sha256=GT9xVZYBNMcPpShJIlSazwiZYGhoBowhR0MA_cGO5Q0,7200
|
|
9
9
|
tsrkit_types/null.py,sha256=IcYYY5ZT7cZ5q5oyc0mCFGUCVCdhAXB_ftyAM9z5_Ek,1312
|
|
10
10
|
tsrkit_types/option.py,sha256=V4J8SmhUDjINqMM6Ml3ho0YwTy2UT-avrjoYh32Swyg,879
|
|
11
11
|
tsrkit_types/sequences.py,sha256=2vJeO47rmIN7WQjFGKudDhzDVifTNmrj1whE03npz3c,8092
|
|
12
12
|
tsrkit_types/string.py,sha256=8rvg0BwvyhQnbMW3qornmBFTQHeTQFUfwD7OC0eVgcY,2575
|
|
13
|
-
tsrkit_types/struct.py,sha256=
|
|
13
|
+
tsrkit_types/struct.py,sha256=ni8jwZlfT_wehardfImBJ0AsvnO-oCW-3APplLXsqGY,3206
|
|
14
14
|
tsrkit_types/itf/codable.py,sha256=jWfoYZ31MZ6k3nlHb2IwJdjD3G0pVPyZWlF0Sv9MAWs,2794
|
|
15
|
-
tsrkit_types-0.1.
|
|
16
|
-
tsrkit_types-0.1.
|
|
17
|
-
tsrkit_types-0.1.
|
|
18
|
-
tsrkit_types-0.1.
|
|
19
|
-
tsrkit_types-0.1.
|
|
15
|
+
tsrkit_types-0.1.1.dist-info/licenses/LICENSE,sha256=TwnDvVCPwHadHWLUuY1sPx03XNw1jzh_ZmoDBNai9Uc,1072
|
|
16
|
+
tsrkit_types-0.1.1.dist-info/METADATA,sha256=Yuq6ylZlPzHnNpfEGIio0FFMS13G6oMPHkFwGVAjkm0,19404
|
|
17
|
+
tsrkit_types-0.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
18
|
+
tsrkit_types-0.1.1.dist-info/top_level.txt,sha256=pnVhnUsnZ_A0FIj1zHwDw3suMGrfMJwusp-4GPVY1CM,13
|
|
19
|
+
tsrkit_types-0.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|