跳转至

Changelog

变更日志

本文件记录该项目的所有重要变更。

格式基于 Keep a Changelog, 本项目遵循 语义化版本

[Unreleased]

新增

  • 命令行工具 — 新增 pyrs-yaml 命令(通过 pip install "pyrs-yaml[cli]" 安装, 需 Python 3.10+),在终端中暴露库的核心能力:fmt(往返重新格式化,保留注释/ 锚点/顺序)、get(JSONPath 查询,支持 --format yaml|json|text)、set / delete / rename(基于路径的编辑,支持 --inplace--string--create-missing)、validate(对 CI 友好的退出码)以及 to-json / from-json 转换。所有命令通过 - 读取 stdin,默认输出到 stdout。实现为纯 Python(python/pyrs_yaml/cli/),基于 Cyclopts 作为可选 extra,基础安装保持零额外依赖并继续支持 Python 3.8。 基础安装保持零额外依赖并继续支持 Python 3.8。
  • CLI 扩展 —— 新增 sort-keys(对路径处映射键排序)、move(将子树移动到已存在的目标)、 frontmatter(提取 Markdown front matter 为 YAML,可选拆分正文)与 compliance (YAML Test Suite 报告,支持 --json)命令;为 fmt/get/set/delete/rename/ sort-keys/validate/to-json 提供 -A/--all-docs 多文档模式;validate 改为互斥的 --schema <名称>--schema-file <路径>。未成文的 python -m pyrs_yaml.compliance 入口已被子命令取代并移除。
  • 可选第三方类型插件!durationpendulum.Duration)、!arrowarrow.Arrow)、 !ulidulid.ULID)在安装对应库时自动注册(python/pyrs_yaml/plugins/_builtin.py 中的 _register_third_party)。每个插件使用独立标签,不影响现有 !timestamp / !date / !uuid 处理器;标准库 timedelta 绝不会被 !duration 匹配。
  • pydantic-settings YAML 配置来源PyrsYamlConfigSettingsSourcepython/pyrs_yaml/settings.py)是 pydantic_settings.YamlConfigSettingsSource 的即插即用替代,使用 pyrs-yaml(YAML 1.2 核心 schema)而非 PyYAML 解析。采用惰性 导出,import pyrs_yaml 不依赖 pydantic-settings;通过 pip install "pyrs-yaml[settings]" 安装(Python 3.10+)。dump_pydanticparse_as 也已改为相同的模块级 __getattr__ 惰性导出模式。

[v0.15.0] — 2026-08-19

