Changelog¶
change in minor releases. Finding codes are stable: a code is never renumbered or reused.
Unreleased¶
0.1.0 - 2026-10-01¶
Initial release.
Added¶
- Reading CUF-XML 4.000–4.003 with
pycuf.read()into a typed, English-named model (project, sort-code schemes, estimate tree of bundles and lines, resource and quantity take-off lines in document order, tail), with the parsed text of every element and attribute kept inrawand vendor attributes inextra. - Tolerant reading of real exporter output: Windows-1252 and other declared encodings, UTF-16
and UTF-32 in either byte order, namespaces that are not valid URIs, empty required
attributes, decimal commas, d-m-yyyy dates and
true/falsebooleans (opt-out), Bakker & Spees attribute-style sort codes, legacySC1–SC6attributes, and opt-in repairs for bare ampersands and control characters, applied to decoded characters so they never change valid text in any encoding. - Calculation of every bundle, line and resource line with exact
Decimalarithmetic in pycuf's own decimal context, independent of the caller's (CufFile.totals()), under an immutable, validatedPolicywith the presetsusage-rules(default),schemaanderp. - Validation (
pycuf.validate(),CufFile.validate()) with graded findings and stableCUF<nnnn>codes: encoding, XML, structure and values, sort codes, stated totals against computed totals, resource lines and the contract sum. Finding limits shorten the list but never changeok,max_severityor the exit code (ValidationReport.severity_counts). - Normalized tables exported to CSV and JSONL without dependencies, and to Arrow (PyCapsule interface), polars, pandas, DuckDB and Parquet through extras.
- The
pycufcommand line (info,totals,validate,export,codes) with thecliextra; invalid options and unwritable output exit with code 3 and a one-line message. - Hardened parsing: DOCTYPE/ENTITY declarations refused, size and depth limits, no recover mode
(only NUL and Ctrl-Z padding after the document is tolerated), and numbers limited to the XDR
range (zero or magnitudes from
2.2250738585072014E-308to1.7976931348623157E+308, at most 1,074 decimals; others areCUF3018), so a short attribute cannot make calculations or exports enormous. - Synthetic sample files in
examples/.