Skip to content

Improve pySpecs robustness: graceful failures, regex support, and reusable API#512

Open
joehendrix wants to merge 1 commit intomainfrom
jhx/pyspec_re
Open

Improve pySpecs robustness: graceful failures, regex support, and reusable API#512
joehendrix wants to merge 1 commit intomainfrom
jhx/pyspec_re

Conversation

@joehendrix
Copy link
Contributor

@joehendrix joehendrix commented Mar 3, 2026

Summary

Improves the robustness of the pySpecs command so it reports failures
gracefully — including regex usage — instead of aborting, and extracts
the core logic into a reusable API with CLI flags for skipping
definitions, controlling verbosity, and selecting log events.

Details

  • Graceful failure handling. When a Python import cannot be resolved,
    the translator now registers the imported names as opaque extern types
    and continues, rather than aborting. This means downstream references
    to those names still produce valid (if incomplete) output. Overload
    stubs with unexpected bodies produce a warning instead of failing.
  • Regex support. from re import compile is recognized via the
    built-in prelude, so Python files that use regex no longer trigger
    unknown-identifier errors. A test confirms this import resolves
    without warnings.
  • Reusable API. The translation logic that was inline in the CLI
    callback is extracted into a self-contained entry point in SimpleAPI.
    It validates inputs, parses skip-name strings, translates, writes
    output, and reports warnings — all returning structured errors instead
    of calling exitFailure. The CLI callback now delegates to this.
  • CLI flags. --skip <name> omits named top-level definitions from
    output (overloaded variants are always kept). --quiet suppresses
    logging and warnings. --log <event> enables specific event types.
  • Warning pipeline. Warnings are now collected during translation
    and returned to the caller as data, rather than being printed to
    stderr internally. A three-level verbosity setting (none / summary /
    detail) controls how they are reported.
  • Composable assertion expressions. The expression tree for
    preconditions and postconditions is refactored from fused nodes
    (e.g., "length >= N" as one node) into orthogonal building blocks
    (length, integer literal, greater-or-equal, etc.). This makes
    serialization a direct structural recursion with no special cases.
  • Readable DDM output. Assertions print as ensure(pred, msg).
    Comparisons use infix >=/<=. Class member blocks are indented
    on separate lines. These changes make the generated specs easier to
    read and diff.
  • Event logging cleanup. Logging no longer uses a global mutable
    reference; the set of enabled events is threaded through the
    translation context. Import messages now report after completion
    (past tense) and include warning counts.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@joehendrix joehendrix marked this pull request as draft March 3, 2026 23:27
Base automatically changed from jhx/pyspec_exceptions to main March 3, 2026 23:30
@joehendrix joehendrix force-pushed the jhx/pyspec_re branch 10 times, most recently from cfe01d0 to af909a0 Compare March 6, 2026 17:28
Improves the robustness of the pySpecs command so it reports failures
gracefully — including regex usage — instead of aborting, and extracts
the core logic into a reusable API with CLI flags for skipping
definitions, controlling verbosity, and selecting log events.

- Graceful failure handling: when a Python import cannot be resolved,
  the translator now registers the imported names as opaque extern types
  and continues, rather than aborting. Overload stubs with unexpected
  bodies produce a warning instead of failing.
- Regex support: `from re import compile` is recognized via the built-in
  prelude, so Python files that use regex no longer trigger
  unknown-identifier errors.
- Reusable API: the translation logic that was inline in the CLI callback
  is extracted into a self-contained entry point in SimpleAPI, returning
  structured errors instead of calling exitFailure.
- CLI flags: --skip omits named top-level definitions (overloads kept),
  --quiet suppresses logging and warnings, --log enables event types.
- Warning pipeline: warnings are collected during translation and
  returned as data; a three-level verbosity setting controls reporting.
- Composable assertion expressions: the expression tree is refactored
  from fused nodes into orthogonal building blocks, making serialization
  a direct structural recursion with no special cases.
- Readable DDM output: ensure(pred, msg) format, infix comparisons,
  indented class member blocks.
- Event logging cleanup: global mutable reference replaced by a context-
  threaded event set.
@joehendrix joehendrix changed the title Add re.compile to prelude to avoid crash on regex imports Improve pySpecs robustness: graceful failures, regex support, and reusable API Mar 6, 2026
@joehendrix joehendrix marked this pull request as ready for review March 6, 2026 17:35
@shigoel shigoel enabled auto-merge March 6, 2026 20:29
-- Parse skip names into PythonIdents
let some fileStem := pythonFile.fileStem
| throw s!"No file stem for {pythonFile}"
let stem := fileStem
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: looks like fileStem can be used everywhere and stem isn't needed

def ppSourceRange (fmm : FileMaps) (path : System.FilePath) (loc : SourceRange) : String :=
match fmm[path]? with
| none =>
panic! "Invalid path {file}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of scope for this PR, but noting a panic here that'd be a good candidate to convert to an exception.

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.

2 participants