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.
- yaml_tstring-0.1.0/PKG-INFO +90 -0
- yaml_tstring-0.1.0/README.md +63 -0
- yaml_tstring-0.1.0/pyproject.toml +78 -0
- yaml_tstring-0.1.0/src/yaml_tstring/__init__.py +21 -0
- yaml_tstring-0.1.0/src/yaml_tstring/_errors.py +15 -0
- yaml_tstring-0.1.0/src/yaml_tstring/_runtime.py +106 -0
- yaml_tstring-0.1.0/src/yaml_tstring/_slots.py +3 -0
- yaml_tstring-0.1.0/src/yaml_tstring/py.typed +1 -0
|
@@ -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 @@
|
|
|
1
|
+
# Marker file for PEP 561 typing support.
|