monty-type-checking
Type checking for Monty sessions, powered by ty: checks code against Monty’s trimmed typeshed before execution.
pub struct ImportedModule {
pub name: String,
/// The first import statement naming it.
pub range: ruff_text_size::TextRange,
}
A top-level module a snippet imports (a for import a.b and from a.b import c).
Implements: Debug, Eq, PartialEq, StructuralPartialEq.
pub struct SnippetImports {
/// Import statements with aliases, one per line, injected before later checks' `.pyi` star import.
/// This preserves bindings such as `import math`, which `.pyi` files do not re-export.
pub prelude: String,
/// Each top-level module imported, once, in source order.
pub modules: Vec<ImportedModule>,
}
Imports collected by scan_imports.
Implements: Debug, Default, Eq, PartialEq, StructuralPartialEq.
pub fn scan_imports(source: &str) -> SnippetImports;
Collects imports outside function and class bodies, excluding __future__ and relative imports.
Invalid syntax yields no imports. All module-level branches are included because the checker
cannot tell which ran, and any names bound at runtime must resolve.
pub struct SourceFile<'a> {
/// source code
pub source_code: &'a str,
/// file path
pub path: &'a str,
}
Definition of a source file.
pub fn new(source_code: &'a str, path: &'a str) -> Self
Create a new source file.
Implements: Clone, Copy, Debug.
pub struct TypeCheckContext<'a> {
/// Host stubs and committed snippets, star-imported into the snippet.
pub stubs: Option<&'a SourceFile<'a>>,
/// Host module stubs, written as `.pyi` modules or packages and never star-imported.
pub module_stubs: &'a [monty_types::ModuleStub],
/// Committed imports injected before the star import; see `scan_imports`.
pub prelude: &'a str,
}
Session declarations and imports for TypeChecker::run_with.
Implements: Clone, Copy, Debug, Default.
pub struct TypeChecker { /* private fields */ }
pub fn run<'a>(
&'a mut self,
python_source: &SourceFile<'_>,
stubs_file: Option<&SourceFile<'_>>,
config: TypeCheckingConfig,
) -> Result<Option<TypeCheckingDiagnostics<'a>>, String>
Type check some python source code, checking if it’s valid to run with monty.
python_source- The python source code to type check.stubs_file- Optional stubs file to use for type checking.config- Configuration for the type checking diagnostics.
Ok(None)- If there are no typing errors.Ok(Some(string))- If there are typing errors.Err(String)- If there was an unexpected/internal error during type checking, or the script path names the stubs file.
pub fn run_with<'a>(
&'a mut self,
python_source: &SourceFile<'_>,
context: &TypeCheckContext<'_>,
config: TypeCheckingConfig,
) -> Result<Option<TypeCheckingDiagnostics<'a>>, String>
run with host module stubs and committed imports.
The prelude precedes the stubs’ star import so later bindings shadow imports as at runtime.
Diagnostics use the snippet’s original line numbers.
pub fn reset(&mut self) -> Result<(), String>
Remove every file written since the last reset and sync the filesystem changes, so the checker can be reused for unrelated code.
Security-critical: without this a recycled worker would let one
session’s modules and stubs resolve while checking the next session’s
code. Each TouchedRootFile::cleanup removes its own file and walks its
ancestor chain up to SRC_ROOT, removing any directory that has become
empty. Shared parent directories collapse naturally once the last file
inside them is gone. We sync SRC_ROOT once at the end so the next
session cannot observe the previous root directory listing.
Implements: Debug, Default.
pub struct TypeCheckingDiagnostics<'a> { /* private fields */ }
The diagnostics of one failed type check, rendered on Display.
Borrows the checker because ty’s diagnostics only resolve their spans (file
paths, source snippets) against the database that produced them — which is
why the format is chosen up front, in TypeChecker::run, and why callers
that outlive the checker (anything across a process boundary) must keep the
rendered string rather than this.
Implements: Display.