base-typed-string 0.1.1__tar.gz → 0.1.2__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 (21) hide show
  1. {base_typed_string-0.1.1/src/base_typed_string.egg-info → base_typed_string-0.1.2}/PKG-INFO +35 -2
  2. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/README.md +33 -1
  3. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/pyproject.toml +2 -1
  4. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/src/base_typed_string/__init__.py +1 -1
  5. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/src/base_typed_string/_base_typed_string.py +2 -2
  6. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/src/base_typed_string/_exceptions.py +1 -1
  7. {base_typed_string-0.1.1 → base_typed_string-0.1.2/src/base_typed_string.egg-info}/PKG-INFO +35 -2
  8. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/src/base_typed_string.egg-info/requires.txt +1 -0
  9. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/tests/test_runtime_behavior.py +1 -1
  10. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/LICENSE +0 -0
  11. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/setup.cfg +0 -0
  12. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/src/base_typed_string/py.typed +0 -0
  13. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/src/base_typed_string.egg-info/SOURCES.txt +0 -0
  14. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/src/base_typed_string.egg-info/dependency_links.txt +0 -0
  15. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/src/base_typed_string.egg-info/top_level.txt +0 -0
  16. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/tests/test_constructor.py +0 -0
  17. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/tests/test_internal_invariants.py +0 -0
  18. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/tests/test_pickle_support.py +0 -0
  19. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/tests/test_pydantic_support.py +0 -0
  20. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/tests/testing_assertions.py +0 -0
  21. {base_typed_string-0.1.1 → base_typed_string-0.1.2}/tests/testing_types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: base-typed-string
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Strict typed string base class with exact runtime subtype preservation and optional Pydantic v2 support.
5
5
  Author-email: Eldeniz Guseinli <eldenizfamilyanskicode@gmail.com>
6
6
  License-Expression: MIT
@@ -26,6 +26,7 @@ Requires-Dist: pydantic<3,>=2.6; extra == "pydantic"
26
26
  Provides-Extra: test
27
27
  Requires-Dist: pytest>=8.0; extra == "test"
28
28
  Requires-Dist: pytest-cov>=5.0; extra == "test"
29
+ Requires-Dist: pydantic<3,>=2.6; extra == "test"
29
30
  Provides-Extra: lint
30
31
  Requires-Dist: ruff>=0.5; extra == "lint"
31
32
  Provides-Extra: typecheck
@@ -101,7 +102,6 @@ domain-specific names in type annotations, while keeping real `str` behavior at
101
102
  - no normalization
102
103
  - no regex engine
103
104
  - no domain-specific methods
104
- - no custom JSON layer
105
105
 
106
106
  This package is intentionally minimal.
107
107
 
@@ -446,6 +446,39 @@ assert type(restored_email) is EmailAddress
446
446
 
447
447
  ---
448
448
 
449
+ ## JSON behavior
450
+
451
+ Since `BaseTypedString` inherits from `str`, standard JSON serialization naturally produces plain JSON strings.
452
+
453
+ ```python
454
+ import json
455
+
456
+ from base_typed_string import BaseTypedString
457
+
458
+
459
+ class EmailAddress(BaseTypedString):
460
+ pass
461
+
462
+
463
+ value: EmailAddress = EmailAddress("hello@example.com")
464
+ serialized_value: str = json.dumps(value)
465
+ restored_value: object = json.loads(serialized_value)
466
+
467
+ assert serialized_value == '"hello@example.com"'
468
+ assert restored_value == "hello@example.com"
469
+ assert type(restored_value) is str
470
+ ```
471
+
472
+ This behavior is intentional.
473
+
474
+ JSON is a plain data boundary.
475
+
476
+ The exact runtime subtype exists only inside Python objects.
477
+ After serialization, values become plain strings and do not carry subtype information.
478
+
479
+ ---
480
+
481
+
449
482
  ## Public API
450
483
 
