hegeltest 0.49.6

Property-based testing for Rust, built on Hypothesis
Documentation
#!/usr/bin/env -S uv run --script --with unicodedata2==17.0.0
"""Generate an independent Python-sourced reference table for testing.

Run from the repo root, with uv, which fetches the `unicodedata2` package
for the Unicode version the engine's tables are generated from (the
`UNICODE_VERSION` of `generate_unicodedata_tables.py`):

    scripts/generate_unicodedata_python_reference.py

Emits `hegel-c/tests/embedded/native/unicodedata_python_reference_data.rs`
with a run-length-encoded list of `(end_codepoint, category_str)` pairs,
sourced directly from `unicodedata2.category()`. The Rust test compares
`crate::unicodedata::general_category` against this reference for every
codepoint in `0..=0x10FFFF`, catching any divergence between the vendored
UnicodeData.txt and Python's own tables for that version.
"""

from __future__ import annotations

import sys
from pathlib import Path

import unicodedata2 as unicodedata

sys.path.insert(0, str(Path(__file__).resolve().parent))
from generate_unicodedata_tables import UNICODE_VERSION  # noqa: E402

REPO_ROOT = Path(__file__).resolve().parent.parent
OUT_PATH = (
    REPO_ROOT
    / "hegel-c"
    / "tests"
    / "embedded"
    / "native"
    / "unicodedata_python_reference_data.rs"
)

MAX_CP = 0x10FFFF


def main() -> None:
    if unicodedata.unidata_version != UNICODE_VERSION:
        sys.exit(
            f"unicodedata2 is Unicode {unicodedata.unidata_version}, "
            f"the engine's tables are {UNICODE_VERSION}"
        )
    ranges: list[tuple[int, int, str]] = []
    current_cat = unicodedata.category(chr(0))
    current_start = 0
    for cp in range(1, MAX_CP + 1):
        cat = unicodedata.category(chr(cp))
        if cat != current_cat:
            ranges.append((current_start, cp - 1, current_cat))
            current_cat = cat
            current_start = cp
    ranges.append((current_start, MAX_CP, current_cat))

    # Emit a bare array literal so the test file can `include!` it directly
    # inside a `const` definition without binding it to a specific name.
    lines = [
        "// Auto-generated by scripts/generate_unicodedata_python_reference.py.",
        "// Do not edit by hand; regenerate when upgrading the Unicode tables.",
        f"// Source: unicodedata2 {unicodedata.unidata_version} unicodedata2.category().",
        "// Run-length-encoded: each tuple is (end_inclusive, category_code),",
        "// covering `0..=0x10FFFF` contiguously.",
        "[",
    ]
    for _, end, cat in ranges:
        lines.append(f'    ({end:#07x}, "{cat}"),')
    lines.append("]")
    lines.append("")

    OUT_PATH.parent.mkdir(parents=True, exist_ok=True)
    OUT_PATH.write_text("\n".join(lines))
    print(f"Wrote {OUT_PATH} with {len(ranges)} ranges "
          f"(Unicode {unicodedata.unidata_version}).")


if __name__ == "__main__":
    main()