新增

  • Node 元数据 setter/getter — 新增 Node.comment / Node.anchor / Node.tag 只读属性和 set_comment / set_anchor / set_tag(及 remove_* 系列)。编辑别名或不存在路径会报错;内联标量值和序列项上的独立注释现在输出到独立的缩进行(修复 child:\n # c\n val- a\n# c\n- b 既有的 round-trip 缺陷)。
  • Verbatim 标签set_tag("!<tag:yaml.org,2002:str>") 现在生成 verbatim 标签(空 handle),且从源码解析的 verbatim 标签在 round-trip 中保留:TagDisplay 对空 handle 标签以 !<...> 包裹输出,parse_tag 识别 !<...> 形式,流事件通过 Display 序列化标签。
  • Schema 文件 IO 与列表load_schema(name, path) 从文件读取 schema 定义并注册,list_schemas() 返回所有已注册的 schema 名称(内置 failsafe/json/core/yaml1.1 + 自定义)。
  • Node style/format setter/getter — 新增 Node.scalar_style / Node.flow_style / Node.chomping 只读属性和 set_scalar_style / set_flow_style / set_chomping 方法。ScalarStyle/Chomping 现在 derive Copy。非标量节点返回 None / no-op,别名和缺失路径报错。
  • Schema 结构化校验 — 在 schema 定义的 validate 段添加结构检查(路径限定标量类型、sequence_of/mapping_of 容器、required)。validate_against_schema(data, schema_yaml) 列出所有失败项并抛 YamlValidateError
  • Node.copy() — 将子树深度复制为与文档分离的独立 Python 值(dict/list/scalar),可用于通过 set_value() 粘贴。
  • 深度编辑 APIdoc.set_many({path: value}) 在单次 splice 突发中设置多个路径(支持通配符 [*] 和深度扫描 ..);doc.sort_keys() 原地排序映射键;Node.move(new_path) 移动子树;Node.path / Node.find_first() / Node.value_eq() 新增路径访问、首通配符查找、值比较。
  • 0.14+ 新功能的属性测试validate_node / schema 解析 / style round-trip 的 Rust proptest,set_many 通配符 / metadata 编辑 / sort_keys 的 Python hypothesis 测试。hypothesis 移至 test 组,确保 CI 运行属性测试。
  • 序列化器修复 — 空 flow 容器(key: {} / key: [])上的独立注释不再产生无效 YAML(降级为行内)。

变更

  • NumPy 在自由线程 (cp314t) wheel 上重新启用 — 从 cp314t 构建参数移除 --no-default-features;rust-numpy 0.29 支持自由线程 Python,numpy.ndarray 序列化现可在自由线程 wheel 上使用(运行时自动检测 NumPy 是否安装)。

文档

  • 修正全部语言(en/zh/ja/ko)文档中的过时引用saphyr-parsergranit-parser,YAML 合规率 98.1% → 99.75%(405/406 套件用例),ABI3 支持 3.9–3.13 → 3.8–3.15(py3.9+ → py3.8+),并更新基准测试表为当前 CodSpeed CI 数据(解析快 21–43 倍、序列化快 55–177 倍于 PyYAML)。Rust 侧基准测试章节从 Criterion 迁移到 divan(benches/yaml_bench.rscrates/pyrs-yaml/benches/yaml_bench.rs)。

[v0.14.1] — 2026-08-15

修复

  • 含反斜杠+控制字符/非字符的单引号标量 — 此类值改用双引号输出;单引号无法转义控制字符/非字符。
  • 非字符与 BOM 引用needs_quotes / needs_double_quoted 现对 U+FFFE/U+FFFF/平面末尾非字符及 U+FEFF(BOM)要求引用。
  • 双引号转义宽度 — U+FFFF 以上的码点现以 8 位 \Uxxxxxxxx 形式转义(4 位 \u 仅限 BMP)。
  • 折叠 plain 标量续行缩进 — 续行缩进改由值起始列推导,使嵌套序列/映射项续行缩进超过父块缩进。
  • 多字节折叠边界wrap_plain_scalar 对折叠切片做 char boundary 向下取整,避免 4 字节 UTF-8 跨边界时 panic。
  • publish 测试依赖含 hypothesis.ci/requirements-test.txt 固定 hypothesis>=6.113.0,使发布工作流能运行属性测试。

Added

  • scripts/fuzz_panics.py — 本地大规模 Hypothesis fuzz 脚本,含恶意策略覆盖 dump/parse/edit/幂等。

[v0.14.0] — 2026-08-14

Added

  • YAML Schema Language — 定义自定义 schema,将正则模式映射到 YAML 类型。 通过 register_schema() 注册。
  • 内联 dict schemaschema 参数可直接传入 dict
  • Community Plugins — 通过 CustomType 基类注册自定义节点类型。 使用 register_type() 注册。
  • 内置插件 — 默认注册 !timestamp(datetime)和 !set

Changed

  • Schema 解析可插拔SchemaResolver trait + Schema 枚举 + 全局 SchemaRegistry。内置 schema 保持零开销分发。
  • node_to_pyobjectdirect_dump 检查 CustomType — 带标签的标量通过 from_yaml() 转换,Python 对象通过 to_yaml() 序列化。

修复

  • 带引号标量恒为字符串 — 隐式类型解析仅作用于纯标量(YAML 1.2)。safe_load('"true"') 返回字符串 "true"(而非 True)。序列化器保持文档(to_yaml)路径下的负数正确往返。
  • 单引号/双引号单字符键可往返 — 值为单个 '" 的映射键以引号标量输出,不再产生无法解析的 YAML。
  • 空集合输出 {}/[] — 空映射/序列序列化后不再是解析为 None 的空文档。

变更

  • get() 仅接受字面键YamlDocument.get() 不再将含 ./[ 的键视为 JSONPath;所有键都按顶层映射键处理(与 __getitem__/__setitem__ 一致)。路径访问请使用 find()/node()

[v0.13.0] — 2026-08-10

变更

  • Rust MSRV 提升至 1.96,edition 升级为 2024 — 两个 crate 均声明 rust-version = "1.96"edition = "2024";CI 将 build/test-freethreaded 任务固定在 Rust 1.96 以生成确定性 wheel;新增 msrv-check 任务在 MSRV 上运行 cargo check/cargo test 防止静默漂移(rust-lint 仍使用 stable)。 版本基线高于 PyO3 0.29 自身的基线(rustc 1.83),目的是获得 std API 的前瞻性 支持(如 assert_matches!,1.96 稳定),无需代码迁移。 TAG_REGISTRY(标签处理器存储)重构为 std::sync::LazyLock, 移除了 Mutex<Option<...>> 间接层。

Performance

  • safe_dump / from_dict / dump_file / dump_iterable: direct writer — Python→YAML 序列化无需中间 CustomNode AST。 单次 direct_dump 替换旧的两次传递 pyobject_to_node + to_yamlsafe_dump 提速 7 倍(28ns→4ns),from_dict 提速 6 倍(35ns→6ns)。(#60)
  • safe_load / safe_loads / to_dict: fast-path skip anchor tracking — 当输入不含 & 字符时,跳过 collect_anchors 和锚点解析, 使用更简单的 node_to_pyobject_simple 路径。(#59)
  • resolve_core_type: first-byte dispatch whitelist — 非数字/ 非布尔首字节立即返回 Str,避免常见情况下的 schema 解析开销。(#59)
  • 迁移到 granit-parser — 用 granit-parser 1.0.1 替换 saphyr-parser, 借助原生 Event::Comment 输出消除了全文 scan_yaml() 预扫描。 parse_small -18%、parse_large -21%、roundtrip_large -18%。

Fixed

  • float_to_yaml_string round-trip 修复 — Rust Display 丢失小数部分时 补 .04242.0),使 float 按 float 而非 int 正确往返。
  • 回退 count_nodes 预分配 — 全 AST 遍历的开销大于其避免的重新分配 (serialize_10mb 慢约 14%);缓冲扩容交给 Vec。

Added

  • max_depth 支持流式与 frontmatter APIparse_stream(yaml, on_event, max_depth)read_markdown(path, schema, max_depth)read_markdown_str(content, schema, max_depth) 接受 max_depth(默认 1000)。流式解析现通过核心 parse_stream_with_options 强制嵌套深度限制(此前流式事件没有深度限制)。
  • Pydantic 集成dump_pydantic() 将 Pydantic 模型序列化为 YAML 字符串(model_dump(mode='json') + safe_dump);parse_as() 将 YAML 字符串解析为 Pydantic 模型实例。两者均使用延迟导入,无硬性 pydantic 依赖。(#61)

Internal

  • 拆分 py/mod.rs — 单体 1786 行模块拆分为 document.rs(YamlDocument)、yaml_instance.rs(YAML 类)、 functions.rs(模块级函数)、stream_iterator.rswalk_helpers.rsmod.rs 缩减至 128 行。(#61)
  • needs_quotes() 守卫 + double_quoted_scalar() 构造器'true' / '42' / 'null' 等字符串现以双引号标量输出,避免 core schema 重新解析时被误读(pyobject_to_node + json_value_to_node)。
  • CodSpeed 基准统一到 codspeed-divan-compatexclude-allocations 去除分配器噪声;跨库基准合并到 tests/test_benchmark_crosslib.py, 引入共享 tests/data/yaml_samples.py 夹具和流式覆盖。

[v0.12.1] — 2026-08-06

Added

  • set(create_missing=True) - 编辑路径上缺失的中间映射键会创建为嵌套映射 (例如,对 a: 1 设置 a.b.c 会创建 bc);索引段缺失仍报错, 路径上的标量中间层仍会引发异常。
  • doc.walk() / doc.scalars() - Rust 后端的深度优先 AST 遍历, 返回 Node 对象,避免逐节点 to_dict() 解析。 walk() 返回所有节点;scalars() 仅返回标量/null 节点。
  • Rust 核心模块测试 - 39 个新测试,覆盖 editing::navigate (key_eq、navigate、navigate_mut、normalize_index、mapping_key_index)、 editing::region(行辅助函数、node_is_flow、extend_delete_over_comments、 nav_err)、editing::dirty(DirtyKind/DirtyUnit 构造函数)以及 editing::metadata(with_metadata_from、needs_quoting)。
  • Python doc.walk() 边界测试 - 9 个新测试,覆盖空文档、空值、 深度嵌套、流集合、混合类型。

Changed

  • Monorepo workspace - 源码拆分为 crates/pyrs-yaml-core/ (纯 Rust,无 PyO3)和 crates/pyrs-yaml/(PyO3 绑定)。根 Cargo.toml 现在是 workspace。旧的 src/ 目录和 build.rs 已移除。
  • pyproject.toml - 新增 tool.maturin.manifest-path 指向 crates/pyrs-yaml/Cargo.toml
  • 解析热路径 - 单次注释/锚点提取、延迟重复键检测、shift_insert 合并预处理,以及单文档解析跳过 DocumentEnd 深拷贝,大文档 解析成本降低约 19%(CodSpeed: parse[large] +13.9%,parse[medium] +16.6%, roundtrip[large] +12.2%)。
  • Arc<str> 标量存储 - CustomNode::Scalar 和注释/事件 文本通过 Arc<str> 共享分配;AST 节点缩减 8 字节, 克隆变为引用计数递增而非深拷贝。

Fixed

  • set(create_missing=True) 嵌套链构建 - 创建的映射链 不再将第一段重复为嵌套键层级。
  • set(create_missing=True) 资格检查 - 新创建的键现在 可参与值写入(资格检查不再在合成对插入后运行)。
  • 简单映射键前的独立注释 - 往返之前会丢弃附加到 简单键节点的独立注释;现在保留(两个回归测试)。

[0.11.7] - 2026-08-04

Changed

  • stub-build-check 替换为 release-guard — 故意失败以复现 v0.10.0 --generate-stubs 失败模式的总是失败的容器构建 (validate.yml)被三个静态断言替换,当仓库正确时通过grep 保护 publish.yml 不含 --generate-stubsgit ls-files 断言提交的 .pyi 已追踪, test -f 检查 py.typed 存在。任务现在在正确状态下给出绿色 CI, 仅在回归时红色。

Added

  • Numpy free-threaded 跟踪 — ROADMAP.md 现在跟踪 rust-numpy free-threaded 支持状态(PyO3/rust-numpy#476),作为 Rust 绑定成熟后在 cp314t wheel 上重新启用 ndarray 序列化的依赖。

[0.11.6] - 2026-08-04

Changed

  • Free-threaded(cp314t)wheel 不再包含 numpy — 使用 --no-default-features 构建,rust-numpy 完全排除(更小的 二进制,无运行时探测)。free-threaded 构建上对 numpy.ndarray 调用 safe_dump 会引发 YamlTypeError;GIL 构建(Python 3.8-3.15) 保留完整的 ndarray 序列化。

Added

  • Free-threaded CI 验证test-freethreaded 任务现在使用 --no-default-features 构建和测试,与分发的 free-threaded wheel 配置匹配。
  • 安装文档docs/{en,zh,ja,ko} 注明 free-threaded wheel 不含 numpy(cp314t 上不可用 ndarray 序列化)。

[0.11.5] - 2026-08-04

Changed

  • 解析器健壮性项目 3/4/5 通过 Phase 0 严格性审计关闭 — 70 探针语料库(缩进、块映射键、流上下文)与 PyYAML 预言机对比, 显示无可修复的接受但无效案例(64/70 匹配;6 处分歧是 有意为之的 YAML 1.2 / yaml-test-suite 要求,PyYAML 是异常项, 另有一个有意为之的重复键严格性)。合规率保持在 99.75%(405/406)。完整说明见 ROADMAP.md §v0.11.5 和 tests/test_strictness_audit.py

Added

  • tests/test_strictness_audit.py — 70 探针严格性回归语料库, 固定当前拒绝/接受行为(两个方向),使未来解析器变更无法 静默降低严格性或过度拒绝。

[0.11.4] - 2026-08-04

Fixed

  • 重复的空/空映射键不再报错(: a\n: b~: a\n~: b)— 与 yaml-test-suite 2JQS 匹配;真实重复键仍会引发 YamlDuplicateKeyError
  • 合规检测工具:正确拒绝的无效 YAML 现在计为通过(之前尽管行为合规 却降低了通过率)
  • 合规检测工具:convert_special_chars 通过正则表达式解码制表符 — 任何 / + » 序列均为一个制表符,修复制表符编码的套件用例

Changed

  • YAML Test Suite 通过率阈值从 >75% 提升至 ≥95%;当前通过率 99.75%(405/406)
  • 记录已知偏差:ZYU8%YAML 1.1 1.2)按设计拒绝(YAML 1.2 语法无效,与 PyYAML/libyaml 一致)

[0.11.3] - 2026-08-03

Added

  • 流式写入:YAML.dump_stream(file_obj, iterable) / YAML.dump_file(path, iterable),文档级恒定内存,自动 --- 分隔符,以及 explicit_start/explicit_end 标志
  • YamlDocument with 上下文管理器:快照/回滚事务作用域
  • compliance_report():公开 YAML Test Suite 通过率报告(版本一致)

Changed

  • 编辑爆发行偏移缓存:拼接层内部 O(N+edit) 传递(公开 API 不变)
  • compute_compliance 从测试移至 pyrs_yaml.compliance;版本不再硬编码

Fixed

  • 变更日志镜像漂移防护:prek 钩子 + CI 任务断言根/镜像 [Unreleased] 同步
  • 发布存根预验证:CI 在 Release 前复现 v0.10.0 类 --generate-stubs 容器失败

[0.11.2] - 2026-08-03

Added

  • YAML.load_stream(file_obj) / YAML.load_stream_file(path): O(锚点数 + 块) 内存的惰性事件迭代器

Performance

  • 解析不再计算拼接资格 — O(文档) 布局检查现在在首次编辑时通过 YamlDocument.splice_checked 惰性运行,恢复 v0.11.0 回归: parse_comments -59%、parse_anchors -42%、parse/roundtrip/edit -10~35% 全部回到 v0.10.0 水平
  • 线性游标布局检查 — 取代基于预计算行偏移的逐节点二分查找 (单调源码顺序遍历)

Changed

  • parse_with_options 返回 CustomNode(原为 (CustomNode, bool)); 拼接资格现在内置于 YamlDocument 并按需计算

[0.11.0] - 2026-08-02

Added

  • 精准序列化 — 字节级源码范围追踪;基于段的拼接 — 编辑仅重新生成 触碰区域,未触碰文本按字节复制
  • proptest 保真度属性测试(新开发依赖)
  • 10MB 编辑-刷新基准测试(divan)

Changed

  • flush_source 现在使用分段拼接;回退到全量序列化:流风格区域、 非默认布局文档、合并键、CRLF/BOM 文档,以及 materialize 之后 (单次爆发模型)
  • 拼接编辑保留 ---/.../指令标记行为未触碰字节 (全量序列化之前会丢弃它们 — 设计上的行为差异)

[0.10.0] - 2026-08-01

Added

  • 就地编辑 — 编辑已解析的文档而不丢失格式元数据:
    • 路径 API:doc.set(path, value)doc.insert(path, index, value)doc.append(path, value)doc.delete(path)doc.rename(path, new_key), 使用 JSONPath 风格路径($.a.b[0]);根节点语法糖 doc["key"] = valuedel doc["key"]
    • 节点 API:doc.node() / doc.find(path) 返回 Node 对象, 支持 set_value / append / insert / delete / rename, 以及树遍历(parentchildrenwalkfilter
    • 完整元数据保留 — 被替换的标量保留注释/锚点/标签/引号; 重命名的键保留位置和注释;删除时映射顺序保留
    • 原子编辑 — 失败的操作不会改动文档(及其修订号)
    • 惰性源文本重新同步 — source() / to_yaml() / reparse() 仅在编辑成功后重新序列化
    • 过期节点检测 — 文档编辑后访问 Node 引发 YamlDocumentError(并发出 RuntimeWarning
    • 新异常:YamlEditErrorYamlPathError (支持 en/zh-CN/ja-JP/ko-KR 国际化)
    • 别名感知编辑 — 设置别名自身路径会就地替换它; 穿过别名编辑引发 YamlEditError
  • 编辑基准测试benches/yaml_bench.rs 新增 6 个 divan 基准 (小到大文档的 set/insert/delete)

Changed

  • YamlDocument.source() 现在返回 str 并在就地编辑后惰性重新序列化

[0.9.0] - 2026-08-01

Added

  • Python 3.13、3.14 和 3.15 支持 — PyO3 abi3-py38 wheel 覆盖 Python 3.8-3.15(GIL 构建);abi3t + abi3t-py315 提供 free-threaded 稳定 ABI
  • Free-threaded CPython(无 GIL)支持#[pymodule(gil_used = false)] 声明模块对 free-threaded Python 线程安全;Py_GIL_DISABLED cfg 标志门控 numpy(rust-numpy 尚不支持 free-threaded — 通过 --no-default-features 为 free-threaded 构建禁用 numpy feature)
  • CI free-threaded 任务 — 新增 test-freethreaded 工作流任务, 针对 Python 3.14t 验证编译和测试
  • pyo3-build-config 构建依赖 — 通过 build.rs 启用 #[cfg(Py_GIL_DISABLED)]#[cfg(Py_3_15)] 等编译器标志
  • numpy 改为可选 — 由 numpy feature 门控(默认启用); 在 Py_GIL_DISABLED 下自动排除
  • allow_duplicate_keysYAML(allow_duplicate_keys=True)parse(..., allow_duplicate_keys=True)parse_filesafe_loadsafe_loadsparse_all_docs 均接受该标志;重复映射键默认 引发 YamlDuplicateKeyError,允许时采用"最后值生效"
  • SerializeOptions 扩展doc.to_yaml_with_options() 新增 width(行包裹,0 = 关闭)、indent_mappingindent_sequenceindent_offset,与现有的 indent_size/explicit_start/ explicit_end/sort_keys/max_depth 并列 (src/py/mod.rs:432
  • 标签处理器注册表register_tag("!custom") 装饰器和命令式形式
    • clear_tag_handlers();携带已注册标签的标量节点通过处理器转换 (src/py/tag_registry.rs
  • 标签处理器优先级链 — 同一标签的多个处理器按升序 priority 执行;YamlTagSkip 让处理器传递给下一个,fallback 保留原值
  • Pydantic 集成parse_as(Model, yaml, **yaml_kwargs) 解析 YAML 并针对 Pydantic v2 模型验证;缺少 pydantic 时引发 ImportError 并附指导信息(python/pyrs_yaml/pydantic.py
  • .pyi 类型存根 — 由 maturin 自动生成并提交,使 register_tagparse_asto_yaml_with_options 和新异常 对类型检查器可见

Changed

  • CI Python 矩阵扩展:ubuntu、windows、macos 上的 3.8-3.14
  • 稳定 ABI:abi3-py39abi3-py38(更广的 Python 3.8+ 支持), 新增 abi3t + abi3t-py315(free-threaded 稳定 ABI)
  • pyproject.toml classifiers 更新 3.13、3.14、3.15 条目
  • CI 优化:消除冗余 Rust 编译 — 单个 rust-lint 任务运行 cargo clippy + cargo test 一次;build 任务为每个 OS 生成一个 abi3 wheel,测试任务安装而非运行 maturin develop, 将 Rust 编译从 21 个矩阵任务中移除(减少约 86% 编译量); 所有任务添加 Swatinem/rust-cache
  • pydantic 测试依赖pydantic>=2.10.6 加入 [dependency-groups] test.ci/requirements-test.txt (通过 uv sync 在 ci.yml 中统一管理)

Fixed

  • Windows DLL 加载 — 移除 src/py/tag_registry.rs 中的 #[cfg(test)] 块,该块在 Windows 上破坏了 import pyrs_yaml250b8d0
  • Python 3.8 兼容性pydantic.py 中添加 from __future__ import annotations63d2495
  • CI pydantic 跳过 — 使用 pytest.importorskip("pydantic") 使测试在未安装 pydantic 时通过(7be011d
  • CI Windows glob 展开pip install dist/*.whl 使用 shell: bash(PowerShell 不展开 *)(2f7778d
  • 非字符串标签处理器返回值现在引发 YamlTagError — 返回 非 str 值的处理器(之前被静默忽略,保留原标量)现在报错 Tag handler '!x' must return a stringsrc/py/mod.rs:resolve_tags
  • to_yaml_with_options 缩进连线indent_mapping/ indent_sequence/indent_offset 现在被序列化器尊重 (之前为死字段);省略时分别默认 indent_size/0 (src/serializer.rs
  • width 不再对极小值死循环width < 续行缩进 时回退为 直接输出未包裹的剩余内容而非无限循环(src/serializer.rs:write_plain_scalar
  • remove_tag(name) — 新增函数用于注销标签处理器; 补充 register_tag/clear_tag_handlerssrc/py/tag_registry.rs
  • duplicate-key 错误国际化YamlDuplicateKeyError 消息 现通过 format_i18n_error 在所有 4 个语言区域中传递 (src/i18n/locales/*.yml

[0.8.0] - 2026-07-30

Added

  • YAML() 实例 APIYAML(typ="rt"|"safe"|"full", schema="core"|"yaml1.1", max_depth=1000), 可复用配置;.parse().safe_load().safe_loads().parse_file().parse_all_docs() 方法
  • Python Node APINode 类,具有 find()filter()walk()to_yaml()parentchildrenroot_typevalue,用于 AST 导航;JSONPath 风格查询语言 ($.key.sub$.arr[0]$..deep
  • doc.version 元数据YamlDocument.version() 返回 YAML 规范版本(默认 "1.2")
  • MergedViewdoc.merged() 返回解析合并键后的只读 类字典视图
  • 生命周期警告Node.release() 显式使节点失效;过期 访问发出 RuntimeWarning + YamlDocumentError

Changed

  • parse() / safe_load() 现在作为语法糖委托至 YAML().parse() / .safe_load()
  • YamlDocument 现在存储 version 字段用于文档元数据

[0.7.1] - 2026-07-30

Added

  • ryaml 基准对比tests/test_benchmark.py 现在与 ryaml(Rust YAML 库) alongside PyYAML 和 ruamel.yaml 进行 基准测试;benchmark_compare.py 重写为特性对比报告 (tests/test_benchmark.py:25-28.github/workflows/ci.yml:219
  • CI 合规阈值提升 — YAML Test Suite 合规阈值从 70% 提升至 75%(test_compliance_report());有效解析率阈值 95% (tests/test_yaml_suite.py:251
  • CI 依赖整合 — 新增 .ci/requirements-test.txt.ci/requirements-test-lite.txt,用于发布工作流和本地开发 的统一测试依赖管理
  • 基准测试现代化 — 从 pytest-benchmark 迁移至 pytest-codspeed 以实现更快的 C 扩展统计基准测试; 所有 CI 任务现在使用 -r .ci/requirements-test.txt
  • Rust 基准测试迁移至 Divan — 用 codspeed-divan-compat v5.0.1 替换 codspeed-criterion-compat;16 个基准测试从 Criterion 组重写为 #[divan::bench] 属性 (Cargo.tomlbenches/yaml_bench.rs

Changed

  • CI 基准任务安装 ryaml 用于跨库对比
  • benchmark_compare.py 现在委托计时至 pytest-benchmark, 作为特性对比/报告工具

[0.7.0] - 2026-07-29

Added

  • 序列化器 max_depth 守卫serialize_node_internal 现在 跟踪递归深度,超出限制时引发 YamlMaxDepthError(默认 1000), 与解析器保护一致(src/serializer.rs:135-145
  • 序列化器热路径优化 — 5 项针对块风格序列化的优化,约 4.9% 往返加速:
    • 内联 write_anchor_tagwrite_inline_comment None 检查 (消除约 99% 节点的函数调用)
    • write_indent 热/冷路径分离(缓存级别 ≤64 直接索引)
    • write_plain_scalar 短 ASCII 字母数字字符串快速路径 (≤8 字符)
    • write_scalar_for_key Plain 标量直接分派(避免分派链)
  • pytest-benchmark 迁移 — Python 基准测试从原始 time.perf_counter() 迁移至 pytest-benchmark 以获得统计严谨性、 结构化 JSON 输出和 CI 集成(tests/test_benchmark.py + 更新的 tests/test_performance.py

Changed

  • pytest-benchmark 替换 Python 基准测试中的原始 timeit
  • CI 基准任务现在运行 pytest --benchmark-json 而非独立脚本

Removed

  • write_inline_comment 方法 — 在所有调用点内联
  • 序列化器的 Comment 导入 — 不再需要

[0.6.0] - 2026-07-27

Added

  • 异步序列化safe_dumps_asyncsafe_dump_asyncsafe_loads_asyncsafe_load_async,通过 asyncio.run_in_executorpython/pyrs_yaml/async_dump.py
  • JSON Schema 验证YamlValidateError 异常 + YamlDocument.validate(schema) 方法(接受 strdict); 委托至 Python jsonschema 模块
  • YamlDocument.to_json() — 将文档序列化为 JSON 字符串 (使用 Python json.dumps
  • 增量重新解析YamlDocument 现在存储源文本 (doc.source());doc.reparse(resolve_merges=True, schema="core") 就地重新解析
  • 29 个新测试 — 跨 test_async.py(8)、test_validate.py (14)、test_reparse.py(7)

Changed

  • YamlValidateError 注册为新自定义异常(继承 ValueError
  • rust_i18n::i18n! 宏路径更新为 "src/i18n/locales"
  • validate_translations() 测试路径更新以匹配新语言目录

Removed

  • 删除冗余的 src/i18n/en.ftlsrc/i18n/zh-CN.ftl(从未被 rust-i18n 引用)
  • locales/*.yml 移至 src/i18n/locales/(与 i18n 模块共置)

依赖变更

  • 运行时依赖:jsonschema>=4.25.1
  • 开发依赖:pytest-asyncio>=0.23(从运行时移至开发依赖,不再固定)

[0.5.0] - 2026-07-27

Fixed

  • Serializer::write_nodeblock_mapping/block_sequence.unwrap() on values.iter().next().unwrap() 替换为安全 索引访问,消除边缘 AST 的潜在 panic
  • YAML_SCHEMA 常量 — 拼写错误 yamorg2002 修正为 yamlorg2002(匹配 YAML 1.2 规范 URL)
  • 开发文档AGENTS.md 更新,为 Python 命令添加强制 uv run 前缀,Rust 命令直接使用 cargo

[0.4.0] - 2026-07-27

Added

  • 132 个新功能填补测试 — 全面覆盖之前未测试的 API
  • i18n 函数测试set_languageget_languagelist_languagesdetect_languagenegotiate_language
  • parse_all_docs 专用测试套件 — 单文档、多文档、空、注释
  • parse_file 成功用例测试 — 基本解析、注释保留、文件未找到错误
  • to_yaml_with_options 测试explicit_startexplicit_endindent_sizesort_keys 顺序保留
  • to_dict() 方法测试 — 标量根、嵌套、列表、布尔、空、 锚点解析、空映射/序列
  • YamlDocument dunder 方法测试__repr____str____contains____len____iter____getitem__root_type()
  • 字节输入测试parse(b"key: value")、UTF-8 字节、无效 UTF-8 错误
  • Unicode 及特殊字符测试 — 中日韩、emoji、往返、CRLF 换行、重复键
  • safe_load/safe_loads 特性覆盖 — 锚点、合并键、块标量、 流集合、特殊浮点数、类型解析
  • from_dict 边界用例 — 键中的特殊字符、嵌套列表、None 值、 空字典/列表
  • from_json 往返 — 嵌套结构、数组、无效 JSON 错误
  • dump_file 测试 — 成功路径、无效路径错误
  • YAML Test Suite 单个用例测试 — 八进制、十六进制、科学计数法、 NaN、无穷大、合并键、显式/隐式键、布尔/空变体、块标量截断 (|-)、流集合
  • resolve_merges 参数测试 — 禁用时保留 <<,默认时解析
  • 流集合往返 — 根级和嵌套流映射/序列
  • 非标量节点上的锚点 — 映射锚点(&defaults)和序列锚点(&items
  • 序列索引测试 — 正索引、越界错误
  • 合并键集成 — 解析和未解析合并键的往返
  • 标签保留!!seq!!map 标签测试覆盖
  • 注释保留 — 复杂结构上的内联和独立注释测试

Changed

  • 修复版本同步:python/pyrs_yaml/__init__.py__version__ 从 0.2.0 更新至 0.4.0 以匹配 Cargo.toml/pyproject.toml
  • 移除 dist/ 中过时的 0.2.0 wheel 产物

[0.3.0] - 2026-07-27

Added

  • NumPy ndarray 序列化safe_dump() / safe_dumps() / from_dict() / dump_file() 现在支持所有维度的 numpy.ndarray(0-D 至 N-D)
    • 支持的数据类型:int8/16/32/64uint8/16/32/64float32/64complex64/128bool
    • 多维数组序列化为嵌套 YAML 列表,缩进正确
    • 复数序列化为 (re+imj) 字符串格式
    • 0-D 标量数组重塑为 1-D 并序列化为单元素列表
    • 通过 numpy Rust crate 的 PyUntypedArray + PyArrayDyn 实现零拷贝 dtype 分派
    • 切片迭代期间释放 GIL 以获得最大性能
  • quoted_scalar() — 新增 CustomNode::quoted_scalar() 构造函数,用于需要单引号 YAML 风格的值
  • 引号标量的类型解析resolve_yaml_type 现在应用于 SingleQuoted/DoubleQuoted 标量,以正确往返引号负数
  • 全面 NumPy 测试套件 — 42 个测试覆盖所有数据类型、 维度(0-D 至 4-D)、负数、无穷大、NaN、空数组及边界用例

Fixed

  • 负数往返 — YAML 1.2 块序列不能包含以 - 开头的纯标量; 序列化时负数现在加引号,解析时正确还原为整数/浮点数
  • N-D 数组支持 — 用 PyArrayDyn<T> 替换 PyArray1<T>, 支持任意维度数组而不仅限于 1-D
  • 正确嵌套深度 — 多维数组现在产生恰好 N 层嵌套 (shape[1..] 处理内部维度,根维度由 plain_sequence 包裹)

Changed

  • 新增 numpy crate(v0.29)作为 ndarray 类型分派的依赖

[0.1.0] - 2026-07-25

Added

  • 初始发布,通过 saphyr-parser 实现 YAML 1.2 合规
  • 自定义 AST,完整元数据(注释、锚点、标签、chomping、标量风格)
  • 注释、锚点、标签和格式的往返保留
  • PyYAML 兼容 API(safe_load/safe_dump
  • from_dict/from_json 转换函数
  • read_markdown/read_markdown_str 用于 YAML frontmatter 提取
  • 块标量(|/>)带 chomping 指示符(|-/|+/>-/>+
  • 转义序列(\n\t\uXXXX\xXX
  • YAML 1.2 类型解析(null、bool、int、float、infinity、NaN)
  • 合并键解析(<<: *alias
  • 复杂键(序列/映射作为键)