tsrkit-types 0.1.0__py3-none-any.whl → 0.1.2__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/bytes.py CHANGED
@@ -1,6 +1,4 @@
1
- from typing import Tuple, Union, ClassVar, Self
2
- import base64
3
-
1
+ from typing import Tuple, Union, ClassVar
4
2
  from tsrkit_types.integers import Uint
5
3
  from tsrkit_types.itf.codable import Codable
6
4
 
@@ -22,7 +20,7 @@ class Bytes(bytes, Codable):
22
20
  return f"{self.__class__.__name__}({self.hex()})"
23
21
 
24
22
  @classmethod
25
- def from_bits(cls, bits: list[bool], bit_order = "msb") -> Self:
23
+ def from_bits(cls, bits: list[bool], bit_order = "msb") -> "Bytes":
26
24
  # Sanitize input: make sure bits are 0 or 1
27
25
  bits = [int(bool(b)) for b in bits]
28
26
  n = len(bits)
@@ -79,7 +77,7 @@ class Bytes(bytes, Codable):
79
77
  return current_offset - offset
80
78
 
81
79
  @classmethod
82
- def decode_from(cls, buffer: Union[bytes, bytearray, memoryview], offset: int = 0) -> Tuple[Self, int]:
80
+ def decode_from(cls, buffer: Union[bytes, bytearray, memoryview], offset: int = 0) -> Tuple["Bytes", int]:
83
81
  current_offset = offset
84
82
  _len = cls._length
85
83
  if _len is None:
tsrkit_types/choice.py CHANGED
@@ -1,5 +1,4 @@
1
- from typing import ClassVar, Optional, Union, Tuple, Any, get_origin
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
- current_offset += Uint(self._choice_types.index(type(self._value))).encode_into(buf, current_offset)
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
 
@@ -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
- _matches_key_type = getattr(cls, "_key_type", None) == getattr(instance, "_key_type", None)
26
- _matches_value_type = getattr(cls, "_value_type", None) == getattr(instance, "_value_type", None)
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/enum.py CHANGED
@@ -20,8 +20,8 @@ class Enum(metaclass=EnumMeta):
20
20
  >>> assert decoded == value
21
21
  >>> assert bytes_read == 1
22
22
  >>>
23
- >>> assert MyEnum.from_json(1,) == MyEnum.A
24
- >>> assert MyEnum.from_json("A",) == MyEnum.A
23
+ >>> assert MyEnum.from_json(1) == MyEnum.A
24
+ >>> assert MyEnum.from_json("A") == MyEnum.A
25
25
  """
26
26
 
27
27
  @property
@@ -106,7 +106,7 @@ class Enum(metaclass=EnumMeta):
106
106
  The corresponding enum value
107
107
 
108
108
  Raises:
109
- JsonDeserializationError: If the value is invalid
109
+ ValueError: If the value is invalid
110
110
  """
111
111
  for v in cls.__members__.values():
112
112
  if v._value_ == data or v._name_ == data:
tsrkit_types/null.py CHANGED
@@ -1,4 +1,4 @@
1
- from typing import Optional, Self, Tuple, Union
1
+ from typing import Optional, Tuple, Union
2
2
 
3
3
 
4
4
  class NullType:
@@ -22,7 +22,7 @@ class NullType:
22
22
  return 0
23
23
 
24
24
  @classmethod
25
- def decode_from(cls, buffer: Union[bytes, bytearray, memoryview], offset: int = 0) -> Tuple[Self, int]:
25
+ def decode_from(cls, buffer: Union[bytes, bytearray, memoryview], offset: int = 0) -> Tuple['NullType', int]:
26
26
  return cls(), 0
27
27
 
28
28
  # ---------------------------------------------------------------------------- #
@@ -33,7 +33,7 @@ class NullType:
33
33
  return None
34
34
 
35
35
  @classmethod
36
- def from_json(cls, json_str: Optional[str]) -> Self:
36
+ def from_json(cls, json_str: Optional[str]) -> 'NullType':
37
37
  if json_str is None:
38
38
  return cls()
39
39
  raise ValueError("Invalid JSON string for NullType")
