json-tstring 0.1.0__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.
@@ -0,0 +1,21 @@
1
+ from tstring_core import (
2
+ RenderResult,
3
+ TemplateError,
4
+ TemplateParseError,
5
+ TemplateSemanticError,
6
+ UnrepresentableValueError,
7
+ )
8
+
9
+ from ._runtime import JsonProfile, render_data, render_result, render_text
10
+
11
+ __all__ = [
12
+ "JsonProfile",
13
+ "RenderResult",
14
+ "TemplateError",
15
+ "TemplateParseError",
16
+ "TemplateSemanticError",
17
+ "UnrepresentableValueError",
18
+ "render_data",
19
+ "render_result",
20
+ "render_text",
21
+ ]
@@ -0,0 +1,15 @@
1
+ from __future__ import annotations
2
+
3
+ from tstring_core import (
4
+ TemplateError,
5
+ TemplateParseError,
6
+ TemplateSemanticError,
7
+ UnrepresentableValueError,
8
+ )
9
+
10
+ __all__ = [
11
+ "TemplateError",
12
+ "TemplateParseError",
13
+ "TemplateSemanticError",
14
+ "UnrepresentableValueError",
15
+ ]
@@ -0,0 +1,106 @@
1
+ from __future__ import annotations
2
+
3
+ from string.templatelib import Template
4
+ from typing import Literal, Protocol, TypeIs, cast
5
+
6
+ from tstring_bindings import tstring_bindings as _bindings
7
+ from tstring_core import JsonValue, RenderResult
8
+
9
+ type JsonProfile = Literal["rfc8259"]
10
+
11
+ _CONTRACT_VERSION = 1
12
+ _REQUIRED_SYMBOLS = {
13
+ "render_json",
14
+ "render_json_text",
15
+ "_render_json_result_payload",
16
+ }
17
+
18
+
19
+ class _RenderJson(Protocol):
20
+ def __call__(self, template: Template, *, profile: JsonProfile) -> JsonValue: ...
21
+
22
+
23
+ class _RenderJsonText(Protocol):
24
+ def __call__(self, template: Template, *, profile: JsonProfile) -> str: ...
25
+
26
+
27
+ class _RenderJsonResultPayload(Protocol):
28
+ def __call__(
29
+ self, template: Template, *, profile: JsonProfile
30
+ ) -> tuple[str, JsonValue]: ...
31
+
32
+
33
+ def _bind_extension() -> tuple[_RenderJson, _RenderJsonText, _RenderJsonResultPayload]:
34
+ version = getattr(_bindings, "__contract_version__", None)
35
+ if version != _CONTRACT_VERSION:
36
+ raise ImportError(
37
+ "json_tstring extension contract mismatch: "
38
+ f"expected version {_CONTRACT_VERSION}, got {version!r}."
39
+ )
40
+
41
+ exported = set(getattr(_bindings, "__contract_symbols__", ()))
42
+ missing = sorted(_REQUIRED_SYMBOLS - exported)
43
+ if missing:
44
+ raise ImportError(
45
+ "json_tstring could not bind required extension symbols: "
46
+ + ", ".join(missing)
47
+ )
48
+
49
+ return (
50
+ cast(_RenderJson, _bindings.render_json),
51
+ cast(_RenderJsonText, _bindings.render_json_text),
52
+ cast(_RenderJsonResultPayload, _bindings._render_json_result_payload),
53
+ )
54
+
55
+
56
+ _render_json, _render_json_text, _render_json_result_payload = _bind_extension()
57
+
58
+
59
+ def _is_template(value: object) -> TypeIs[Template]:
60
+ return isinstance(value, Template)
61
+
62
+
63
+ def _validate_template(template: object, api_name: str) -> Template:
64
+ if _is_template(template):
65
+ return template
66
+ raise TypeError(
67
+ f"{api_name} requires a PEP 750 Template object. "
68
+ f"Got {type(template).__name__} instead."
69
+ )
70
+
71
+
72
+ def _resolve_profile(profile: JsonProfile | str | None) -> JsonProfile:
73
+ if profile is None or profile == "rfc8259":
74
+ return "rfc8259"
75
+ raise ValueError(
76
+ f"Unsupported JSON profile {profile!r}. Supported profiles: 'rfc8259'."
77
+ )
78
+
79
+
80
+ def render_data(
81
+ template: Template, *, profile: JsonProfile | str | None = None
82
+ ) -> JsonValue:
83
+ checked = _validate_template(template, "render_data")
84
+ return _render_json(checked, profile=_resolve_profile(profile))
85
+
86
+
87
+ def render_text(template: Template, *, profile: JsonProfile | str | None = None) -> str:
88
+ checked = _validate_template(template, "render_text")
89
+ return _render_json_text(checked, profile=_resolve_profile(profile))
90
+
91
+
92
+ def render_result(
93
+ template: Template, *, profile: JsonProfile | str | None = None
94
+ ) -> RenderResult[JsonValue]:
95
+ checked = _validate_template(template, "render_result")
96
+ text, data = _render_json_result_payload(checked, profile=_resolve_profile(profile))
97
+ return RenderResult(text=text, data=data)
98
+
99
+
100
+ __all__ = [
101
+ "JsonProfile",
102
+ "RenderResult",
103
+ "render_data",
104
+ "render_result",
105
+ "render_text",
106
+ ]
json_tstring/_slots.py ADDED
@@ -0,0 +1,3 @@
1
+ from tstring_core import FragmentGroup, Slot, SlotContext
2
+
3
+ __all__ = ["FragmentGroup", "Slot", "SlotContext"]
json_tstring/py.typed ADDED
@@ -0,0 +1 @@
1
+ # Marker file for PEP 561 typing support.
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.3
2
+ Name: json-tstring
3
+ Version: 0.1.0
4
+ Summary: JSON renderer for t-string structured data templates
5
+ Keywords: pep750,t-strings,json,template-strings,structured-data
6
+ Author: Koudai Aono
7
+ Author-email: Koudai Aono <koxudaxi@gmail.com>
8
+ License: MIT
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Dist: tstring-bindings>=0.1.0
17
+ Requires-Dist: tstring-core>=0.1.0
18
+ Maintainer: Koudai Aono
19
+ Maintainer-email: Koudai Aono <koxudaxi@gmail.com>
20
+ Requires-Python: >=3.14
21
+ Project-URL: Homepage, https://github.com/koxudaxi/tstring-structured-data
22
+ Project-URL: Repository, https://github.com/koxudaxi/tstring-structured-data
23
+ Project-URL: Documentation, https://github.com/koxudaxi/tstring-structured-data/blob/main/json-tstring/README.md
24
+ Project-URL: Changelog, https://github.com/koxudaxi/tstring-structured-data/blob/main/CHANGELOG.md
25
+ Project-URL: Issues, https://github.com/koxudaxi/tstring-structured-data/issues
26
+ Description-Content-Type: text/markdown
27
+
28
+ # json-tstring
29
+
30
+ JSON rendering for PEP 750 t-strings. Parsing and rendering happen in Rust;
31
+ this package is the Python wrapper.
32
+
33
+ Requires Python 3.14+.
34
+
35
+ This package depends on `tstring-bindings`, a native PyO3 extension. On
36
+ supported platforms, install from prebuilt wheels. Other environments require a
37
+ local Rust 1.94.0 toolchain build.
38
+
39
+ ## API
40
+
41
+ ```python
42
+ render_data(template, profile="rfc8259") # -> Python data
43
+ render_text(template, profile="rfc8259") # -> JSON text
44
+ render_result(template, profile="rfc8259") # -> RenderResult (.text + .data)
45
+ ```
46
+
47
+ Type alias: `JsonProfile = Literal["rfc8259"]`
48
+
49
+ Parsed template structure is cached per process using `template.strings` +
50
+ profile as the key.
51
+
52
+ ## How it works
53
+
54
+ The Python `Template` is converted to a Rust token stream, parsed into JSON
55
+ nodes (keeping interpolation visible in values, keys, and string fragments),
56
+ and rendered back to text or Python data. `serde_json` handles normalization.
57
+
58
+ ## Supported positions
59
+
60
+ - whole-value, object-key, quoted-key-fragment, and string-fragment interpolation
61
+ - bare fragments promoted to JSON strings
62
+ - nested arrays and objects, top-level values
63
+
64
+ ## Limits
65
+
66
+ - object keys must be `str`
67
+ - non-finite floats rejected
68
+ - values must be JSON-representable
69
+ - integers keep exact Python text (no silent `float` coercion)
70
+
71
+ ## Verify
72
+
73
+ ```bash
74
+ uv sync --group dev
75
+ uv run --group dev pytest
76
+ ```
77
+
78
+ ## See also
79
+
80
+ - [Project README](https://github.com/koxudaxi/tstring-structured-data#readme)
81
+ - [Backend support matrix](https://github.com/koxudaxi/tstring-structured-data/blob/main/docs/backend-support-matrix.md)
@@ -0,0 +1,8 @@
1
+ json_tstring/__init__.py,sha256=hbI2b0EyxRFDoeQCw8PhmNxwJwmvRfiqkmDetGNqlm8,446
2
+ json_tstring/_errors.py,sha256=bZp21oaGkpLPS70_eJ6jlP7Edrvf1mC6JaOB1FzG0HA,290
3
+ json_tstring/_runtime.py,sha256=fSFQONfsYnHPUNjqLIu8QAFYNkuyGW8KPWnk3GnyR8U,3199
4
+ json_tstring/_slots.py,sha256=V7QUPNUvo2G1IQzVXjRHvD8IQTcXI0-oOEi5lzTfXag,110
5
+ json_tstring/py.typed,sha256=0VrMqa_u6HfLYNPxflMqTVvjIovV_taKM7nltQcS1TA,42
6
+ json_tstring-0.1.0.dist-info/WHEEL,sha256=9sjN42GvvIkyGb9JrWAWXnA96E2dxDe0tzHzrLxUlD4,81
7
+ json_tstring-0.1.0.dist-info/METADATA,sha256=Yqc_aJjcWu8I-zboZ5NXTKyPg6KjTz-WKJGE5v0aV8I,2884
8
+ json_tstring-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.10.11
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any