|
| 1 | +# Grimp |
| 2 | + |
| 3 | +Grimp builds a queryable graph of the imports within one or more Python packages. It's a |
| 4 | +hybrid Python/Rust project: the public API and orchestration are in Python |
| 5 | +(`src/grimp/`), and the import scanning and graph algorithms are implemented in Rust |
| 6 | +(`rust/`) as a PyO3 extension module (`grimp._rustgrimp`), built with maturin. |
| 7 | + |
| 8 | +## Architecture |
| 9 | + |
| 10 | +`src/grimp/` follows a layered/hexagonal architecture, enforced by Import Linter itself |
| 11 | +(see `.importlinter`): |
| 12 | + |
| 13 | +- `domain/` — core types (`valueobjects.py`, `analysis.py`), no dependencies on other layers. |
| 14 | +- `application/` — use cases and ports (`usecases.py`, `graph.py`, `scanning.py`, `config.py`). |
| 15 | +- `adaptors/` — implementations of application ports (filesystem, module/package finding, |
| 16 | + caching, timing). |
| 17 | +- `main.py` — top-level entry point (`grimp.build_graph`), wires adaptors to use cases. |
| 18 | +- `exceptions.py` — shared exceptions, importable from any layer. |
| 19 | + |
| 20 | +Respect this layering: `domain` must not import from `application` or `adaptors`, etc. Run |
| 21 | +`just lint-python` (which includes `lint-imports`) to check. |
| 22 | + |
| 23 | +The Rust side (`rust/src/`) does the heavy lifting: import parsing (via `ruff`'s parser), |
| 24 | +module/import scanning, and graph algorithms (`rust/src/graph/`: pathfinding, cycle |
| 25 | +detection, hierarchy queries, etc.). |
| 26 | + |
| 27 | +## Setup |
| 28 | + |
| 29 | +Prerequisites: `git`, [`uv`](https://docs.astral.sh/uv/), [`just`](https://just.systems/), |
| 30 | +and Rust via [`rustup`](https://rust-lang.org/tools/install/). No virtualenv management is |
| 31 | +needed — `uv` handles it. Run `just install-precommit` once to set up pre-commit hooks. |
| 32 | + |
| 33 | +Run `just help` (or `just --list`) to see all available recipes. |
| 34 | + |
| 35 | +## Common commands |
| 36 | + |
| 37 | +- `just compile` — build the Rust extension for development (via `maturin develop`). Needed |
| 38 | + after any change to `rust/`. |
| 39 | +- `just test-python` — run Python tests (default Python version). Pass a version to target |
| 40 | + another, e.g. `just test-python 3.14`. |
| 41 | +- `just test-rust` — run Rust tests. |
| 42 | +- `just compile-and-test` — compile Rust, then run Rust and Python tests. Use this after |
| 43 | + touching Rust code. |
| 44 | +- `just lint` — ruff format check, ruff check, mypy, and `lint-imports` for Python; `cargo |
| 45 | + fmt --check` and `cargo clippy` for Rust. |
| 46 | +- `just autofix` — autofix both Python (ruff) and Rust (clippy --fix) issues. |
| 47 | +- `just build-and-open-docs` — build Sphinx docs and open them locally. |
| 48 | +- `just full-check` — lint + docs build + tests across all supported Python versions. Run |
| 49 | + this before requesting a review. |
| 50 | + |
| 51 | +## Working with tests |
| 52 | + |
| 53 | +Most tests are Python (`tests/`); Rust tests are optional for a change unless you touched |
| 54 | +Rust internals. Aim for full test coverage at the Python level. Snapshot tests use Syrupy — |
| 55 | +regenerate with `just update-snapshots` when a snapshot legitimately needs to change, and |
| 56 | +review the diff. |
| 57 | + |
| 58 | +Important principle: even if the implementation is in Rust, write the tests in Python. |
| 59 | +The Python tests are regression tests, the Rust tests are there purely to aid development / debugging |
| 60 | +in certain cases, and are optional. |
| 61 | + |
| 62 | +## Conventions |
| 63 | + |
| 64 | +- Add a `CHANGELOG.rst` entry (imperative mood) under the `latest` section at the top for |
| 65 | + any user-facing change; create the section if it doesn't exist. |
| 66 | +- Add yourself to `AUTHORS.rst` for a first contribution. |
| 67 | +- For non-trivial changes, prefer discussing direction in a GitHub issue before large PRs |
| 68 | + (see `CONTRIBUTING.rst`). |
| 69 | +- Update documentation (`docs/`) when adding or changing public API/functionality. |
| 70 | + |
| 71 | +## Full contributor guide |
| 72 | + |
| 73 | +`CONTRIBUTING.rst` has the complete guide, including benchmarking (Codspeed and local), |
| 74 | +profiling, and the PyPI release process. |
0 commit comments