451
484
  ```python
@@ -54,7 +54,6 @@ domain-specific names in type annotations, while keeping real `str` behavior at
54
54
  - no normalization
55
55
  - no regex engine
56
56
  - no domain-specific methods
57
- - no custom JSON layer
58
57
 
59
58
  This package is intentionally minimal.
60
59
 
@@ -399,6 +398,39 @@ assert type(restored_email) is EmailAddress
399
398
 
400
399
  ---
401
400
 
401
+ ## JSON behavior
402
+
403
+ Since `BaseTypedString` inherits from `str`, standard JSON serialization naturally produces plain JSON strings.
404
+
405
+ ```python
406
+ import json
407
+
408
+ from base_typed_string import BaseTypedString
409
+
410
+
411
+ class EmailAddress(BaseTypedString):
412
+ pass
413
+
414
+
415
+ value: EmailAddress = EmailAddress("hello@example.com")
416
+ serialized_value: str = json.dumps(value)
417
+ restored_value: object = json.loads(serialized_value)
418
+
419
+ assert serialized_value == '"hello@example.com"'
420
+ assert restored_value == "hello@example.com"
421
+ assert type(restored_value) is str
422
+ ```
423
+
424
+ This behavior is intentional.
425
+
426
+ JSON is a plain data boundary.
427
+
428
+ The exact runtime subtype exists only inside Python objects.
429
+ After serialization, values become plain strings and do not carry subtype information.
430
+
431
+ ---
432
+
433
+
402
434
  ## Public API
403
435
 
404
436
  ```python
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "base-typed-string"
7
- version = "0.1.1"
7
+ version = "0.1.2"
8
8
  description = "Strict typed string base class with exact runtime subtype preservation and optional Pydantic v2 support."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -40,6 +40,7 @@ pydantic = [
40
40
  test = [
41
41
  "pytest>=8.0",
42
42
  "pytest-cov>=5.0",
43
+ "pydantic>=2.6,<3",
43
44
  ]
44
45
  lint = [
45
46
  "ruff>=0.5",
@@ -12,4 +12,4 @@ __all__: list[str] = [
12
12
  "BaseTypedStringInvariantViolationError",
13
13
  ]
14
14
 
15
- __version__: str = "0.1.0"
15
+ __version__: str = "0.1.2"
@@ -29,9 +29,9 @@ class BaseTypedString(str):
29
29
 
30
30
  def __new__(
31
31
  cls: type[BaseTypedStringType],
32
- value: Any,
32
+ value: str,
33
33
  ) -> BaseTypedStringType:
34
- if not isinstance(value, str):
34
+ if not isinstance(value, str): # pyright: ignore[reportUnnecessaryIsInstance] runtime boundary guard
35
35
  raise BaseTypedStringInvalidInputValueError(
36
36
  "BaseTypedString must be initialized only with str. "
37
37
  f"Got: {type(value).__name__}."
@@ -7,4 +7,4 @@ class BaseTypedStringInvalidInputValueError(BaseTypedStringError, TypeError):
7
7
 
8
8
 
9
9
  class BaseTypedStringInvariantViolationError(BaseTypedStringError):
10
- """Raised when an internal invariant or contract is violated."""
10
+ """Raised when an internal invariant or contract is violated."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: base-typed-string
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Strict typed string base class with exact runtime subtype preservation and optional Pydantic v2 support.
5
5
  Author-email: Eldeniz Guseinli <eldenizfamilyanskicode@gmail.com>
6
6
  License-Expression: MIT
@@ -26,6 +26,7 @@ Requires-Dist: pydantic<3,>=2.6; extra == "pydantic"
26
26
  Provides-Extra: test
27
27
  Requires-Dist: pytest>=8.0; extra == "test"
28
28
  Requires-Dist: pytest-cov>=5.0; extra == "test"
29
+ Requires-Dist: pydantic<3,>=2.6; extra == "test"
29
30
  Provides-Extra: lint
30
31
  Requires-Dist: ruff>=0.5; extra == "lint"
31
32
  Provides-Extra: typecheck
@@ -101,7 +102,6 @@ domain-specific names in type annotations, while keeping real `str` behavior at
101
102
  - no normalization
102
103
  - no regex engine
103
104
  - no domain-specific methods
104
- - no custom JSON layer
105
105
 
106
106
  This package is intentionally minimal.
107
107
 
@@ -446,6 +446,39 @@ assert type(restored_email) is EmailAddress
446
446
 
447
447
  ---
448
448
 
449
+ ## JSON behavior
450
+
451
+ Since `BaseTypedString` inherits from `str`, standard JSON serialization naturally produces plain JSON strings.
452
+
453
+ ```python
454
+ import json
455
+
456
+ from base_typed_string import BaseTypedString
457
+
458
+
459
+ class EmailAddress(BaseTypedString):
460
+ pass
461
+
462
+
463
+ value: EmailAddress = EmailAddress("hello@example.com")
464
+ serialized_value: str = json.dumps(value)
465
+ restored_value: object = json.loads(serialized_value)
466
+
467
+ assert serialized_value == '"hello@example.com"'
468
+ assert restored_value == "hello@example.com"
469
+ assert type(restored_value) is str
470
+ ```
471
+
472
+ This behavior is intentional.
473
+
474
+ JSON is a plain data boundary.
475
+
476
+ The exact runtime subtype exists only inside Python objects.
477
+ After serialization, values become plain strings and do not carry subtype information.
478
+
479
+ ---
480
+
481
+
449
482
  ## Public API
450
483
 
451
484
  ```python
@@ -22,6 +22,7 @@ pydantic<3,>=2.6
22
22
  [test]
23
23
  pytest>=8.0
24
24
  pytest-cov>=5.0
25
+ pydantic<3,>=2.6
25
26
 
26
27
  [typecheck]
27
28
  mypy>=1.10
@@ -127,6 +127,7 @@ def test_repr_uses_exact_runtime_subtype_name_and_plain_string_value() -> None:
127
127
 
128
128
  assert rendered_value == "AdminUserName('root')"
129
129
 
130
+
130
131
  def test_plain_class_attribute_preserves_exact_runtime_subtype() -> None:
131
132
  typed_value: UserName = UserName("alice")
132
133
 
@@ -140,4 +141,3 @@ def test_plain_class_attribute_preserves_exact_runtime_subtype() -> None:
140
141
  expected_plain_value="alice",
141
142
  expected_type=UserName,
142
143
  )
143
-