pymap
Map a Python codebase in one command. No service, no upload: everything is analysed and rendered locally.
cd my-project
pymap --open
pymap guesses which package to analyse, runs whichever graph tools you have installed, and assembles the result into a single page — plus a flow explorer that pymap builds itself: for every function, the order of the calls, the conditions, the loops, the error paths, and the data flowing through.
Install
pipx install pymap-cli # isolated, available everywhere
# or, inside the project you want to map:
pip install pymap-cli
The core depends only on the standard library, so installing pymap into a project adds no version constraint to it. The graph tools are optional and live behind an extra:
pip install "pymap-cli[graphs]" # pydeps, code2flow, pylint, tach
brew install graphviz # or: apt install graphviz
Any missing tool is reported at start-up and then skipped; the explorer always works.
Usage
pymap # guess the current project's package
pymap src/mypkg # explicit target
pymap src/mypkg -o map/ --open # output directory, open when done
pymap --exclude "generated_*" # skip more paths
pymap --editor pycharm # code links for another editor
How the target is guessed, in order: [tool.pymap] target in pyproject.toml,
a src/<package>/ layout, the package named after the project, then the single
top-level package. If nothing stands out, pymap says so and waits for a path.
Configuration
Optional, in the project's pyproject.toml (read on Python ≥ 3.11, or with
tomli installed):
[tool.pymap]
target = "src/mypkg"
output = "pymap-out"
editor = "vscode" # vscodium, cursor, windsurf, zed, pycharm,
# idea, sublime, none, or "myeditor://{f}:{l}"
exclude = ["vendor", "generated_*"]
timeout = 300 # seconds per external tool
As a library
from pymap import Settings, map_codebase
report = map_codebase(Settings(target="src/mypkg", output="map/"))
print(report.coverage, "% documented,", len(report.cycles), "cycles")
What the map contains
| View | Source | What you read there |
|---|---|---|
| Walkthrough tree | pymap (AST) | The execution flow function by function, keyboard-navigable |
| Imports between modules | pydeps | The layers, and the modules everyone pulls in |
| Classes and inheritance | pyreverse | Attributes and hierarchies, when the code is object-oriented |
| Module boundaries | tach | File-by-file dependencies, cycles, Mermaid source |
The output directory (pymap-out/ by default) holds index.html — the page to
open — and the views it links to.
In the explorer
↓ ↑ walk the steps · ↵ step into the highlighted call · ← go back up · m mark seen · o open in the editor · / search
How the code is organised
src/pymap/
├── cli.py command line: arguments, pyproject, messages
├── settings.py what to analyse, where to write, what to skip
├── mapper.py orchestration + library API
├── runner.py launching external tools, detecting missing ones
├── render.py templates → HTML pages
├── analysis/ what pymap works out on its own, from the AST
│ ├── symbols.py modules, classes, functions, signatures
│ ├── flow.py execution tree of a function
│ ├── calls.py code2flow's call graph
│ └── cycles.py circular dependencies
├── tools/ one module per external tool
│ ├── pydeps.py pyreverse.py code2flow.py tach.py
└── templates/ index.html, section.html, explorer.html
Adding a tool: drop a module in tools/ exposing execute(settings) that
returns raw facts (never HTML), then add one line to STEPS and one section to
_sections(), both in mapper.py. See CONTRIBUTING.md.
Guarantees
- Nothing is executed from the analysed code: everything goes through the standard library's AST.
- Nothing is written into the target project.
tachrequires atach.tomlat the root of wherever it runs, so pymap copies the sources into a temporary directory instead of dropping that file in your tree. - Environments and caches (
.venv/,node_modules/,build/,__pycache__/, …) are pruned during the walk, never traversed.
Known limitations
- Files sharing a basename share a namespace. Symbol keys are
<file stem>::<qualified name>, because that is how code2flow names its graph nodes and it is what lets the two data sets be joined. In a project withapp/models.pyandblog/models.py, their symbols merge in the explorer. pymap prints a note when it detects the case. - tach declares at most 60 modules. Beyond that
tach syncgets very slow for a graph that is already unreadable. The count left out is reported. - The call graph is only as good as code2flow's static resolution: calls
through dynamic dispatch or
getattrdo not appear.
Development
git clone https://github.com/hermann225-zrouama/pymap-cli
cd pymap-cli
pip install -e ".[dev]"
pytest
ruff check src tests && ruff format --check src tests
pymap # pymap maps itself
tests/test_contract.py pins the key names shared between the Python payload
and templates/explorer.html. A rename on one side without the other produces
a blank page rather than an error, so that test is what keeps them honest.
Licence
MIT — see LICENSE.
The distribution is named pymap-cli because pymap is already taken on PyPI
by an IMAP library. The command and the import name are both pymap.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pymap_cli-0.3.0.tar.gz.
File metadata
- Download URL: pymap_cli-0.3.0.tar.gz
- Upload date:
- Size: 44.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f04774cf18d4fbd4364717ad91a4fece3abfa8f5d36d55af9017634bf30f2e5f
|
|
| MD5 |
ebc7d88adf708c46e3a1f4e5db6cca94
|
|
| BLAKE2b-256 |
5c148ca6a847c2b6e0b8ad5cc03e53d0a3cf6240d13b812dbc0337b9827989b8
|
Provenance
The following attestation bundles were made for pymap_cli-0.3.0.tar.gz:
Publisher:
publish.yml on hermann225-zrouama/pymap-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pymap_cli-0.3.0.tar.gz -
Subject digest:
f04774cf18d4fbd4364717ad91a4fece3abfa8f5d36d55af9017634bf30f2e5f - Sigstore transparency entry: 2713922328
- Sigstore integration time:
-
Permalink:
hermann225-zrouama/pymap-cli@5cde6c6cf7abd96631595f79dc377a51b7654929 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/hermann225-zrouama
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5cde6c6cf7abd96631595f79dc377a51b7654929 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pymap_cli-0.3.0-py3-none-any.whl.
File metadata
- Download URL: pymap_cli-0.3.0-py3-none-any.whl
- Upload date:
- Size: 41.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
658367b70048ed772a0c48999ba0937593e0418ed2b6c73cc13a385feda68fde
|
|
| MD5 |
ae5dac697f3bd20e289363f3686d08af
|
|
| BLAKE2b-256 |
83dfbfb55457600ecdcc9489a5edbb63c2714fc1a230b671e8caf849a35f568d
|
Provenance
The following attestation bundles were made for pymap_cli-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on hermann225-zrouama/pymap-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pymap_cli-0.3.0-py3-none-any.whl -
Subject digest:
658367b70048ed772a0c48999ba0937593e0418ed2b6c73cc13a385feda68fde - Sigstore transparency entry: 2713922346
- Sigstore integration time:
-
Permalink:
hermann225-zrouama/pymap-cli@5cde6c6cf7abd96631595f79dc377a51b7654929 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/hermann225-zrouama
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5cde6c6cf7abd96631595f79dc377a51b7654929 -
Trigger Event:
push
-
Statement type: