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.1.0.tar.gz (3.9 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.1.0-py3-none-any.whl (2.8 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for who_calls-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f4d40ef5ef2f2514be6580c618a9366e182b50a82ae47b0ef3856e091da8850d
MD5 2d032d9c49c5bfc493237b0b6fa29aa4
BLAKE2b-256 289a0b0c35216b4cf1ac13cc29261ddcc33f7a85d1e76c8024f752bcbe9e71d2

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for who_calls-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b3cec8da9eb1003322fec66398ebbec50cd04871dbe470c792962b3b8052a6d6
MD5 8d5ad16bf1cfe17aebfecee6c92fadef
BLAKE2b-256 bce342a4ac05b00d2436951518ca486184cb5bf1cb65cc8dcf142037ff94258b

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