Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
59380fc
Add agent skills to .gitignore
nathanjmcdougall May 12, 2026
1033b98
Add design doc
nathanjmcdougall May 12, 2026
053030d
feat: add yamlpath, yamlpatch, serde_yaml dependencies
nathanjmcdougall May 12, 2026
5295f00
feat: add Python ↔ serde_yaml value conversion
nathanjmcdougall May 12, 2026
989c5ed
feat: add core type bindings (Location, FeatureKind, Component, Route…
nathanjmcdougall May 12, 2026
f655247
feat: add core Document binding with query and extract
nathanjmcdougall May 12, 2026
51b5296
feat: add Op, Patch, and apply_patches bindings
nathanjmcdougall May 12, 2026
afe18df
feat: add error hierarchy
nathanjmcdougall May 12, 2026
0049940
Add Rust config to .gitignore
nathanjmcdougall May 12, 2026
d33bf04
feat: add Python Document class with querying and parse_value
nathanjmcdougall May 12, 2026
3fe5a4a
feat: add Document patch operations
nathanjmcdougall May 12, 2026
d244810
feat: add Editor context manager
nathanjmcdougall May 12, 2026
06fd02f
feat: add public API, convenience functions, and type stubs
nathanjmcdougall May 12, 2026
d524dcb
test: add round-trip preservation tests
nathanjmcdougall May 12, 2026
ecb5bd5
Fix ruff violations and replace assert guards with RuntimeError\n\n- …
nathanjmcdougall May 12, 2026
0a2a9cb
Fix TYPE_CHECKING imports and remove dead code\n\n- Replace __import_…
nathanjmcdougall May 12, 2026
a5c090a
Fix ruff violations from stricter config\n\n- Add docstrings to all p…
nathanjmcdougall May 12, 2026
a9903f8
Replace placeholder test with real invalid YAML test\n\ntest_parse_in…
nathanjmcdougall May 12, 2026
cef62ae
Fix fragile empty-container check in prune logic\n\nReplace `parent_v…
nathanjmcdougall May 12, 2026
6732454
Remove redundant route construction in Document methods\n\nReuse the …
nathanjmcdougall May 12, 2026
fa2003c
Add __eq__ and __hash__ to Document\n\nDocument is immutable, so it s…
nathanjmcdougall May 12, 2026
4e53801
Improve Op.merge_into error message for non-dict input\n\nReplace con…
nathanjmcdougall May 12, 2026
6a30253
Support tuple in py_to_yaml_value conversion\n\nPython tuples are now…
nathanjmcdougall May 12, 2026
046e592
Use bare strings for single-key containment checks in tests\n\nReplac…
nathanjmcdougall May 12, 2026
88186cd
Fix .pyi stub for FeatureKind enum\n\nUse ClassVar for variant attrib…
nathanjmcdougall May 12, 2026
3ac9126
Add __eq__ and __hash__ to all value types\n\nLocation, FeatureKind, …
nathanjmcdougall May 12, 2026
9321e61
Wrap Rust errors at the Python boundary\n\nAll _core.apply_patches ca…
nathanjmcdougall May 12, 2026
ef8147a
Batch extend_list and remove_from_list operations\n\nBoth methods now…
nathanjmcdougall May 12, 2026
ce927ad
Move parse_value to Document method to avoid reparse\n\nparse_value i…
nathanjmcdougall May 12, 2026
ac3c774
Write README with usage examples and documented limitations\n\nCovers…
nathanjmcdougall May 12, 2026
cbb7745
Remove copy-pasted ruff.toml config from unrelated project
nathanjmcdougall May 12, 2026
f0a5f97
Remove unused serde_json dependency
nathanjmcdougall May 12, 2026
f3c6083
Remove unused serde dependency
nathanjmcdougall May 12, 2026
5d22a17
Narrow Document.__init__ to catch only ValueError and RuntimeError
nathanjmcdougall May 12, 2026
20ffea9
Raise PatchError for integer keys in upsert path creation
nathanjmcdougall May 12, 2026
45aff07
Inline _normalize_keys in Editor instead of importing private function
nathanjmcdougall May 12, 2026
19949e0
Let TypeError propagate from Document.__contains__
nathanjmcdougall May 12, 2026
b942f39
Remove redundant query_exists pre-checks in __getitem__ and query
nathanjmcdougall May 12, 2026
0c1211e
Add Rust-level unit tests for convert module
nathanjmcdougall May 12, 2026
86cdfff
Make Op.__repr__ Python-idiomatic
nathanjmcdougall May 12, 2026
5be15b1
Add __repr__ to Document and Editor
nathanjmcdougall May 12, 2026
3ee051e
Detect external file modifications in Editor
nathanjmcdougall May 12, 2026
3f04bc3
Use set for O(1) lookups in remove_from_list
nathanjmcdougall May 12, 2026
e3ef51d
Remove unused standalone parse_value function
nathanjmcdougall May 12, 2026
71868c7
Fix __exit__ type annotations
nathanjmcdougall May 12, 2026
bf91594
Add tests for critical edge cases
nathanjmcdougall May 12, 2026
eac2314
Preserve exception chain in _apply
nathanjmcdougall May 12, 2026
20efedf
Promote query_pretty and has_anchors to public Document API
nathanjmcdougall May 12, 2026
93720c1
Validate Location start <= end in constructor
nathanjmcdougall May 12, 2026
6a80183
Document that Document equality is source-text-based
nathanjmcdougall May 12, 2026
cff32ef
Add ty type checker via usethis
nathanjmcdougall May 12, 2026
0b73ee5
Add coverage.py via usethis
nathanjmcdougall May 12, 2026
882170d
Add codespell via usethis
nathanjmcdougall May 12, 2026
75c6d6f
Add deptry via usethis
nathanjmcdougall May 12, 2026
dde9736
Add import-linter via usethis
nathanjmcdougall May 12, 2026
0982026
Add pyproject-fmt via usethis
nathanjmcdougall May 12, 2026
72bdcd5
Move import-linter config to .importlinter file
nathanjmcdougall May 13, 2026
132020a
Make _core.pyi stub fields read-only properties
nathanjmcdougall May 13, 2026
579f827
Eliminate double-parsing on every Document mutation
nathanjmcdougall May 13, 2026
3d4529d
Simplify remove_from_list value matching
nathanjmcdougall May 13, 2026
60c1b1a
Replace mtime-based external modification check with content comparison
nathanjmcdougall May 13, 2026
c030662
Fix stale state in Editor on __enter__ parse failure
nathanjmcdougall May 13, 2026
9b86a51
Standardize exception chaining to use 'from None'
nathanjmcdougall May 13, 2026
56e441b
Replace assert with proper TypeError for key type narrowing
nathanjmcdougall May 13, 2026
f374602
Extract _create_at helper from upsert
nathanjmcdougall May 13, 2026
cf62205
Wrap UnicodeDecodeError in ParseError in load()
nathanjmcdougall May 13, 2026
5c3df1c
Add read-only kind property to Op
nathanjmcdougall May 13, 2026
33c71d4
Validate tuple element types in _normalize_keys
nathanjmcdougall May 13, 2026
4b69a2f
Enforce meaningful import layering: editor > document > errors
nathanjmcdougall May 13, 2026
570229c
Add Rust unit tests for types module
nathanjmcdougall May 13, 2026
b8781a7
Escape single quotes and backslashes in yaml_value_repr
nathanjmcdougall May 13, 2026
43f886a
Fix dedenting column calculation in parse_value
nathanjmcdougall May 13, 2026
c28d122
Document serde_yaml deprecation in Cargo.toml
nathanjmcdougall May 13, 2026
7251136
Document native memory lifecycle in Document docstring
nathanjmcdougall May 13, 2026
f97852c
Add Editor tests for extend_list, remove_from_list, query, extract, a…
nathanjmcdougall May 13, 2026
c986237
Fix README: use public API, document has_anchors and query_pretty
nathanjmcdougall May 13, 2026
a8a51e8
Remediate issues #2-#7: cross-ref comments, type annotations, docs, r…
nathanjmcdougall May 13, 2026
2b1c8f7
Remediate issues #11-#13: repr cleanup, exhaustive match arms, pyclas…
nathanjmcdougall May 14, 2026
a3a6b04
Add file I/O integration tests (#15)
nathanjmcdougall May 14, 2026
c3b7206
Fix _core.pyi stubs and add stubtest validation (#20)
nathanjmcdougall May 14, 2026
22113f6
Fix UTF-8 boundary panic in Document.extract()
nathanjmcdougall May 14, 2026
262f56a
Add UTF-8 parse_value tests, accept-risk on internal spans
nathanjmcdougall May 14, 2026
1c30a27
Document additional limitations in README
nathanjmcdougall May 14, 2026
44faea2
Note serde_yaml 0.9 is archived/unmaintained
nathanjmcdougall May 14, 2026
d347187
Fix two bugs in Python-to-Rust type conversion
nathanjmcdougall May 14, 2026
e4336e1
Add CI workflows for testing and static analysis
nathanjmcdougall May 14, 2026
b7dfba6
Fix CI failures: add Python setup, fix clippy deprecations, fix stubt…
nathanjmcdougall May 14, 2026
f0db7a6
Fix cargo test linking: make extension-module a conditional feature
nathanjmcdougall May 14, 2026
f5f6c91
Rewrite README: add uv install, split design decisions from limitatio…
nathanjmcdougall May 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Python Test
permissions: {}
on:
workflow_dispatch:
push:
branches: ["main"]
paths-ignore:
- "doc/**"
- "**/*.md"
- ".github/workflows/static-checks.yml"
- ".pre-commit-config.yaml"
pull_request:
paths-ignore:
- "doc/**"
- "**/*.md"
- ".github/workflows/static-checks.yml"
- ".pre-commit-config.yaml"
schedule:
- cron: "20 14 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
tests:
name: ${{ format('Test Python {0} {1}', matrix.python_version, ((matrix.dependencies == 'min' || matrix.dependencies == 'max') && format('{0} dependencies', matrix.dependencies)) || (matrix.os || 'ubuntu-latest')) }}
runs-on: ${{ matrix.os || 'ubuntu-latest' }}
env:
PYTHONIOENCODING: utf-8
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Set up uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: ${{ matrix.uv_version || 'latest' }}
enable-cache: true
python-version: ${{ matrix.python_version }}

- name: Setup dependencies
run: |
uv sync $CI_UV_UPGRADE_ARG
env:
CI_UV_UPGRADE_ARG: ${{ matrix.dependencies == 'max' && '--upgrade' || '' }}
UV_RESOLUTION: ${{ matrix.dependencies == 'min' && 'lowest-direct' || 'highest' }}

- name: Run pytest
run: uv run --frozen pytest -v

strategy:
matrix:
python_version: ["3.10", "3.14"]
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
dependencies: ["lockfile"]

include:
- python_version: "3.11"
os: "ubuntu-latest"
- python_version: "3.12"
os: "ubuntu-latest"
- python_version: "3.13"
os: "ubuntu-latest"
- dependencies: "min"
python_version: "3.10"
uv_version: "0.9.9"
- dependencies: "max"
python_version: "3.14"
58 changes: 58 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Release to PyPI
permissions: {}
on:
push:
tags:
- "v*"
jobs:
build:
name: Build Distributions
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Set up uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "latest"
enable-cache: false

- name: Build distributions
run: uv build

- name: Upload distributions
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dists
path: dist/
if-no-files-found: error

publish:
name: Publish
runs-on: ubuntu-latest
permissions:
id-token: write # for Trusted Publishing
needs: build

environment: release

steps:
- name: Set up uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "latest"
enable-cache: false
ignore-empty-workdir: true

- name: Download distributions
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: dists
path: dist/

- name: Publish
run: |
uv publish --trusted-publishing always dist/*
48 changes: 48 additions & 0 deletions .github/workflows/rust-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Rust Test
permissions: {}
on:
workflow_dispatch:
push:
branches: ["main"]
paths-ignore:
- "doc/**"
- "**/*.md"
- ".github/workflows/static-checks.yml"
- ".pre-commit-config.yaml"
pull_request:
paths-ignore:
- "doc/**"
- "**/*.md"
- ".github/workflows/static-checks.yml"
- ".pre-commit-config.yaml"
schedule:
- cron: "20 14 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
cargo-test:
name: Cargo Test (${{ matrix.rust }})
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.rust == 'beta' }}
strategy:
matrix:
rust: [stable, beta]
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.10"

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
toolchain: ${{ matrix.rust }}

- name: Run cargo test
run: cargo test --no-default-features
57 changes: 57 additions & 0 deletions .github/workflows/static-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Static Checks
permissions: {}
on:
workflow_dispatch:
push:
branches: ["main"]
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
analyze-python:
name: Analyze Python
runs-on: "ubuntu-latest"
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Set up uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "latest"
enable-cache: true

- name: Run checks
run: |
uv run --frozen prek -a
env:
PREK_UV_SOURCE: github

analyze-rust:
name: Analyze Rust
runs-on: "ubuntu-latest"
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.10"

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
toolchain: stable
components: clippy, rustfmt

- name: Check formatting
run: cargo fmt --check

- name: Run clippy
run: cargo clippy --no-default-features -- -D warnings
29 changes: 29 additions & 0 deletions .github/workflows/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: zizmor
on:
push:
branches: ["main"]
paths-ignore:
- "docs/**"
- "**/*.md"
- ".pre-commit-config.yaml"
pull_request:
branches: ["**"]
paths-ignore:
- "docs/**"
- "**/*.md"
- ".pre-commit-config.yaml"
permissions: {}
jobs:
zizmor:
name: Analyze
runs-on: ubuntu-latest
permissions:
security-events: write # needed to upload results
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Run zizmor
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
29 changes: 29 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,32 @@ cython_debug/
marimo/_static/
marimo/_lsp/
__marimo__/

# Generated by Cargo
# will have compiled files and executables
debug
target

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

# Generated by cargo mutants
# Contains mutation testing data
**/mutants.out*/

# rustc will dump stack traces when hitting an internal compiler error to PWD
rustc-ice-*.txt

# RustRover
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# Agent Skills
.agents/skills/
skills-lock.json
18 changes: 18 additions & 0 deletions .importlinter
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[importlinter]
root_packages =
yamltrip

[importlinter:contract:0]
name = yamltrip
type = layers
layers =
editor
document
errors
containers =
yamltrip
exhaustive = True
exhaustive_ignores =
_core
ignore_imports =
yamltrip.document -> yamltrip
47 changes: 47 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
repos:
- repo: https://github.com/tsvikas/sync-with-uv
rev: v0.5.0
hooks:
- id: sync-with-uv
- repo: https://github.com/tox-dev/pyproject-fmt
rev: v2.21.2
hooks:
- id: pyproject-fmt
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.12
hooks:
- id: ruff-check
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.12
hooks:
- id: ruff-format
- repo: local
hooks:
- id: ty
name: ty
always_run: true
entry: uv run --frozen --offline ty check
language: system
pass_filenames: false
- repo: local
hooks:
- id: deptry
name: deptry
always_run: true
entry: uv run --frozen --offline deptry src
language: system
pass_filenames: false
- repo: local
hooks:
- id: import-linter
name: import-linter
always_run: true
entry: uv run --frozen --offline lint-imports
language: system
pass_filenames: false
- repo: https://github.com/codespell-project/codespell
rev: v2.4.2
hooks:
- id: codespell
additional_dependencies:
- tomli
Loading
Loading