read_registry and read_needed_registry catch OSError, UnicodeDecodeError and
JSONDecodeError, but a registry nested a few hundred thousand levels deep raises
RecursionError. main returns 2 for an AuditError and 1 for missing imports, so
the traceback ended with exit code 1 and a corrupt registry looked like a failed
import audit. RecursionError is now caught with the other read errors and
reported as an AuditError, so the exit code is 2.
Specify utf-8-sig encoding when reading library source files in
source_stubs so UTF-8 characters are preserved on Windows and leading
BOMs are tolerated.
Reconfigure stdout and stderr streams to UTF-8 with backslashreplace
at the beginning of main, and specify UTF-8 encoding when writing test
fixtures.
A compound statement that is not a conditional, loop or lambda always runs, so its calls are collected like the body's own and its exits stop the scan. An export whose only throw sits in such a block stays a stub and fails a strict audit.
A conditional return, co_return or goto before the throwing call leaves a path that succeeds, so the audit stops collecting calls at it and the export, or a helper it calls, is partial. A guard that throws still leaves every path throwing, so it stays a stub.
The previous check called any stub call inside an #if block partial,
so an export that throws in every #if, #elif and #else alternative was
reported as partial. Each combination of preprocessor branches is now
expanded into its own body, an #if without #else gets an empty
alternative, and the export is a stub when every combination reaches
the throw. More than 256 combinations in one function, or unbalanced
directives, are reported as errors.
A NotImplemented_nid_no_patch call inside an #if, #ifdef or #ifndef block
opened in the export's own body runs only on some hosts, so the export
is partial, not a stub. An export wrapped in a preprocessor block from
outside its body keeps its class.
An export whose body reaches NotImplemented_nid_no_patch on every path,
directly or through a helper that always reaches it, stays a stub. One
that reaches it only under a condition (if, else, loop, switch, ternary,
short-circuit or lambda) is now classified as partial, so implemented
exports with guards for unknown behaviour are no longer counted as stubs.
progress.py and the progress page are unchanged.
A needed library with no file in --libs or --modules is reported, but when the
file sits elsewhere in the converted title's folder the report gave no way to
find it. import_audit now looks for it, case-insensitively, up to four levels
below each registry's folder and names the directory to pass with --modules.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The NID patcher and check_conventions resolve
fstat_nid_disambig1_nid_postfix to fstat. import_audit hashed it as
fstat_nid_disambig1, so a throwing stub with the suffix was keyed under
the wrong NID, and nid_names reported fstat and pwrite as rename-ready
instead of already-implemented.