Skip to main content

pyoverview

Static analyzer that turns a Python project into a single, deterministic Markdown overview: metadata, directory tree, entry points, per-file docstrings/imports/exports/signatures, a project-wide symbol table, resolved "used by" back-references (with confidence levels), a module dependency graph, a flattened public API index, and an unresolved-reference report.

Built entirely on the ast module. It never imports or executes the project it analyzes.

Installation

Distributed on PyPI as cpm-pyoverview (the pyoverview name was already taken by an unrelated package); the installed command is cpm-pyoverview.

uv tool install cpm-pyoverview
# or
pipx install cpm-pyoverview
# or
pip install cpm-pyoverview

For local development instead of installing from PyPI, see CONTRIBUTING.md.

Usage

cpm-pyoverview ./path/to/project --output overview.md

Options:

--output PATH                 Write to PATH instead of stdout
--include PATTERN             Glob pattern to include (repeatable)
--exclude PATTERN             Glob pattern to exclude (repeatable)
--python-version VERSION      Declared target version (metadata only, see limitations)
--include-private             Include underscore-prefixed definitions in the Files section
--include-tests               Include tests/ files in the rendered Files section
--show-line-numbers            Append :line to reference locations
--include-local-references     Include "used by" references originating from the same file
--strict                      Exit non-zero if any file has a syntax error
--fail-on-unresolved           Exit non-zero if any reference is unresolved
--version                     Print the installed version and exit

Architecture

Three passes, each backed by a focused module:

  1. Parse (parser.py, syntax-only, per file, via ast_visitors.py) → ParsedModule (internal only -- holds the retained AST tree).
  2. Resolve (project_resolver.py orchestrating module_resolver.py, import_resolver.py, export_resolver.py, binding.py, symbol_table.py, entry_point_resolver.py) → ResolvedModule + project-wide symbol table + dependency edges.
  3. Reference (reference_resolver.py, bounded type inference) → graded resolved / probable / unresolved usage references.

markdown_renderer.py is a pure function (ProjectInfo -> str); cli.py wires the pipeline together.

Known limitations

  • Method-call type inference is bounded, not full type checking: single-function scope, one hop of attribute/alias propagation, and a binding is invalidated (never guessed) the moment it sees two different constructor assignments. No interprocedural or control-flow-sensitive analysis beyond that.
  • Export inference is conservative: imported names are never treated as re-exports unless they also appear in a statically resolved __all__ -- even in __init__.py. This avoids silently promoting ordinary imports to public API, at the cost of missing some intentional re-export patterns.
  • --python-version is metadata-plus-parsing only: stdlib-module classification always uses the running interpreter's sys.stdlib_module_names, since Python does not ship a way to query an arbitrary historical version's stdlib module list.
  • Entry-point detection is conservative: only if __name__ == "__main__": guards and pyproject.toml [project.scripts] / [project.gui-scripts]. Framework-specific route/command discovery (Flask, Click, FastAPI, etc.) is not attempted.
  • Module-name resolution is heuristic: a top-level src/ directory, if present, is treated as the import root; otherwise the project root is. This covers conventional layouts but is not a full sys.path/package configuration resolution.
  • Dynamic Python is always unresolved, never guessed at: getattr/setattr, importlib.import_module/__import__, wildcard imports, monkeypatching, and framework-based discovery all surface in the "Unresolved References" section with a reason, rather than being silently omitted or confidently mis-resolved.
  • Name-binding lookup is module-flat, not precisely scope-nested: a name shadowed only inside one function can occasionally over-resolve against an unrelated module-level binding of the same name.

Testing

uv run pytest

Includes unit tests per component and an integration test running the full pipeline against tests/fixtures/demo_project (multi-package, re-exports, tests, a circular dependency, aliased imports, async methods, a dynamic import, and an ambiguous method call), snapshot-compared against tests/integration/__snapshots__/demo_project.md. Regenerate the snapshot deliberately after a reviewed output-format change with:

UPDATE_SNAPSHOTS=1 uv run pytest tests/integration

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cpm_pyoverview-0.1.0.tar.gz (51.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cpm_pyoverview-0.1.0-py3-none-any.whl (42.6 kB view details)

Uploaded Python 3

File details

Details for the file cpm_pyoverview-0.1.0.tar.gz.

File metadata

  • Download URL: cpm_pyoverview-0.1.0.tar.gz
  • Upload date:
  • Size: 51.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cpm_pyoverview-0.1.0.tar.gz
Algorithm Hash digest
SHA256 77d6d9293130dc01ccfa922eec9b323726769003a128f57a10cb029b9ef43bfb
MD5 23195b1f8efdad7f8beb3d7d9dd4979b
BLAKE2b-256 f24f3d813375baf23ca5b37c8287d83c7c5adde1a865cddf8fe66ea89dd03f53

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpm_pyoverview-0.1.0.tar.gz:

Publisher: publish.yml on cprima/pyoverview

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpm_pyoverview-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: cpm_pyoverview-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 42.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cpm_pyoverview-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0370e3c177dd900539573a12b5b9f4db9105eaab5a39d564664c323da2d4cb0e
MD5 180aac1be662fb8ebba2ef5fa000fcb6
BLAKE2b-256 d2c10e6f16a7a9acbe17bf4593aaf5326c44026ee6c06cce771741a3fb9060dd

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpm_pyoverview-0.1.0-py3-none-any.whl:

Publisher: publish.yml on cprima/pyoverview

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page