Skip to content

feat: add Python type checking via embedded ty - #194

Draft
sd2k wants to merge 8 commits into
mainfrom
feat/eryx-check
Draft

feat: add Python type checking via embedded ty#194
sd2k wants to merge 8 commits into
mainfrom
feat/eryx-check

Conversation

@sd2k

@sd2k sd2k commented Apr 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds eryx-check crate that embeds ruff's Python parser and ty's type checker as Rust library dependencies (git-pinned to the ruff commit used by ty 0.0.29)
  • Adds a unary Check gRPC RPC to eryx-server for static analysis of Python code before execution
  • Generates .pyi callback stubs from CallbackDeclarations so await query_loki(expr=...) is type-checked against the declared parameter types

eryx-check crate

  • check_syntax() — fast syntax validation via ruff's parser
  • check_types() — full type checking via ty with typeshed stubs
  • check_types_with_options() — accepts supporting files and callback declarations
  • Callback stub generation maps JSON Schema types to Python type annotations
  • Uses a minimal salsa database with an in-memory filesystem (no disk I/O)

Check RPC

  • rpc Check(CheckRequest) returns (CheckResponse) — unary, no streaming needed
  • Reuses existing SupportingFile and CallbackDeclaration proto messages
  • Runs on spawn_blocking since type checking is CPU-bound
  • Returns diagnostics with severity, source (syntax/type), and byte offsets into the original source

Dependencies

  • ~66 new crates, primarily from the ruff/ty ecosystem (parser, AST, salsa, typeshed stubs)
  • Isolated in the eryx-check crate — no impact on eryx-server binary size unless opted into

Test plan

  • 15 unit tests in eryx-check (stub generation, syntax checking, type checking, callback validation, offset adjustment)
  • 19 unit tests in eryx-server pass (pre-existing)
  • cargo clippy -p eryx-check -p eryx-server -- -D warnings clean
  • e2e gRPC tests for Check RPC (existing e2e tests require WASM runtime build)

🤖 Generated with Claude Code

sd2k and others added 4 commits April 11, 2026 12:18
New workspace crate that embeds ruff's Python parser and ty's type
checker as git dependencies (pinned to the ruff commit used by ty 0.0.29).

Exposes two APIs:
- check_syntax(): fast syntax validation via ruff_python_parser
- check_types(): full type checking via ty with typeshed stubs

Uses a minimal salsa database with an in-memory filesystem to run ty
without touching disk. Kept as a separate crate to avoid bloating
eryx-server with the ty/salsa dependency tree.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…pporting files

Adds a unary Check RPC to the gRPC server for static analysis of Python
code before execution. Uses ty (Astral's type checker) embedded as a
Rust library dependency via git pin.

eryx-check crate additions:
- stubs.rs: generates .pyi stub files from CallbackDeclarations so
  the type checker can validate `await query_loki(expr=...)` calls
- check_types_with_options(): accepts supporting files and callback
  declarations, writes them to an in-memory filesystem, and runs ty
- Offset adjustment for diagnostics when callback import is prepended

eryx-server additions:
- Check RPC in proto: CheckRequest (code, files, callbacks) →
  CheckResponse (diagnostics with severity, source, byte offsets)
- Service handler runs type checking on a blocking thread via
  spawn_blocking since it's CPU-bound
- Reuses existing SupportingFile and CallbackDeclaration proto messages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The ruff/ty crates use edition 2024 which requires Rust 1.92+.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updates all references to match the MSRV bump in Cargo.toml.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

🌐 Demo preview: https://feat-eryx-check.eryx-bvy.pages.dev
📌 This deploy: https://ff999fe5.eryx-bvy.pages.dev

sd2k and others added 3 commits April 11, 2026 19:07
Workspace lints warn on unwrap_used; allow it in test modules
to match the pattern used by other crates (e.g. grpc_e2e.rs).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9 tests covering: valid code, syntax errors, type errors, supporting
module files, DATA file filtering, callback stubs (correct usage,
wrong arg type, optional params), and diagnostic offset validation.

Also fixes the Check handler to run both check_syntax() and
check_types_with_options() so syntax errors are always reported
even if the type checker setup fails.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eryx scripts use PyCF_ALLOW_TOP_LEVEL_AWAIT at runtime, so top-level
`await`, `async for`, and `async with` are valid. Suppress the
corresponding ty diagnostics since they're false positives for eryx.

Adds an e2e test for top-level await with callback stubs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sd2k
sd2k force-pushed the feat/eryx-check branch from 8b56dbc to 1f6e9e5 Compare April 12, 2026 06:42
Adds ruff's Python formatter as a library dependency and exposes it
via a new unary Format RPC. The formatter operates on raw user source
code directly — no preamble or stubs needed since formatting is purely
syntactic.

- eryx-check: adds format_source() wrapping ruff_python_formatter
- Proto: FormatRequest (code) → FormatResponse (formatted_code, error)
- Server: spawn_blocking handler, returns error for syntax-invalid code
- 4 e2e tests: whitespace fixes, idempotent, syntax error, multiline

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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