Live, dynamic network visualization of Python code — static call graph + runtime tracing in your browser.
Project description
Évariste
Live, dynamic network visualization of Python code — see your code as a living graph.
evariste-core gives Python the kind of interactive, in-browser call-graph
view that other ecosystems take for granted:
- Static graph — an AST-based map of your project (like Go to Definition rendered as a network). FastAPI routes are highlighted.
- Runtime overlay — a
@tracedecorator streams real calls over a WebSocket; nodes warm, edges light, and timings appear as calls happen. - FastAPI Explorer — call your own endpoints from the UI and watch exactly which functions got touched, with captured arg values.
Minimal, zero-frontend-build, MIT-licensed.
Install
pip install evariste-core
The PyPI distribution is called
evariste-core(the bareevaristename on PyPI belongs to an unrelated project). The Python import name is still justevariste— nothing in your code changes.
The 60-second tour — drop it into your FastAPI app
One line. That's the integration.
from fastapi import FastAPI
import evariste
app = FastAPI()
evariste.attach(app) # <-- the whole thing
@app.get("/users/{user_id}")
def get_user(user_id: str):
return load(user_id)
@app.post("/orders")
def create_order(cart: Cart):
return checkout(cart)
Run your app normally (uvicorn myapp:app --reload), open
http://localhost:8000/__evariste__/ui in a browser, and you'll see:
- The static graph of every function in your source tree.
- Endpoints highlighted and browsable from the left drawer.
- Live runtime overlay — every request lights up its call tree.
- A FastAPI tab where you can invoke routes from the UI and watch exactly which code paths fired, with captured arg values.
No second server, no extra port, no code changes beyond that one call.
What attach() does under the hood
- Scans your source tree. Walks up from the caller's file to the outermost Python package to find your project root, then runs the AST analyzer on it.
- Auto-traces every route. Wraps each registered
APIRoute's handler with@evariste.traceso HTTP requests appear in the graph without you decorating anything manually. - Mounts the UI + API under
/__evariste__/*on your own app — shares your port, your TLS, your reverse proxy. - Refuses non-loopback traffic by default. Accidentally shipping
attach()to prod does not leak source code.
Safety knobs (all optional)
evariste.attach(
app,
# Defaults: loopback-only, no auth, no arg capture.
allow_hosts=("127.0.0.1", "::1"), # widen if behind a trusted proxy
auth_token=None, # set a bearer token to gate access
capture_args=False, # include arg/return reprs in events
source_path=None, # override the auto-detected scan root
prefix="/__evariste__", # change the URL mount prefix
enabled=None, # None → defer to EVARISTE_DISABLED env
)
For production: set EVARISTE_DISABLED=1 in your prod environment.
The attach() call becomes a no-op with zero code changes. One-line
kill-switch your ops team controls.
Install + run an example
A realistic FastAPI demo ships in examples/demo_api.py:
pip install evariste-core
python examples/demo_api.py
# → FastAPI on http://localhost:8000
# → Évariste UI on http://localhost:8000/__evariste__/ui
The demo seeds its own traffic in a background thread so you get something visibly alive the moment you open the UI.
Manual decoration (when you need more control)
attach() auto-traces your endpoints. If you want internal helpers
to appear in the live graph too, decorate them explicitly:
import evariste
@evariste.trace
def validate(token: str) -> bool: ...
@evariste.trace
async def fetch_user(user_id: str) -> User: ...
@trace works on sync, async, and methods. It uses functools.wraps so
FastAPI's dependency system, Pydantic validation, and every other
introspecting tool keep seeing the original signature.
To wrap a whole module at once:
import evariste, myapp.services
evariste.module_trace(myapp.services)
Standalone mode — no FastAPI?
You can still use Évariste with any Python codebase. Decorate what you care about, scan the source, start the server:
import evariste
@evariste.trace
def compute(n):
return sum(i * i for i in range(n))
@evariste.trace
def handle_request():
return compute(10_000)
evariste.scan(".") # populate the static graph
evariste.start() # http://localhost:7878 opens your browser
for _ in range(50):
handle_request()
Or skip the code entirely and run the CLI:
evariste view path/to/your/project
# scans + serves the static graph on localhost:7878
Capturing args and return values
Off by default (zero overhead, zero leakage). Turn it on explicitly:
evariste.attach(app, capture_args=True) # for FastAPI apps
# or
evariste.set_capture(True, max_repr=200) # anywhere
Captured values appear in the inspector's "last invocation" panel,
truncated to max_repr chars, safe-repr'd so broken __repr__
implementations can never break tracing.
Caching events to disk + replay
evariste.set_cache("evariste_events.jsonl") # append-only JSONL
# Later:
evariste.replay("evariste_events.jsonl", speed=0.5) # half-speed replay
Or from the CLI:
evariste replay evariste_events.jsonl --speed 1.0
Public API
| Symbol | Purpose |
|---|---|
evariste.attach(app, **kw) |
FastAPI one-line integration. Scans, auto-traces, mounts the UI. |
evariste.trace |
Decorator — wraps sync & async callables. |
evariste.module_trace(module) |
Auto-wrap every public function/class in a module. |
evariste.scan(path, *, module=None) |
AST analyzer — populate the static graph. |
evariste.start(host, port, **kw) |
Launch the standalone viz server in a background thread. |
evariste.stop() |
Shut the standalone server down. |
evariste.set_capture(enabled, *, max_repr=120) |
Toggle arg/return capture. |
evariste.set_cache(path) |
Persist events to a JSONL file. |
evariste.replay(path, *, speed=1.0) |
Re-emit a cached event stream through the live UI. |
evariste.events() |
Snapshot of the in-memory ring buffer (for tests). |
Why "Évariste"?
After Évariste Galois — the mathematician who first saw structure as a graph of relationships.
License
MIT — see LICENSE. Bug reports and PRs welcome.
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 evariste_core-0.3.0.tar.gz.
File metadata
- Download URL: evariste_core-0.3.0.tar.gz
- Upload date:
- Size: 103.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d413dfa3b94dc48ba0928ead2ac05aaa45f955e17c84435c7c26f157729b882b
|
|
| MD5 |
cac443b5ae94d2362c07bbb384afd98e
|
|
| BLAKE2b-256 |
cd4dc552fe0601d5d0aba9c584b2e220838e47b23e954622a5010fdbeac7c646
|
File details
Details for the file evariste_core-0.3.0-py3-none-any.whl.
File metadata
- Download URL: evariste_core-0.3.0-py3-none-any.whl
- Upload date:
- Size: 83.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97ec9518f0e4846bb1423ddff32fba4eab74f6c1b1ec597f8abfb8f286ac9825
|
|
| MD5 |
b2d70258fc364777a9ce219f1d1cb6ff
|
|
| BLAKE2b-256 |
54ae4f82a53df36c0991d436a0caf27b00d22b2d09b8714921e8b38b6882a1c8
|