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:LINEso VS Code, PyCharm, Zed, etc. jump straight to the definition. - Regex‑based exclusion – skip vendored or generated code
(
.git,.venv,.cache,testsby default). - Detects
self.method()/cls.method()calls inside classes. - Clear error on ambiguous target names; accepts fully‑qualified
package.module:Class.methodstyle.
🚀 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 pipwithpip.
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)
-
Recursively collect
*.pyfiles below--root, apply--exclude. -
Parse each file with
ast.parse. -
Record every
FunctionDef/AsyncFunctionDefwith a fully‑qualified dotted name (pkg.mod.Class.func). -
Discover call edges:
foo()→ unique match by name.self.foo()/cls.foo()→ method on same class.obj.foo()→ falls back to unique global match.
-
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
Release history Release notifications | RSS feed
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 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f4d40ef5ef2f2514be6580c618a9366e182b50a82ae47b0ef3856e091da8850d
|
|
| MD5 |
2d032d9c49c5bfc493237b0b6fa29aa4
|
|
| BLAKE2b-256 |
289a0b0c35216b4cf1ac13cc29261ddcc33f7a85d1e76c8024f752bcbe9e71d2
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3cec8da9eb1003322fec66398ebbec50cd04871dbe470c792962b3b8052a6d6
|
|
| MD5 |
8d5ad16bf1cfe17aebfecee6c92fadef
|
|
| BLAKE2b-256 |
bce342a4ac05b00d2436951518ca486184cb5bf1cb65cc8dcf142037ff94258b
|