Metadata-Version: 2.5
Name: pymap-cli
Version: 0.4.0
Summary: Map a Python codebase in one command.
Project-URL: Homepage, https://github.com/hermann225-zrouama/pymap-cli
Project-URL: Issues, https://github.com/hermann225-zrouama/pymap-cli/issues
Project-URL: Changelog, https://github.com/hermann225-zrouama/pymap-cli/blob/main/CHANGELOG.md
Author: Franck Zrouama
License-Expression: MIT
License-File: LICENSE
Keywords: architecture,ast,call graph,codebase map,documentation
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Documentation
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.9
Provides-Extra: dev
Requires-Dist: code2flow>=2.5; extra == 'dev'
Requires-Dist: pydeps>=1.11; extra == 'dev'
Requires-Dist: pylint>=2.15; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: tach>=0.9; extra == 'dev'
Requires-Dist: tomli>=2.0; (python_version < '3.11') and extra == 'dev'
Provides-Extra: graphs
Requires-Dist: code2flow>=2.5; extra == 'graphs'
Requires-Dist: pydeps>=1.11; extra == 'graphs'
Requires-Dist: pylint>=2.15; extra == 'graphs'
Requires-Dist: tach>=0.9; extra == 'graphs'
Provides-Extra: toml
Requires-Dist: tomli>=2.0; (python_version < '3.11') and extra == 'toml'
Description-Content-Type: text/markdown

# pymap

Map a Python codebase in one command. No service, no upload: everything is
analysed and rendered locally.

```bash
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

```bash
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:

```bash
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

```bash
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):

```toml
[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

```python
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

<kbd>↓</kbd> <kbd>↑</kbd> walk the steps · <kbd>↵</kbd> step into the
highlighted call · <kbd>←</kbd> go back up · <kbd>m</kbd> mark seen ·
<kbd>o</kbd> open in the editor · <kbd>/</kbd> 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](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. `tach` requires a `tach.toml`
  at 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
  with `app/models.py` and `blog/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 sync` gets 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 `getattr` do not appear.

## Development

```bash
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](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`.
