yaml-tstring 0.1.0__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.
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.3
2
+ Name: yaml-tstring
3
+ Version: 0.1.0
4
+ Summary: YAML renderer for t-string structured data templates
5
+ Keywords: pep750,t-strings,yaml,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/yaml-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
+ # yaml-tstring
29
+
30
+ YAML 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="1.2.2") # -> Python data (list for multi-doc)
43
+ render_text(template, profile="1.2.2") # -> YAML text
44
+ render_result(template, profile="1.2.2") # -> RenderResult (.text + .data)
45
+ ```
46
+
47
+ Type alias: `YamlProfile = Literal["1.2.2"]`
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 and parsed by an
55
+ interpolation-aware YAML scanner/parser. Block mappings, block sequences, flow
56
+ collections, scalar styles, anchors, aliases, and tags are all parsed
57
+ explicitly in Rust with interpolation nodes preserved. `saphyr` handles
58
+ data materialization and normalization.
59
+
60
+ ## Supported positions
61
+
62
+ - mapping-key interpolation
63
+ - plain, single-quoted, double-quoted, and block scalar assembly
64
+ - anchor, alias, and tag interpolation (including verbatim `!<...>` tags)
65
+ - block and flow collections, multi-document streams
66
+ - directives, `%TAG` handles, explicit document markers
67
+ - merge keys, complex keys, trailing commas in flow collections
68
+ - YAML 1.2.2 escape sequences in double-quoted scalars
69
+
70
+ The full tested boundary is in the
71
+ [backend support matrix](https://github.com/koxudaxi/tstring-structured-data/blob/main/docs/backend-support-matrix.md).
72
+
73
+ ## Limits
74
+
75
+ - non-finite floats rejected
76
+ - metadata fragments must be non-empty and whitespace-free
77
+ - integers keep exact Python text (no silent `float` coercion)
78
+ - values must be representable in the current YAML 1.2+ surface
79
+
80
+ ## Verify
81
+
82
+ ```bash
83
+ uv sync --group dev
84
+ uv run --group dev pytest
85
+ ```
86
+
87
+ ## See also
88
+
89
+ - [Project README](https://github.com/koxudaxi/tstring-structured-data#readme)
90
+ - [Backend support matrix](https://github.com/koxudaxi/tstring-structured-data/blob/main/docs/backend-support-matrix.md)
@@ -0,0 +1,63 @@
1
+ # yaml-tstring
2
+
3
+ YAML rendering for PEP 750 t-strings. Parsing and rendering happen in Rust;
4
+ this package is the Python wrapper.
5
+
6
+ Requires Python 3.14+.
7
+
8
+ This package depends on `tstring-bindings`, a native PyO3 extension. On
9
+ supported platforms, install from prebuilt wheels. Other environments require a
10
+ local Rust 1.94.0 toolchain build.
11
+
12
+ ## API
13
+
14
+ ```python
15
+ render_data(template, profile="1.2.2") # -> Python data (list for multi-doc)
16
+ render_text(template, profile="1.2.2") # -> YAML text
17
+ render_result(template, profile="1.2.2") # -> RenderResult (.text + .data)
18
+ ```
19
+
20
+ Type alias: `YamlProfile = Literal["1.2.2"]`
21
+
22
+ Parsed template structure is cached per process using `template.strings` +
23
+ profile as the key.
24
+
25
+ ## How it works
26
+
27
+ The Python `Template` is converted to a Rust token stream and parsed by an
28
+ interpolation-aware YAML scanner/parser. Block mappings, block sequences, flow
29
+ collections, scalar styles, anchors, aliases, and tags are all parsed
30
+ explicitly in Rust with interpolation nodes preserved. `saphyr` handles
31
+ data materialization and normalization.
32
+
33
+ ## Supported positions
34
+
35
+ - mapping-key interpolation
36
+ - plain, single-quoted, double-quoted, and block scalar assembly
37
+ - anchor, alias, and tag interpolation (including verbatim `!<...>` tags)
38
+ - block and flow collections, multi-document streams
39
+ - directives, `%TAG` handles, explicit document markers
40
+ - merge keys, complex keys, trailing commas in flow collections
41
+ - YAML 1.2.2 escape sequences in double-quoted scalars
42
+
43
+ The full tested boundary is in the
44
+ [backend support matrix](https://github.com/koxudaxi/tstring-structured-data/blob/main/docs/backend-support-matrix.md).
45
+
46
+ ## Limits
47
+
48
+ - non-finite floats rejected
49
+ - metadata fragments must be non-empty and whitespace-free
50
+ - integers keep exact Python text (no silent `float` coercion)
51
+ - values must be representable in the current YAML 1.2+ surface
52
+
53
+ ## Verify
54
+
55
+ ```bash
56
+ uv sync --group dev
57
+ uv run --group dev pytest
58
+ ```
59
+
60
+ ## See also
61
+
62
+ - [Project README](https://github.com/koxudaxi/tstring-structured-data#readme)
63
+ - [Backend support matrix](https://github.com/koxudaxi/tstring-structured-data/blob/main/docs/backend-support-matrix.md)
@@ -0,0 +1,78 @@
1
+ [project]
2
+ name = "yaml-tstring"
3
+ version = "0.1.0"
4
+ description = "YAML renderer for t-string structured data templates"
5
+ readme = "README.md"
6
+ license = { text = "MIT" }
7
+ authors = [{ name = "Koudai Aono", email = "koxudaxi@gmail.com" }]
8
+ maintainers = [{ name = "Koudai Aono", email = "koxudaxi@gmail.com" }]
9
+ requires-python = ">=3.14"
10
+ dependencies = [
11
+ "tstring-bindings>=0.1.0",
12
+ "tstring-core>=0.1.0",
13
+ ]
14
+ keywords = ["pep750", "t-strings", "yaml", "template-strings", "structured-data"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Programming Language :: Python :: 3.14",
22
+ "Topic :: Software Development :: Libraries :: Python Modules",
23
+ ]
24
+
25
+ [project.urls]
26
+ Homepage = "https://github.com/koxudaxi/tstring-structured-data"
27
+ Repository = "https://github.com/koxudaxi/tstring-structured-data"
28
+ Documentation = "https://github.com/koxudaxi/tstring-structured-data/blob/main/yaml-tstring/README.md"
29
+ Changelog = "https://github.com/koxudaxi/tstring-structured-data/blob/main/CHANGELOG.md"
30
+ Issues = "https://github.com/koxudaxi/tstring-structured-data/issues"
31
+
32
+ [build-system]
33
+ requires = ["uv_build>=0.10.9,<0.11.0"]
34
+ build-backend = "uv_build"
35
+
36
+ [dependency-groups]
37
+ dev = [
38
+ "coverage[toml]>=7.8.0",
39
+ "inline-snapshot>=0.32.4",
40
+ "pytest>=8.4.0",
41
+ "ruff>=0.11.0",
42
+ "ty>=0.0.23",
43
+ ]
44
+
45
+ [tool.uv.sources]
46
+ tstring-bindings = { workspace = true }
47
+ tstring-core = { workspace = true }
48
+
49
+ [tool.uv.build-backend]
50
+ source-exclude = [".DS_Store"]
51
+ wheel-exclude = [".DS_Store"]
52
+
53
+ [tool.pytest.ini_options]
54
+ testpaths = ["tests"]
55
+
56
+ [tool.inline-snapshot]
57
+ format-command = "ruff format --stdin-filename {filename}"
58
+
59
+ [tool.coverage.run]
60
+ branch = true
61
+ source_pkgs = ["yaml_tstring", "tstring_core"]
62
+
63
+ [tool.coverage.report]
64
+ show_missing = true
65
+ fail_under = 100
66
+
67
+ [tool.ty.environment]
68
+ extra-paths = [
69
+ "../rust/python-bindings/python",
70
+ "../tstring-core/src",
71
+ "../examples",
72
+ ]
73
+
74
+ [tool.ruff]
75
+ target-version = "py314"
76
+
77
+ [tool.ruff.lint]
78
+ select = ["B", "E", "F", "I"]
@@ -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 YamlProfile, render_data, render_result, render_text
10
+
11
+ __all__ = [
12
+ "RenderResult",
13
+ "TemplateError",
14
+ "TemplateParseError",
15
+ "TemplateSemanticError",
16
+ "UnrepresentableValueError",
17
+ "YamlProfile",
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 RenderResult, YamlValue
8
+
9
+ type YamlProfile = Literal["1.2.2"]
10
+
11
+ _CONTRACT_VERSION = 1
12
+ _REQUIRED_SYMBOLS = {
13
+ "render_yaml",
14
+ "render_yaml_text",
15
+ "_render_yaml_result_payload",
16
+ }
17
+
18
+
19
+ class _RenderYaml(Protocol):
20
+ def __call__(self, template: Template, *, profile: YamlProfile) -> YamlValue: ...
21
+
22
+
23
+ class _RenderYamlText(Protocol):
24
+ def __call__(self, template: Template, *, profile: YamlProfile) -> str: ...
25
+
26
+
27
+ class _RenderYamlResultPayload(Protocol):
28
+ def __call__(
29
+ self, template: Template, *, profile: YamlProfile
30
+ ) -> tuple[str, YamlValue]: ...
31
+
32
+
33
+ def _bind_extension() -> tuple[_RenderYaml, _RenderYamlText, _RenderYamlResultPayload]:
34
+ version = getattr(_bindings, "__contract_version__", None)
35
+ if version != _CONTRACT_VERSION:
36
+ raise ImportError(
37
+ "yaml_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
+ "yaml_tstring could not bind required extension symbols: "
46
+ + ", ".join(missing)
47
+ )
48
+
49
+ return (
50
+ cast(_RenderYaml, _bindings.render_yaml),
51
+ cast(_RenderYamlText, _bindings.render_yaml_text),
52
+ cast(_RenderYamlResultPayload, _bindings._render_yaml_result_payload),
53
+ )
54
+
55
+
56
+ _render_yaml, _render_yaml_text, _render_yaml_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: YamlProfile | str | None) -> YamlProfile:
73
+ if profile is None or profile == "1.2.2":
74
+ return "1.2.2"
75
+ raise ValueError(
76
+ f"Unsupported YAML profile {profile!r}. Supported profiles: '1.2.2'."
77
+ )
78
+
79
+
80
+ def render_data(
81
+ template: Template, *, profile: YamlProfile | str | None = None
82
+ ) -> YamlValue:
83
+ checked = _validate_template(template, "render_data")
84
+ return _render_yaml(checked, profile=_resolve_profile(profile))
85
+
86
+
87
+ def render_text(template: Template, *, profile: YamlProfile | str | None = None) -> str:
88
+ checked = _validate_template(template, "render_text")
89
+ return _render_yaml_text(checked, profile=_resolve_profile(profile))
90
+
91
+
92
+ def render_result(
93
+ template: Template, *, profile: YamlProfile | str | None = None
94
+ ) -> RenderResult[YamlValue]:
95
+ checked = _validate_template(template, "render_result")
96
+ text, data = _render_yaml_result_payload(checked, profile=_resolve_profile(profile))
97
+ return RenderResult(text=text, data=data)
98
+
99
+
100
+ __all__ = [
101
+ "RenderResult",
102
+ "YamlProfile",
103
+ "render_data",
104
+ "render_result",
105
+ "render_text",
106
+ ]
@@ -0,0 +1,3 @@
1
+ from tstring_core import FragmentGroup, Slot, SlotContext
2
+
3
+ __all__ = ["FragmentGroup", "Slot", "SlotContext"]
@@ -0,0 +1 @@
1
+ # Marker file for PEP 561 typing support.