tsrkit_types/sequences.py CHANGED
@@ -84,7 +84,7 @@ class Seq(list, Codable, Generic[T], metaclass=SeqCheckMeta):
84
84
  raise TypeError(f"{value!r} is not an instance of {self._element_type!r}")
85
85
 
86
86
  def _validate_self(self):
87
- """For Resultant Self check - added to fns that alter size"""
87
+ """For Resultant self check - added to fns that alter size"""
88
88
  if len(self) < self._min_length:
89
89
  raise ValueError(f"Vector: Expected sequence size to be >= {self._min_length}, resultant size {len(self)}")
90
90
  elif len(self) > self._max_length:
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 struct(_cls=None, *, frozen=False, **kwargs):
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
- >>> @struct
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.0
4
- Summary: High-performance Python library for type-safe binary serialization, JSON encoding, and data validation with zero dependencies
3
+ Version: 0.1.2
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,7 @@ 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.11
18
19
  Classifier: Programming Language :: Python :: 3.12
19
20
  Classifier: Programming Language :: Python :: 3 :: Only
20
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -26,7 +27,7 @@ Classifier: Topic :: Utilities
26
27
  Classifier: Topic :: System :: Archiving
27
28
  Classifier: Topic :: Communications
28
29
  Classifier: Typing :: Typed
29
- Requires-Python: >=3.12
30
+ Requires-Python: >=3.11
30
31
  Description-Content-Type: text/markdown
31
32
  License-File: LICENSE
32
33
  Provides-Extra: dev
@@ -40,7 +41,7 @@ Dynamic: license-file
40
41
 
41
42
  # TSRKit Types
42
43
 
43
- Performant Python library for type-safe binary serialization, JSON encoding, and data validation with zero dependencies.
44
+ Performant Python Typings library for type-safe binary serialization, JSON encoding, and data validation with zero dependencies.
44
45
 
45
46
  Perfect for network protocols, game state serialization, configuration files, and any application requiring efficient, validated data handling.
46
47
 
@@ -62,7 +63,7 @@ pip install tsrkit-types
62
63
 
63
64
  ## Type Categories
64
65
 
65
- ### Integer Types
66
+ ### Integer Types (extension of Python int)
66
67
 
67
68
  #### Unsigned Integers (`Uint`)
68
69
 
@@ -70,13 +71,13 @@ The `Uint` class provides both fixed-size and variable-size unsigned integers.
70
71
 
71
72
  **Fixed-Size Integers:**
72
73
  ```python
73
- from tsrkit_types.integers import Uint, U8, U16, U32, U64
74
+ from tsrkit_types.integers import Uint
74
75
 
75
76
  # Pre-defined types
76
- value = U8(255) # 8-bit unsigned integer (0-255)
77
- value = U16(65535) # 16-bit unsigned integer (0-65535)
78
- value = U32(42949) # 32-bit unsigned integer
79
- value = U64(1844674) # 64-bit unsigned integer
77
+ value = Uint[8](255) # 8-bit unsigned integer (0-255)
78
+ value = Uint[16](65535) # 16-bit unsigned integer (0-65535)
79
+ value = Uint[32](42949) # 32-bit unsigned integer
80
+ value = Uint[64](1844674) # 64-bit unsigned integer
80
81
 
81
82
  # Dynamic size specification
82
83
  U128 = Uint[128] # 128-bit unsigned integer
@@ -96,9 +97,9 @@ encoded = num.encode()
96
97
  decoded = Uint.decode(encoded)
97
98
 
98
99
  # Arithmetic operations preserve type
99
- a = U8(10)
100
- b = U8(20)
101
- result = a + b # result is U8(30)
100
+ a = Uint[8](10)
101
+ b = Uint[8](20)
102
+ result = a + b # result is Uint[8](30)
102
103
  ```
103
104
 
104
105
  **Encoding Details:**
@@ -107,7 +108,7 @@ result = a + b # result is U8(30)
107
108
  - Values < 2^7 are encoded in 1 byte
108
109
  - Larger values use a variable-length prefix encoding
109
110
 
110
- ### String Types
111
+ ### String Types (extension of Python str)
111
112
 
112
113
  #### UTF-8 Strings (`String`)
113
114
 
