Skip to main content

Static caller-tree explorer for Python code

Project description

who‑calls

Who calls my function? — A tiny static caller‑tree explorer for Python.

who‑calls scans a project’s source code with the built‑in ast module, builds a directed call‑graph (caller → callee), and prints every call‑path that can reach a target function. Output is an ASCII tree whose nodes are clickable file‑and‑line references in most modern terminals and IDEs.

├── main @ app/entry.py:28
│   └── orchestrate @ app/tasks/flow.py:71
│       └── do_work @ app/worker.py:42  <─ target
└── cli_entry @ app/cli.py:13
    └── do_work @ app/worker.py:42  <─ target

✨ Features

  • Static analysis only – no code execution, so it’s safe to run on untrusted repos or in CI.
  • Clickable labels – format func @ path.py:LINE so VS Code, PyCharm, Zed, etc. jump straight to the definition.
  • Regex‑based exclusion – skip vendored or generated code (.git.venv, .cache, tests by default).
  • Detects self.method() / cls.method() calls inside classes.
  • Clear error on ambiguous target names; accepts fully‑qualified package.module:Class.method style.

🚀 Installation (with UV)

uv pip install who‑calls

UV? uv is a super‑fast drop‑in replacement for pip + virtualenv. If you prefer stock tools, replace uv pip with pip.

Dev / editable install

uv venv .venv && source .venv/bin/activate
uv pip install -e .[dev]

🛠️ CLI usage

who‑calls <function> [OPTIONS]

Options:
  --root DIR         Project root (default: current directory)
  --exclude REGEX    Regex of paths to ignore (default: \\ .git | .venv | .cache | tests)

Examples:

# show who can reach do_work()
who‑calls do_work

# fully‑qualified target
who‑calls app.worker.do_work

# scan ./src and ignore build folder
who‑calls process_order --root src --exclude "build|dist"

If the short name matches multiple symbols you’ll get:

⚠ Ambiguous function name. Matches:
  • app.utils.filters:create_filter
  • app.api.v1.picking_filters.queries:create_filter
Please specify full path like <module>.<func> or <module>.<Class>.<method>.

🔍 How it works (high‑level)

  1. Recursively collect *.py files below --root, apply --exclude.

  2. Parse each file with ast.parse.

  3. Record every FunctionDef / AsyncFunctionDef with a fully‑qualified dotted name (pkg.mod.Class.func).

  4. Discover call edges:

    • foo() → unique match by name.
    • self.foo() / cls.foo() → method on same class.
    • obj.foo() → falls back to unique global match.
  5. Build a networkx.DiGraph, reverse it, keep only ancestors that can reach the target, then pretty‑print.


📦 Project structure

who‑calls/
├── pyproject.toml          # uv build backend
└── who_calls/
    ├── __init__.py         # exposes who_calls.main
    └── cli.py              # core logic (ast + networkx)

🖋️ License

MIT © 2025  janbjorge

Project details


Download files

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

Source Distribution

who_calls-0.2.0.tar.gz (6.3 kB view details)

Uploaded Source

Built Distribution

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

who_calls-0.2.0-py3-none-any.whl (5.5 kB view details)

Uploaded Python 3

File details

Details for the file who_calls-0.2.0.tar.gz.

File metadata

  • Download URL: who_calls-0.2.0.tar.gz
  • Upload date:
  • Size: 6.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.16

File hashes

Hashes for who_calls-0.2.0.tar.gz
Algorithm Hash digest
SHA256 624f1c6fef8e199dad016d9a10dc2b574d97fe9e2c53a6000637869bd1429c38
MD5 eb33891773d805b4b8da4400974e6721
BLAKE2b-256 5b0615c521071c3e98d44890ac8cd6c65117ed07f2e0d3d4b9bb56917cd68e97

See more details on using hashes here.

File details

Details for the file who_calls-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: who_calls-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 5.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.16

File hashes

Hashes for who_calls-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0c794cfe284d1300b9702b201d1d18260229ed97d6bd445bdcff07516c842ee6
MD5 cfdbd10e00cf0776f5c3678fb6f928bd
BLAKE2b-256 8f0048f3821136d0439d5a51441321aea60487f16756af6f858768f1f787ac60

See more details on using hashes here.

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