Skip to content

Commit a395455

Browse files
authored
Merge pull request #7 from posit-dev/pr/core-polish
yaml12: native Yaml wrapper + tag/formatting polish
2 parents ce95d12 + ce5f28e commit a395455

File tree

14 files changed

+756
-271
lines changed

14 files changed

+756
-271
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ YAML and parses the same way.
2121
The package ships prebuilt wheels for Python 3.10+ on common platforms. Install from PyPI:
2222

2323
```bash
24-
pip install yaml12
24+
pip install py-yaml12
2525
```
2626

2727
## Development install

docs/index.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ For almost every use case, `yaml12` lets you work with plain builtin Python type
1414

1515
## Installation
1616

17-
The project targets Python 3.10+ and builds via `maturin` (Rust
18-
toolchain required). From the repository root:
17+
Install from PyPI:
18+
19+
```bash
20+
pip install py-yaml12
21+
```
22+
23+
For development, install from the repository root (requires Python 3.10+ and a Rust toolchain):
1924

2025
```bash
2126
python -m venv .venv
@@ -133,7 +138,7 @@ assert parsed == {
133138

134139
Tags, custom handlers, and non-string mapping keys work without extra
135140
setup when you need them. Nodes that can’t be represented as plain
136-
Python types are wrapped in `Yaml` (a small frozen dataclass). You’ll
141+
Python types are wrapped in `Yaml` (a small immutable wrapper class). You’ll
137142
only see `Yaml` when:
138143

139144
- A tagged node has no matching handler; inspect `.value` and `.tag`.

docs/reference/format_yaml.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ and mapping keys; scalar core tags (`!!str`, `!!int`, `!!bool`,
66
`!!float`, `!!null`, `!!seq`, `!!map`) are dropped on emit because they
77
add no extra information.
88

9+
Mappings are emitted in insertion order (the order you inserted keys into the Python
10+
mapping).
11+
912
## Usage
1013

1114
```python

docs/reference/parse_yaml.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ read_yaml(path, multi=False, handlers=None)
1313

1414
## Arguments
1515

16-
- text: `str` or sequence of `str`; sequence items are joined with
17-
`"\n"`. When empty, returns `None` (or `[]` when `multi=True`).
16+
- text: `str` or iterable of `str`; chunks are concatenated exactly as provided (no implicit
17+
separators are inserted). When empty, returns `None` (or `[]` when `multi=True`).
1818
- path: `str`, `os.PathLike`, or readable object yielding `str` or
1919
UTF-8 `bytes`.
2020
- multi: When `True`, parse the whole stream and return a list of
@@ -31,6 +31,9 @@ handler (including informative core tags such as `!!timestamp` or
3131
`!!binary`) become `Yaml` objects. Unhashable mapping keys are wrapped
3232
in `Yaml` so they remain hashable.
3333

34+
Mapping key order is preserved in the returned `dict` (in the same order keys appear in
35+
the YAML input).
36+
3437
## Examples
3538

3639
```python
@@ -60,6 +63,6 @@ lines = [
6063
"---",
6164
"# Body that is not YAML",
6265
]
63-
parse_yaml(lines)
66+
parse_yaml("\n".join(lines))
6467
# {'title': 'Front matter only', 'params': {'answer': 42}}
6568
```

docs/tags.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ always starts with `!`, and it appears before the node’s value; it is
1212
not part of the scalar text itself.
1313

1414
`yaml12` preserves tags by wrapping nodes in a `Yaml` object. A `Yaml`
15-
is a small frozen dataclass that carries the parsed `value` (a regular
15+
is a small immutable wrapper class that carries the parsed `value` (a regular
1616
Python type) and the `tag` string. Here is an example of parsing a tagged scalar:
1717

1818
```python
@@ -158,7 +158,7 @@ true: true
158158
159159
When a key can’t be represented directly as a plain Python dict key,
160160
`yaml12` wraps it in `Yaml`. That preserves the original key and makes
161-
it hashable (with equality defined by structure), so it can safely live
161+
it hashable (with equality defined by structure, including mapping key order), so it can safely live
162162
in a Python `dict`:
163163

164164
```python
@@ -277,7 +277,7 @@ rmd_lines = [
277277
"---",
278278
"# Body that is not YAML",
279279
]
280-
frontmatter = parse_yaml(rmd_lines)
280+
frontmatter = parse_yaml("\n".join(rmd_lines))
281281
assert frontmatter == {"title": "Front matter only", "params": {"answer": 42}}
282282
```
283283

@@ -417,15 +417,17 @@ assert parse_yaml(text)["item"].tag == "tag:example.com,2024:widgets/gizmo"
417417

418418
### Tag URIs
419419

420-
To bypass handle resolution, use `!<...>` with a valid URI-like string:
420+
To specify a verbatim tag, use `!<...>` with a valid URI-like string. For
421+
simple tags like `gizmo`, `yaml12` normalizes `!<gizmo>` to the local tag
422+
form `!gizmo`:
421423

422424
```python
423425
parsed = parse_yaml("""
424426
%TAG ! tag:example.com,2024:widgets/
425427
---
426428
item: !<gizmo> foo
427429
""")
428-
assert parsed["item"].tag == "gizmo"
430+
assert parsed["item"].tag == "!gizmo"
429431
```
430432

431433
### Core schema tags
@@ -472,8 +474,8 @@ def binary_handler(value):
472474
converted = parse_yaml(
473475
yaml_text,
474476
handlers={
475-
"tag:yaml.org,2002:timestamp": ts_handler,
476-
"tag:yaml.org,2002:binary": binary_handler,
477+
"!!timestamp": ts_handler,
478+
"!!binary": binary_handler,
477479
},
478480
)
479481
assert isinstance(converted[0], datetime) and isinstance(converted[2], (bytes, bytearray))

docs/usage.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ Python result (`parse_yaml()` with defaults):
257257
spaces.
258258
- All JSON is valid YAML.
259259
- Sequences stay Python lists; there is no vector "simplification."
260+
- Mapping (dict) key order is preserved on load and emit (in the order keys appear in
261+
the YAML input, and in the insertion order of Python mappings you format).
260262
- Block scalars (`|`, `>`) always produce strings.
261263
- Booleans are only `true`/`false`; `null` maps to `None`.
262264
- Numbers can be signed, scientific, hex (`0x`), octal (`0o`), `.inf`,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ requires = ["maturin>=1.9,<2.0"]
33
build-backend = "maturin"
44

55
[project]
6-
name = "yaml12"
6+
name = "py-yaml12"
77
description = "A modern YAML 1.2 parser and emitter for Python, written in Rust."
88
readme = "README.md"
99
license = { file = "LICENSE" }

0 commit comments

Comments
 (0)