@@ -161,27 +162,11 @@ restored = Bool.from_json("true")
161
162
 
162
163
  ### Null Types
163
164
 
164
- #### Null and Nullable
165
-
166
165
  ```python
167
- from tsrkit_types.null import Null, Nullable
166
+ from tsrkit_types.null import Null
168
167
 
169
168
  # Null type
170
169
  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
170
  ```
186
171
 
187
172
  ### Choice and Option Types
@@ -219,7 +204,7 @@ encoded = result.encode() # [variant_index][value]
219
204
  decoded = Result.decode(encoded)
220
205
  ```
221
206
 
222
- #### Option (Optional Values)
207
+ #### Option (Optional Value - T | Null)
223
208
 
224
209
  ```python
225
210
  from tsrkit_types.option import Option
@@ -240,7 +225,7 @@ decoded = Option[U32].decode(encoded)
240
225
 
241
226
  ### Container Types
242
227
 
243
- #### Sequences (Arrays and Vectors)
228
+ #### Sequences (Extension of Python list)
244
229
 
245
230
  ```python
246
231
  from tsrkit_types.sequences import Array, Vector, TypedArray, TypedVector
@@ -274,7 +259,7 @@ decoded = TypedDynamicVector.decode(encoded)
274
259
 
275
260
  **Sequence Types:**
276
261
  - `Array[N]`: Fixed size, any element type
277
- - `Vector[max]`: Variable size up to max, any element type
262
+ - `Vector`: Variable size, any element type
278
263
  - `TypedArray[T, N]`: Fixed size with typed elements
279
264
  - `TypedVector[T]`: Variable size with typed elements
280
265
  - `BoundedVector[min, max]`: Size constrained vector
@@ -314,7 +299,7 @@ restored = StringToInt.from_json(json_data)
314
299
 
315
300
  ### Bytes Types
316
301
 
317
- #### Raw Bytes
302
+ #### Bytes (extension of Python in-built bytes)
318
303
 
319
304
  ```python
320
305
  from tsrkit_types.bytes import Bytes
@@ -323,6 +308,10 @@ from tsrkit_types.bytes import Bytes
323
308
  data = Bytes(b"Hello, binary world!")
324
309
  data = Bytes([0x01, 0x02, 0x03, 0x04])
325
310
 
311
+ # Bytes <-> Bits Operations
312
+ data.to_bits() # [True, False, True, ...]
313
+ Bytes.from_bits([True, False, True, ...])
314
+
326
315
  # Operations
327
316
  length = len(data) # Byte length
328
317
  raw_bytes = bytes(data) # Convert to Python bytes
@@ -336,7 +325,7 @@ json_str = data.to_json() # "48656c6c6f2c2062696e61727920776f726c6421"
336
325
  restored = Bytes.from_json(json_str)
337
326
  ```
338
327
 
339
- #### Bit Arrays
328
+ #### Bit Arrays (Sequence of bool)
340
329
 
341
330
  ```python
342
331
  from tsrkit_types.bits import BitArray
@@ -361,7 +350,7 @@ encoded = bits.encode() # [length][packed_bits]
361
350
  decoded = BitArray.decode(encoded)
362
351
  ```
363
352
 
364
- ### Enumeration Types
353
+ ### Enum (Extension of Python Enum, with Codable + JSON support)
365
354
 
366
355
  ```python
367
356
  from tsrkit_types.enum import Enum
@@ -391,7 +380,7 @@ restored = Color.from_json("GREEN")
391
380
 
392
381
  ### Structured Types
393
382
 
394
- #### Struct Decorator
383
+ #### Struct Decorator (Extension of dataclasses)
395
384
 
396
385
  ```python
397
386
  from tsrkit_types.struct import struct
@@ -399,12 +388,12 @@ from tsrkit_types.string import String
399
388
  from tsrkit_types.integers import U8, U32
400
389
  from dataclasses import field
401
390
 
402
- @struct
391
+ @structure
403
392
  class Person:
404
393
  name: String
405
394
  age: U8
406
395
 
407
- @struct
396
+ @structure
408
397
  class Employee:
409
398
  person: Person
410
399
  employee_id: U32
@@ -427,7 +416,7 @@ encoded = employee.encode() # Concatenated field encodings
427
416
  decoded = Employee.decode(encoded)
428
417
 
429
418
  # JSON serialization with custom field names
430
- @struct
419
+ @structure
431
420
  class CustomPerson:
432
421
  name: String = field(metadata={"name": "full_name"})
433
422
  age: U8
@@ -479,7 +468,7 @@ class Point3D(Codable):
479
468
 
480
469
  ```python
