yarutsk 0.0.1__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,132 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ tags: ["v*"]
7
+ pull_request:
8
+
9
+ env:
10
+ PYTHON_VERSIONS: "3.9 3.10 3.11 3.12 3.13 3.14"
11
+
12
+ jobs:
13
+ # ── Tests ──────────────────────────────────────────────────────────────────
14
+ test:
15
+ name: Test (${{ matrix.os }}, Python ${{ matrix.python-version }})
16
+ runs-on: ${{ matrix.os }}
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ os: [ubuntu-latest, macos-latest, windows-latest]
21
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
22
+
23
+ steps:
24
+ - uses: actions/checkout@v6
25
+ with:
26
+ submodules: recursive
27
+
28
+ - name: Install Rust (nightly)
29
+ uses: dtolnay/rust-toolchain@nightly
30
+
31
+ - name: Install uv
32
+ uses: astral-sh/setup-uv@v7
33
+ with:
34
+ python-version: ${{ matrix.python-version }}
35
+ enable-cache: true
36
+
37
+ - name: Install dev dependencies
38
+ run: uv sync --group dev
39
+
40
+ - name: Build extension
41
+ run: uv run maturin develop
42
+
43
+ - name: Core tests
44
+ run: uv run pytest tests/test_yarutsk.py tests/test_sort.py -v
45
+
46
+ - name: yaml-test-suite compliance
47
+ run: uv run pytest tests/test_yaml_suite.py -q --tb=short
48
+
49
+ # ── Rust lint ──────────────────────────────────────────────────────────────
50
+ lint:
51
+ name: Rust lint
52
+ runs-on: ubuntu-latest
53
+ steps:
54
+ - uses: actions/checkout@v6
55
+
56
+ - name: Install Rust (nightly)
57
+ uses: dtolnay/rust-toolchain@nightly
58
+ with:
59
+ components: clippy
60
+
61
+ - name: Clippy
62
+ run: cargo clippy -- -D warnings
63
+
64
+ # ── Build release wheels ───────────────────────────────────────────────────
65
+ build-wheels:
66
+ name: Wheels (${{ matrix.os }})
67
+ if: startsWith(github.ref, 'refs/tags/v')
68
+ needs: [test, lint]
69
+ runs-on: ${{ matrix.os }}
70
+ strategy:
71
+ matrix:
72
+ os: [ubuntu-latest, macos-latest, windows-latest]
73
+
74
+ steps:
75
+ - uses: actions/checkout@v6
76
+
77
+ - name: Install Rust (nightly)
78
+ uses: dtolnay/rust-toolchain@nightly
79
+
80
+ - name: Set up Python interpreters
81
+ uses: actions/setup-python@v6
82
+ with:
83
+ python-version: |
84
+ 3.9
85
+ 3.10
86
+ 3.11
87
+ 3.12
88
+ 3.13
89
+ 3.14
90
+
91
+ - name: Build wheels
92
+ uses: PyO3/maturin-action@v1
93
+ with:
94
+ command: build
95
+ args: >-
96
+ --release --out dist
97
+ --interpreter ${{ env.PYTHON_VERSIONS }}
98
+ ${{ matrix.os == 'macos-latest' && '--target universal2-apple-darwin' || '' }}
99
+ manylinux: ${{ matrix.os == 'ubuntu-latest' && 'auto' || '' }}
100
+ rust-toolchain: nightly
101
+
102
+ - name: Build sdist
103
+ if: matrix.os == 'ubuntu-latest'
104
+ uses: PyO3/maturin-action@v1
105
+ with:
106
+ command: sdist
107
+ args: --out dist
108
+
109
+ - uses: actions/upload-artifact@v7
110
+ with:
111
+ name: wheels-${{ matrix.os }}
112
+ path: dist/
113
+
114
+ # ── Publish to PyPI ────────────────────────────────────────────────────────
115
+ publish:
116
+ name: Publish to PyPI
117
+ if: startsWith(github.ref, 'refs/tags/v')
118
+ needs: build-wheels
119
+ runs-on: ubuntu-latest
120
+ environment: pypi
121
+ permissions:
122
+ id-token: write
123
+
124
+ steps:
125
+ - uses: actions/download-artifact@v8
126
+ with:
127
+ pattern: wheels-*
128
+ merge-multiple: true
129
+ path: dist/
130
+
131
+ - name: Publish
132
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,23 @@
1
+ # Rust
2
+ /target/
3
+ Cargo.lock
4
+
5
+ # Python
6
+ .venv/
7
+ __pycache__/
8
+ *.py[cod]
9
+ *.pyd
10
+ *.so
11
+ *.egg-info/
12
+ dist/
13
+ .pytest_cache/
14
+ .benchmark/
15
+
16
+ # maturin / build output
17
+ *.whl
18
+
19
+ # Editor
20
+ .idea/
21
+ .vscode/
22
+ *.swp
23
+ *.swo
@@ -0,0 +1,3 @@
1
+ [submodule "yaml-test-suite"]
2
+ path = yaml-test-suite
3
+ url = https://github.com/yaml/yaml-test-suite
@@ -0,0 +1,164 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "arraydeque"
7
+ version = "0.5.1"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
10
+
11
+ [[package]]
12
+ name = "equivalent"
13
+ version = "1.0.2"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
16
+
17
+ [[package]]
18
+ name = "hashbrown"
19
+ version = "0.17.0"
20
+ source = "registry+https://github.com/rust-lang/crates.io-index"
21
+ checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
22
+
23
+ [[package]]
24
+ name = "heck"
25
+ version = "0.5.0"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
28
+
29
+ [[package]]
30
+ name = "indexmap"
31
+ version = "2.14.0"
32
+ source = "registry+https://github.com/rust-lang/crates.io-index"
33
+ checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
34
+ dependencies = [
35
+ "equivalent",
36
+ "hashbrown",
37
+ ]
38
+
39
+ [[package]]
40
+ name = "libc"
41
+ version = "0.2.184"
42
+ source = "registry+https://github.com/rust-lang/crates.io-index"
43
+ checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
44
+
45
+ [[package]]
46
+ name = "once_cell"
47
+ version = "1.21.4"
48
+ source = "registry+https://github.com/rust-lang/crates.io-index"
49
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
50
+
51
+ [[package]]
52
+ name = "portable-atomic"
53
+ version = "1.13.1"
54
+ source = "registry+https://github.com/rust-lang/crates.io-index"
55
+ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
56
+
57
+ [[package]]
58
+ name = "proc-macro2"
59
+ version = "1.0.106"
60
+ source = "registry+https://github.com/rust-lang/crates.io-index"
61
+ checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
62
+ dependencies = [
63
+ "unicode-ident",
64
+ ]
65
+
66
+ [[package]]
67
+ name = "pyo3"
68
+ version = "0.28.3"
69
+ source = "registry+https://github.com/rust-lang/crates.io-index"
70
+ checksum = "91fd8e38a3b50ed1167fb981cd6fd60147e091784c427b8f7183a7ee32c31c12"
71
+ dependencies = [
72
+ "indexmap",
73
+ "libc",
74
+ "once_cell",
75
+ "portable-atomic",
76
+ "pyo3-build-config",
77
+ "pyo3-ffi",
78
+ "pyo3-macros",
79
+ ]
80
+
81
+ [[package]]
82
+ name = "pyo3-build-config"
83
+ version = "0.28.3"
84
+ source = "registry+https://github.com/rust-lang/crates.io-index"
85
+ checksum = "e368e7ddfdeb98c9bca7f8383be1648fd84ab466bf2bc015e94008db6d35611e"
86
+ dependencies = [
87
+ "target-lexicon",
88
+ ]
89
+
90
+ [[package]]
91
+ name = "pyo3-ffi"
92
+ version = "0.28.3"
93
+ source = "registry+https://github.com/rust-lang/crates.io-index"
94
+ checksum = "7f29e10af80b1f7ccaf7f69eace800a03ecd13e883acfacc1e5d0988605f651e"
95
+ dependencies = [
96
+ "libc",
97
+ "pyo3-build-config",
98
+ ]
99
+
100
+ [[package]]
101
+ name = "pyo3-macros"
102
+ version = "0.28.3"
103
+ source = "registry+https://github.com/rust-lang/crates.io-index"
104
+ checksum = "df6e520eff47c45997d2fc7dd8214b25dd1310918bbb2642156ef66a67f29813"
105
+ dependencies = [
106
+ "proc-macro2",
107
+ "pyo3-macros-backend",
108
+ "quote",
109
+ "syn",
110
+ ]
111
+
112
+ [[package]]
113
+ name = "pyo3-macros-backend"
114
+ version = "0.28.3"
115
+ source = "registry+https://github.com/rust-lang/crates.io-index"
116
+ checksum = "c4cdc218d835738f81c2338f822078af45b4afdf8b2e33cbb5916f108b813acb"
117
+ dependencies = [
118
+ "heck",
119
+ "proc-macro2",
120
+ "pyo3-build-config",
121
+ "quote",
122
+ "syn",
123
+ ]
124
+
125
+ [[package]]
126
+ name = "quote"
127
+ version = "1.0.45"
128
+ source = "registry+https://github.com/rust-lang/crates.io-index"
129
+ checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
130
+ dependencies = [
131
+ "proc-macro2",
132
+ ]
133
+
134
+ [[package]]
135
+ name = "syn"
136
+ version = "2.0.117"
137
+ source = "registry+https://github.com/rust-lang/crates.io-index"
138
+ checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
139
+ dependencies = [
140
+ "proc-macro2",
141
+ "quote",
142
+ "unicode-ident",
143
+ ]
144
+
145
+ [[package]]
146
+ name = "target-lexicon"
147
+ version = "0.13.5"
148
+ source = "registry+https://github.com/rust-lang/crates.io-index"
149
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
150
+
151
+ [[package]]
152
+ name = "unicode-ident"
153
+ version = "1.0.24"
154
+ source = "registry+https://github.com/rust-lang/crates.io-index"
155
+ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
156
+
157
+ [[package]]
158
+ name = "yarutsk"
159
+ version = "0.0.1"
160
+ dependencies = [
161
+ "arraydeque",
162
+ "indexmap",
163
+ "pyo3",
164
+ ]
@@ -0,0 +1,19 @@
1
+ [package]
2
+ name = "yarutsk"
3
+ version = "0.0.1"
4
+ edition = "2024"
5
+ description = "A YAML round-trip library that preserves comments and insertion order"
6
+ license = "MIT"
7
+ readme = "README.md"
8
+
9
+ [lib]
10
+ name = "yarutsk"
11
+ crate-type = ["cdylib"]
12
+
13
+ [dependencies]
14
+ indexmap = "2"
15
+ pyo3 = { version = "0.28", features = ["extension-module", "indexmap"] }
16
+ arraydeque = "0.5"
17
+
18
+ [profile.release]
19
+ lto = true
yarutsk-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 theyugin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
yarutsk-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.4
2
+ Name: yarutsk
3
+ Version: 0.0.1
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: Programming Language :: Python :: Implementation :: CPython
8
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
9
+ Classifier: Programming Language :: Rust
10
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
11
+ Classifier: Topic :: Text Processing :: Markup
12
+ License-File: LICENSE
13
+ Summary: A YAML round-trip library that preserves comments and insertion order
14
+ License: MIT
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
17
+ Project-URL: Homepage, https://github.com/theyugin/yarutsk
18
+ Project-URL: Repository, https://github.com/theyugin/yarutsk
19
+
20
+ # yarutsk
21
+
22
+ A Python YAML library that round-trips documents while preserving **comments** and **insertion order**.
23
+
24
+ ## What it does
25
+
26
+ Most YAML libraries silently drop comments on load. yarutsk keeps them attached to their keys — both inline (`key: value # like this`) and block-level (`# above a key`) — so a load → modify → dump cycle leaves the rest of the file intact.
27
+
28
+ ```python
29
+ import io
30
+ import yarutsk
31
+
32
+ doc = yarutsk.load(io.StringIO("""
33
+ # database config
34
+ host: localhost # primary
35
+ port: 5432
36
+ """))
37
+
38
+ doc["port"] = 5433
39
+
40
+ out = io.StringIO()
41
+ doc.dump(out)
42
+ print(out.getvalue())
43
+ # # database config
44
+ # host: localhost # primary
45
+ # port: 5433
46
+ ```
47
+
48
+ ## Installation
49
+
50
+ Built with [Maturin](https://github.com/PyO3/maturin). From the repo root:
51
+
52
+ ```bash
53
+ pip install maturin
54
+ maturin develop
55
+ ```
56
+
57
+ ## API
58
+
59
+ ```python
60
+ # Load
61
+ doc = yarutsk.load(stream) # first document
62
+ docs = yarutsk.load_all(stream) # all documents
63
+
64
+ # Dump
65
+ yarutsk.dump(doc, stream)
66
+ yarutsk.dump_all(docs, stream)
67
+
68
+ # Mapping access
69
+ doc["key"] # get (returns native Python type or PyYamlDocument)
70
+ doc["key"] = value # set
71
+ "key" in doc # contains
72
+ doc.keys() # insertion-ordered list
73
+ doc.to_dict() # deep conversion to plain Python dict/list
74
+
75
+ # Sequence access
76
+ doc[0] # get by index (negative indices supported)
77
+ doc[0] = value # set by index
78
+ len(doc) # item count
79
+
80
+ # Comments
81
+ doc.get_comment_inline("key") # -> str | None
82
+ doc.get_comment_before("key") # -> str | None
83
+ doc.set_comment_inline("key", text)
84
+ doc.set_comment_before("key", text)
85
+
86
+ # Sorting — mappings
87
+ doc.sort_keys() # alphabetical, in-place
88
+ doc.sort_keys(reverse=True) # reverse alphabetical
89
+ doc.sort_keys(key=lambda k: len(k)) # custom key function on key strings
90
+ doc.sort_keys(recursive=True) # also sort all nested mappings
91
+
92
+ # Sorting — sequences
93
+ doc.sort() # natural order, in-place
94
+ doc.sort(reverse=True)
95
+ doc.sort(key=lambda v: len(v)) # custom key function on item values
96
+ ```
97
+
98
+ Sorting preserves all comments — each entry or item carries its inline and before-key comments with it when reordered.
99
+
100
+ ## Running tests
101
+
102
+ The repo contains three test suites. You need Rust (nightly) and Python 3.9+ with [uv](https://github.com/astral-sh/uv).
103
+
104
+ ```bash
105
+ # 1. Clone with the yaml-test-suite submodule
106
+ git clone --recurse-submodules https://github.com/anomalyco/yarutsk
107
+ cd yarutsk
108
+
109
+ # 2. Create a virtual environment and install dev dependencies
110
+ # (includes pytest, pyyaml, ruamel-yaml, pytest-benchmark)
111
+ uv sync --group dev
112
+
113
+ # 3. Build the extension in dev (debug) mode
114
+ uv run maturin develop
115
+
116
+ # 4. Run the suites
117
+ uv run pytest tests/test_yarutsk.py -v # core library tests
118
+ uv run pytest tests/test_sort.py -v # key-ordering tests
119
+ uv run pytest tests/test_yaml_suite.py -q # yaml-test-suite compliance
120
+ ```
121
+
122
+ `test_yaml_suite.py` requires the `yaml-test-suite` submodule and PyYAML (both available after the steps above). Round-trip tests that fail due to YAML normalisation (flow→block, anchors, folded scalars) are marked `xfail` and do not count as failures.
123
+
124
+ ## Benchmarks
125
+
126
+ Benchmarks compare yarutsk against PyYAML and ruamel.yaml using [pytest-benchmark](https://pytest-benchmark.readthedocs.io/):
127
+
128
+ ```bash
129
+ uv run pytest benchmarks/ -v --benchmark-min-rounds=10
130
+ ```
131
+
132
+ ruamel.yaml is the closest analogue to yarutsk (it also preserves comments), so it is the primary point of comparison.
133
+
134
+ ## Internals
135
+
136
+ The scanner and parser are vendored from [yaml-rust2](https://github.com/Ethiraric/yaml-rust2) (MIT licensed) with one targeted modification: the comment-skipping loop in the scanner now emits `Comment` tokens instead of discarding them. Everything else — block/flow parsing, scalar type coercion, multi-document support — comes from yaml-rust2 unchanged. The builder layer wires those tokens to the data model, and a hand-written block-style emitter serialises it back out.
137
+
138
+ ## Disclaimer
139
+
140
+ This library was created with [Claude Code](https://claude.ai/code) (Anthropic). The design, implementation, tests, and this README were written by Claude under human direction.
141
+
@@ -0,0 +1,121 @@
1
+ # yarutsk
2
+
3
+ A Python YAML library that round-trips documents while preserving **comments** and **insertion order**.
4
+
5
+ ## What it does
6
+
7
+ Most YAML libraries silently drop comments on load. yarutsk keeps them attached to their keys — both inline (`key: value # like this`) and block-level (`# above a key`) — so a load → modify → dump cycle leaves the rest of the file intact.
8
+
9
+ ```python
10
+ import io
11
+ import yarutsk
12
+
13
+ doc = yarutsk.load(io.StringIO("""
14
+ # database config
15
+ host: localhost # primary
16
+ port: 5432
17
+ """))
18
+
19
+ doc["port"] = 5433
20
+
21
+ out = io.StringIO()
22
+ doc.dump(out)
23
+ print(out.getvalue())
24
+ # # database config
25
+ # host: localhost # primary
26
+ # port: 5433
27
+ ```
28
+
29
+ ## Installation
30
+
31
+ Built with [Maturin](https://github.com/PyO3/maturin). From the repo root:
32
+
33
+ ```bash
34
+ pip install maturin
35
+ maturin develop
36
+ ```
37
+
38
+ ## API
39
+
40
+ ```python
41
+ # Load
42
+ doc = yarutsk.load(stream) # first document
43
+ docs = yarutsk.load_all(stream) # all documents
44
+
45
+ # Dump
46
+ yarutsk.dump(doc, stream)
47
+ yarutsk.dump_all(docs, stream)
48
+
49
+ # Mapping access
50
+ doc["key"] # get (returns native Python type or PyYamlDocument)
51
+ doc["key"] = value # set
52
+ "key" in doc # contains
53
+ doc.keys() # insertion-ordered list
54
+ doc.to_dict() # deep conversion to plain Python dict/list
55
+
56
+ # Sequence access
57
+ doc[0] # get by index (negative indices supported)
58
+ doc[0] = value # set by index
59
+ len(doc) # item count
60
+
61
+ # Comments
62
+ doc.get_comment_inline("key") # -> str | None
63
+ doc.get_comment_before("key") # -> str | None
64
+ doc.set_comment_inline("key", text)
65
+ doc.set_comment_before("key", text)
66
+
67
+ # Sorting — mappings
68
+ doc.sort_keys() # alphabetical, in-place
69
+ doc.sort_keys(reverse=True) # reverse alphabetical
70
+ doc.sort_keys(key=lambda k: len(k)) # custom key function on key strings
71
+ doc.sort_keys(recursive=True) # also sort all nested mappings
72
+
73
+ # Sorting — sequences
74
+ doc.sort() # natural order, in-place
75
+ doc.sort(reverse=True)
76
+ doc.sort(key=lambda v: len(v)) # custom key function on item values
77
+ ```
78
+
79
+ Sorting preserves all comments — each entry or item carries its inline and before-key comments with it when reordered.
80
+
81
+ ## Running tests
82
+
83
+ The repo contains three test suites. You need Rust (nightly) and Python 3.9+ with [uv](https://github.com/astral-sh/uv).
84
+
85
+ ```bash
86
+ # 1. Clone with the yaml-test-suite submodule
87
+ git clone --recurse-submodules https://github.com/anomalyco/yarutsk
88
+ cd yarutsk
89
+
90
+ # 2. Create a virtual environment and install dev dependencies
91
+ # (includes pytest, pyyaml, ruamel-yaml, pytest-benchmark)
92
+ uv sync --group dev
93
+
94
+ # 3. Build the extension in dev (debug) mode
95
+ uv run maturin develop
96
+
97
+ # 4. Run the suites
98
+ uv run pytest tests/test_yarutsk.py -v # core library tests
99
+ uv run pytest tests/test_sort.py -v # key-ordering tests
100
+ uv run pytest tests/test_yaml_suite.py -q # yaml-test-suite compliance
101
+ ```
102
+
103
+ `test_yaml_suite.py` requires the `yaml-test-suite` submodule and PyYAML (both available after the steps above). Round-trip tests that fail due to YAML normalisation (flow→block, anchors, folded scalars) are marked `xfail` and do not count as failures.
104
+
105
+ ## Benchmarks
106
+
107
+ Benchmarks compare yarutsk against PyYAML and ruamel.yaml using [pytest-benchmark](https://pytest-benchmark.readthedocs.io/):
108
+
109
+ ```bash
110
+ uv run pytest benchmarks/ -v --benchmark-min-rounds=10
111
+ ```
112
+
113
+ ruamel.yaml is the closest analogue to yarutsk (it also preserves comments), so it is the primary point of comparison.
114
+
115
+ ## Internals
116
+
117
+ The scanner and parser are vendored from [yaml-rust2](https://github.com/Ethiraric/yaml-rust2) (MIT licensed) with one targeted modification: the comment-skipping loop in the scanner now emits `Comment` tokens instead of discarding them. Everything else — block/flow parsing, scalar type coercion, multi-document support — comes from yaml-rust2 unchanged. The builder layer wires those tokens to the data model, and a hand-written block-style emitter serialises it back out.
118
+
119
+ ## Disclaimer
120
+
121
+ This library was created with [Claude Code](https://claude.ai/code) (Anthropic). The design, implementation, tests, and this README were written by Claude under human direction.
@@ -0,0 +1,49 @@
1
+ Third-Party Notices
2
+ ===================
3
+
4
+ This project incorporates source code from the following third-party libraries.
5
+
6
+
7
+ yaml-rust2
8
+ ----------
9
+ Source: https://github.com/Ethiraric/yaml-rust2
10
+ Files: src/scanner.rs, src/parser.rs, src/char_traits.rs, src/debug.rs
11
+ License: MIT OR Apache-2.0 (at your option)
12
+
13
+ Copyright (c) 2015 Chen Yuheng
14
+ Copyright (c) 2023 Ethiraric
15
+
16
+ MIT License
17
+ -----------
18
+ Permission is hereby granted, free of charge, to any person obtaining a copy
19
+ of this software and associated documentation files (the "Software"), to deal
20
+ in the Software without restriction, including without limitation the rights
21
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22
+ copies of the Software, and to permit persons to whom the Software is
23
+ furnished to do so, subject to the following conditions:
24
+
25
+ The above copyright notice and this permission notice shall be included in all
26
+ copies or substantial portions of the Software.
27
+
28
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34
+ SOFTWARE.
35
+
36
+
37
+ Modifications
38
+ -------------
39
+ The vendored files have been modified as follows:
40
+
41
+ scanner.rs — Added `Comment(String)` variant to `TokenType`. Modified
42
+ `skip_to_next_token` and `skip_ws_to_eol` to emit Comment
43
+ tokens instead of discarding comment text.
44
+
45
+ parser.rs — Added `pending_comments` field and `drain_comments()` method
46
+ to `Parser`. Modified `scan_next_token` to collect Comment
47
+ tokens into `pending_comments` rather than returning them.
48
+
49
+ char_traits.rs, debug.rs — Vendored verbatim; no modifications.