Skip to main content

fastapi-depgraph

fastapi-depgraph logo

PyPI version Supported Python versions CI status License

Introspection of a FastAPI app's Depends() tree: which dependencies each route resolves, which are shared across routes, which aren't cached, and export to ASCII or Mermaid.

Reads route.dependant — the structure FastAPI already builds internally when each route is registered — instead of reparsing signatures by hand.

Install

pip install fastapi-depgraph

Usage — CLI

depgraph show myapp.main:app
depgraph show myapp.main:app --shared --uncached
depgraph export myapp.main:app --format mermaid > graph.mmd

Usage — API

from fastapi_depgraph import inspect_app

report = inspect_app(app)

report.shared_dependencies()    # {callable: ["/route1", "/route2"]}
report.uncached_dependencies()  # ["module.get_request_id", ...]

for route in report.routes:
    print(route.path, route.root.name)

Example

$ depgraph show examples/basic_app.py:app --shared --uncached
GET /users/me
  basic_app.read_current_user (sync)
  └── basic_app.get_current_user (sync)
      ├── basic_app.get_db (async)
      │   └── basic_app.get_settings (sync)
      └── basic_app.get_request_id (sync) [no-cache]
...

Dependencies shared across routes:
  get_current_user: /orders, /orders/{order_id}, /users/me
  get_db: /orders, /orders/{order_id}, /users, /users/me
  get_settings: /orders, /orders/{order_id}, /users, /users/me
  get_request_id: /orders, /orders/{order_id}, /users/me
  get_orders_service: /orders, /orders/{order_id}

Dependencies with use_cache=False:
  basic_app.get_request_id

At a glance: get_db and get_settings get resolved on four different routes — if one gets expensive, that's where to look first. And get_request_id is intentionally marked as uncached (it comes from a per-request header), but in a real case that's the flag that warns you about a use_cache=False someone forgot or added by mistake.

What patterns it handles

Tested, with regression coverage, against the real patterns that broke early versions of this package:

  • APIRouter + include_router(), at any level of nesting and with any prefix (/api/v1/items correctly accumulates in the path).
  • Dependencies declared on include_router(router, dependencies=[...]) or FastAPI(dependencies=[...]) — an auth guard for an entire router shows up in the tree of every route it covers.
  • Apps mounted with app.mount(sub_app) (path caveat below).
  • Dependencies parametrized by a factory (def make_limiter(n): def check(): ...; return check) or functools.partial(fn, role="admin"): two instances with different captured/bound values show up as distinct nodes (check{n=5} vs. check{n=10}, require_role(role='admin') vs. require_role(role='editor')) instead of collapsing into one name.
  • Depends(SomeClass()) (instance) and Depends(SomeClass) (the class itself) — both "class as a dependency" patterns documented by FastAPI.

Known limitations

  • Apps mounted with app.mount(sub_app) are walked (Starlette exposes the sub-app's routes through Mount.routes), but the reported path is relative to the sub-app, without the mount's prefix.
  • Only HTTP routes are inspected; WebSocket routes aren't part of the tree (intentionally — Depends() on WebSocket doesn't have per-request caching or the same resolution model, see DESIGN.md §2).
  • If two different instances of the same class are used as dependencies on different routes, shared_dependencies() correctly treats them as not shared (it compares by identity), but they're shown with the same label in the tree/Mermaid unless the class itself is a closure — there's no generic way to give an arbitrary instance a readable name.
  • app.dependency_overrides (the standard mechanism for injecting test doubles) isn't reflected: the tree shows the dependency as declared in the code, not the one that would actually run under an active override — it's a static graph, see DESIGN.md §2.
  • The name of a parametrized dependency includes the repr() of its captured/bound values — if those values are secrets (tokens, API keys passed as defaults), they'll show up in depgraph show/export output. Don't paste that output into public channels without checking what parametrized dependencies your app has.
  • Merging the path/dependencies for included routers (include_router) uses, when available, an internal method with no public contract that Starlette exposes to resolve routes at request time; if that shape changes in a future version, the package silently degrades to the previous behavior (no accumulated prefix or inclusion dependencies) instead of failing — the CI matrix runs against several FastAPI versions to catch it early if that happens.

Why

FastAPI's DI system is implicit: nested Depends() resolve with no native way to see the tree. Two questions this package answers that today have no direct way to answer:

  • Which expensive dependencies are being recomputed instead of cached (use_cache=False)?
  • Which routes share an expensive dependency, so you know where to optimize once instead of in five different places?

See DESIGN.md for the rest of the scope and design decisions.

Download files

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

Source Distribution

fastapi_depgraph-0.1.0.tar.gz (812.5 kB view details)

Uploaded Source

Built Distribution

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

fastapi_depgraph-0.1.0-py3-none-any.whl (11.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for fastapi_depgraph-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5f593e58b0fc33489d1461ff4ccf93b77ff7dbea6876acb04b45c44adbb9dc99
MD5 cc7377700b6a409a9f8b644d59f2d68a
BLAKE2b-256 292eaef328c1d0f0bb4be181664d5d78371c1137b59262db8b5d150a49037f76

See more details on using hashes here.

Provenance

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

Publisher: release.yml on jmiguelmangas/fastapi-depgraph

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

File details

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

File metadata

File hashes

Hashes for fastapi_depgraph-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7f83b2221e4affb0d174f9efc5a3cf276ba2f26fb82af6731f1f63c3a4ea1b54
MD5 23352c04c4e23f4515fe9c1480e67255
BLAKE2b-256 4d98a5d7950586de49ba07c41c29b1f3af83ec73425b8821bc1f49d9115fe8f8

See more details on using hashes here.

Provenance

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

Publisher: release.yml on jmiguelmangas/fastapi-depgraph

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

Release history Release notifications | RSS feed

0.1.1

2 files

This release

0.1.0 This release

2 files

Supported by

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