481
470
  # Optimize for specific use cases
482
- @struct(frozen=True) # Immutable structs
471
+ @structure(frozen=True) # Immutable structs
483
472
  class ImmutableData:
484
473
  value: U64
485
474
 
@@ -575,8 +564,8 @@ offset += value2.encode_into(buffer, offset)
575
564
 
576
565
  ### Network Protocol
577
566
 
578
- ```python
579
- @struct
567
+ ```**python**
568
+ @structure
580
569
  class NetworkPacket:
581
570
  packet_type: U8
582
571
  session_id: U32
@@ -601,7 +590,7 @@ received_packet = NetworkPacket.decode(wire_data)
601
590
  ### Configuration File
602
591
 
603
592
  ```python
604
- @struct
593
+ @structure
605
594
  class DatabaseConfig:
606
595
  host: String
607
596
  port: U16
@@ -637,19 +626,19 @@ class GameEntityType(Enum):
637
626
  ENEMY = 1
638
627
  ITEM = 2
639
628
 
640
- @struct
629
+ @structure
641
630
  class Position:
642
631
  x: U16
643
632
  y: U16
644
633
 
645
- @struct
634
+ @structure
646
635
  class GameEntity:
647
636
  entity_type: GameEntityType
648
637
  position: Position
649
638
  health: U8
650
639
  name: String
651
640
 
652
- @struct
641
+ @structure
653
642
  class GameState:
654
643
  level: U8
655
644
  score: U32
@@ -745,6 +734,6 @@ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for gui
745
734
 
746
735
  ## Requirements
747
736
 
748
- - **Python**: >= 3.12
737
+ - **Python**: >= 3.11
749
738
  - **Runtime Dependencies**: None (zero dependencies!)
750
739
  - **Development Dependencies**: pytest and plugins (see `pyproject.toml`)
@@ -0,0 +1,19 @@
1
+ tsrkit_types/__init__.py,sha256=Vw03Fv9RnfmZGqzBpFhuglyewh4MxKR8T5bdWdal1VU,1870
2
+ tsrkit_types/bits.py,sha256=ggx2lDRWtBBIYQBtKEx-XirwYTJdajctCEpd3VmuXrc,3275
3
+ tsrkit_types/bool.py,sha256=anu5RquxV8xdDMj7aIwOOCP3WnK6vMNst4WUPlfeKm4,1460
4
+ tsrkit_types/bytes.py,sha256=rw0sjw1fO9bOElftWehs8oLCZFMXWeajjCyOH-5kChU,3756
5
+ tsrkit_types/choice.py,sha256=L4Pb0ZBvaoCW2h9VBLclmmgIJvfO0Yeb2khPniFN2Xo,5113
6
+ tsrkit_types/dictionary.py,sha256=EktyMKH27HVoR1xNhrkV8fW6KfcxpbHiiYPYoCrFdoI,5614
7
+ tsrkit_types/enum.py,sha256=3MyLW15_ToQQdctJjcMY8Xb3OsS_Ad997OOEo8FjVeA,4256
8
+ tsrkit_types/integers.py,sha256=GT9xVZYBNMcPpShJIlSazwiZYGhoBowhR0MA_cGO5Q0,7200
9
+ tsrkit_types/null.py,sha256=OwHVhWLdazaFLXXR8iHPaHe67NPmYHDCavBxUfcZ53s,1318
10
+ tsrkit_types/option.py,sha256=V4J8SmhUDjINqMM6Ml3ho0YwTy2UT-avrjoYh32Swyg,879
11
+ tsrkit_types/sequences.py,sha256=6aseAdoAkD3RG20ag6CTzVZPR_YlJfLHo82JrNZY3dE,8092
12
+ tsrkit_types/string.py,sha256=8rvg0BwvyhQnbMW3qornmBFTQHeTQFUfwD7OC0eVgcY,2575
13
+ tsrkit_types/struct.py,sha256=ni8jwZlfT_wehardfImBJ0AsvnO-oCW-3APplLXsqGY,3206
14
+ tsrkit_types/itf/codable.py,sha256=jWfoYZ31MZ6k3nlHb2IwJdjD3G0pVPyZWlF0Sv9MAWs,2794
15
+ tsrkit_types-0.1.2.dist-info/licenses/LICENSE,sha256=TwnDvVCPwHadHWLUuY1sPx03XNw1jzh_ZmoDBNai9Uc,1072
16
+ tsrkit_types-0.1.2.dist-info/METADATA,sha256=Yt9wxA4VDq7jhjzPGrrpcQ4rhjgMUQN3hoTl9rjT3ec,19353
17
+ tsrkit_types-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ tsrkit_types-0.1.2.dist-info/top_level.txt,sha256=pnVhnUsnZ_A0FIj1zHwDw3suMGrfMJwusp-4GPVY1CM,13
19
+ tsrkit_types-0.1.2.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- tsrkit_types/__init__.py,sha256=Vw03Fv9RnfmZGqzBpFhuglyewh4MxKR8T5bdWdal1VU,1870
2
- tsrkit_types/bits.py,sha256=ggx2lDRWtBBIYQBtKEx-XirwYTJdajctCEpd3VmuXrc,3275
3
- tsrkit_types/bool.py,sha256=anu5RquxV8xdDMj7aIwOOCP3WnK6vMNst4WUPlfeKm4,1460
4
- tsrkit_types/bytes.py,sha256=t4GeqbYMloKrTu4XyGSRquMhQL4Ayr-S4vgZhZBS9BU,3771
5
- tsrkit_types/choice.py,sha256=eEHkXT2ymk4WwP0IxllErM1ixWjRrwGLcKIPTuiTkd4,4915
6
- tsrkit_types/dictionary.py,sha256=yXhz3ZaVEgLgxSeGuYzVBLDGIFsy7m6PkRGUji8njmc,5538
7
- tsrkit_types/enum.py,sha256=0PZUuydhGVN6zmAscQNzq4Vnn5mUUPIxlDoQBodqf7g,4272
8
- tsrkit_types/integers.py,sha256=GT9xVZYBNMcPpShJIlSazwiZYGhoBowhR0MA_cGO5Q0,7200
9
- tsrkit_types/null.py,sha256=IcYYY5ZT7cZ5q5oyc0mCFGUCVCdhAXB_ftyAM9z5_Ek,1312
10
- tsrkit_types/option.py,sha256=V4J8SmhUDjINqMM6Ml3ho0YwTy2UT-avrjoYh32Swyg,879
11
- tsrkit_types/sequences.py,sha256=2vJeO47rmIN7WQjFGKudDhzDVifTNmrj1whE03npz3c,8092
12
- tsrkit_types/string.py,sha256=8rvg0BwvyhQnbMW3qornmBFTQHeTQFUfwD7OC0eVgcY,2575
13
- tsrkit_types/struct.py,sha256=P5xIvYr0V5Hrhs7bnn0jgvAtkY29XtXuCIISgeP7oks,3148
14
- tsrkit_types/itf/codable.py,sha256=jWfoYZ31MZ6k3nlHb2IwJdjD3G0pVPyZWlF0Sv9MAWs,2794
15
- tsrkit_types-0.1.0.dist-info/licenses/LICENSE,sha256=TwnDvVCPwHadHWLUuY1sPx03XNw1jzh_ZmoDBNai9Uc,1072
16
- tsrkit_types-0.1.0.dist-info/METADATA,sha256=Uz8n_Q2q57blki1O4OrN2wr4I36KJK_HRxZkaQ90c5A,19376
17
- tsrkit_types-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
- tsrkit_types-0.1.0.dist-info/top_level.txt,sha256=pnVhnUsnZ_A0FIj1zHwDw3suMGrfMJwusp-4GPVY1CM,13
19
- tsrkit_types-0.1.0.dist-info/RECORD,,