zerum 0.2.0

Deterministic-first Python code governance: ~75 native checks (ZR001–ZR510), explain mode, human/JSON CLI
Documentation
use crate::parser::{ParsedFile, PythonParser};
use anyhow::Result;
use rustpython_parser::{parse, Mode, ParseError};
use std::path::Path;

#[derive(Debug, Default)]
pub struct RustPythonParser;

impl PythonParser for RustPythonParser {
    fn parse_file(&self, source: &str, path: &Path) -> Result<ParsedFile> {
        let display = path.display().to_string();
        let module = parse(source, Mode::Module, &display).map_err(map_parse_error)?;
        Ok(ParsedFile {
            path: path.to_path_buf(),
            source: source.to_string(),
            module,
        })
    }
}

fn map_parse_error(err: ParseError) -> anyhow::Error {
    anyhow::anyhow!("failed to parse Python source: {err}")
}