Skip to content

errors: AST linter check_error_codes (raise + registry enforcement)#104

Closed
AbdelStark wants to merge 1 commit into
errors/hierarchy-and-registryfrom
errors/ast-linter-error-codes
Closed

errors: AST linter check_error_codes (raise + registry enforcement)#104
AbdelStark wants to merge 1 commit into
errors/hierarchy-and-registryfrom
errors/ast-linter-error-codes

Conversation

@AbdelStark

Copy link
Copy Markdown
Owner

Stacked on #103. Base branch is errors/hierarchy-and-registry so the diff shows only the linter; will retarget to main once #103 merges.

Problem

RFC-0012 §3.3 and RFC-0015 §3.4 require two AST checks at PR time:

  • raise_geno_lewm_errorraise X(...) in geno_lewm/ only raises GenoLeWMError subclasses.
  • registered_error_code — the raised class is one of the leaves listed in ERROR_CODES.

Without these, the registry from #21 drifts silently the moment anyone starts raising real exceptions.

Solution

  • tools/lint/check_error_codes.py
    • Parses geno_lewm/errors.py with ast to discover the legal class set — no runtime import dependency.
    • Walks every .py file under the targets (default geno_lewm/) and inspects every ast.Raise.
    • Allows bare re-raises (raise inside except); flags everything else not in the registry.
    • Splits diagnostics into the two checks: known-stdlib builtins get the raise_geno_lewm_error message; unknown names get registered_error_code (likely registry drift).
    • Output is GitHub-Actions-friendly file:line:col: error: [check] message.
    • Skips errors.py itself (self-reference would loop).
  • tests/lint/test_check_error_codes.py: registry discovery, bare re-raise, Name & Attribute raises, builtin raises (parametrized over 6 common exceptions), raise … from, syntax errors as violations, main() exit codes, format spec.
  • .github/workflows/lint-errors.yml: standalone per-PR workflow running the linter. Designed to fold into the full per-PR CI workflow when testing: implement GitHub Actions per-PR CI workflow #86 lands.

Validation

$ python -m tools.lint.check_error_codes
$ echo $?
0

$ python -m pytest tests/lint/ tests/unit/ -q
144 passed in 0.09s

Caveats

  • The workflow only runs on pull_request / push to main. Once testing: implement GitHub Actions per-PR CI workflow #86 ships the full per-PR CI, this can be merged into it.
  • The linter rejects raise GenoLeWMError(...) because the root class is not in ERROR_CODES. Intentional — RFC says leaf classes only.
  • Whitelist approach is name-based (not type-resolved). That's the same trade-off tach and flake8-tidy-imports make: simple, fast, false-positive only on dynamic raises (raise cls(...) where cls is a runtime variable) — which is itself a smell the spec discourages.

Closes #22

Adds tools/lint/check_error_codes.py implementing the two AST checks
required by RFC-0012 §3.3 and RFC-0015 §3.4:

- raise_geno_lewm_error: every ``raise X(...)`` in geno_lewm/ raises a
  registered GenoLeWMError subclass (or is a bare re-raise).
- registered_error_code: the raised class is one of the leaf classes
  listed in geno_lewm/errors.py::ERROR_CODES.

The linter parses geno_lewm/errors.py with the ast module to discover
the legal class set, so it has no runtime dependency on the package
being installable. Output is GitHub-Actions-friendly
file:line:col: error: [check_name] message.

Wired into a standalone .github/workflows/lint-errors.yml that runs
on PR. Will fold into the full per-PR CI workflow (#86) when that
lands.

Tests in tests/lint/test_check_error_codes.py cover:
- registry discovery against the real errors module
- bare re-raise (allowed)
- registered raises (Name and Attribute forms)
- builtin raises (flagged)
- unregistered class raises (flagged)
- raise-from (still inspects class)
- syntax errors (reported as violations)
- the errors module itself is skipped

Closes #22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant