Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ nav:
- Resource Management: resources.md
- Interfaces: interfaces.md
- Function Injection: function_injection.md
- Interactive Graph: interactive_graph.md
- Advanced Patterns:
- Reusable Bundles: reusable_bundles.md
- Conditional Registration: conditional_registration.md
Expand All @@ -31,6 +32,7 @@ nav:
- Web Frameworks:
- Django:
- Django Integration: integrations/django/index.md
- Interactive Graph: integrations/django/interactive_graph.md
- Setup and Installation: integrations/django/setup.md
- Inject in Views: integrations/django/view_injection.md
- Request-Time Injection: integrations/django/request_time_injection.md
Expand Down
Binary file added docs/pages/img/pet_store_demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions docs/pages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Type-driven dependency injection for Python. Wireup is battle-tested in production, thread-safe, no-GIL (PEP 703) ready,
and designed to fail fast: **if the container starts, it works**.


![Scoped Performance](img/benchmarks_scoped_light.svg#only-light)
![Scoped Performance](img/benchmarks_scoped_dark.svg#only-dark)

Expand All @@ -12,6 +13,20 @@ and designed to fail fast: **if the container starts, it works**.
</p>
<p align="center"><i></i></p>

---

!!! interactive-graph "Interactive Graph"

Turn your container into an interactive dependency graph. Explore routes, functions, services, factories,
configuration, and scopes in a live page with search, grouping, and dependency tracing.

Learn how it works and explore it on an demo pet store app:

[Documentation](interactive_graph.md){ .md-button target="_blank" }
[:octicons-arrow-right-24: Live Demo](wireup_graph/pet_store.html){ .md-button .md-button--primary target="_blank" }

---

<div class="grid cards annotate index-cards" markdown>

- :material-shield-check:{ .lg .middle } __Correct by Default__
Expand Down
11 changes: 11 additions & 0 deletions docs/pages/integrations/django/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ Wireup integrates with Django at both request scope and application scope. Use `
`@inject_app` for non-request entry points, while keeping services as ordinary Python classes that are easy to test and
reuse.

!!! interactive-graph "Interactive Graph"

Turn your container into an interactive dependency graph. Explore routes, functions, services, factories,
configuration, and scopes in a live page with search, grouping, and dependency tracing.

Django can expose it with a small explicit view, and the same renderer is available for other apps too.

[Documentation](interactive_graph.md){ .md-button }
[:octicons-arrow-right-24: Live Demo](../../wireup_graph/pet_store.html){ .md-button .md-button--primary target="_blank" }

## Quick Start

This is the shortest path to a working endpoint with explicit injection.
Expand Down Expand Up @@ -119,6 +129,7 @@ See [What Wireup Validates](../../what_wireup_validates.md) for the full rules.
## Detailed Guides

- [Django Setup and Installation](setup.md): installation, middleware placement, and settings/config integration.
- [Interactive Graph](interactive_graph.md): expose the graph page in Django and gate it by environment.
- [Inject in Views](view_injection.md): core Django, DRF, Ninja, forms, and request-scoped patterns.
- [Request-Time Injection](request_time_injection.md): reusable decorators, middleware entry points, and direct container access.
- [App-Level Injection](app_injection.md): management commands, Django 6 background tasks, signals, checks, and scripts with `@inject_app`.
Expand Down
70 changes: 70 additions & 0 deletions docs/pages/integrations/django/interactive_graph.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
description: Wireup interactive dependency graph for Django: expose the graph page, understand what it shows, and gate it by environment.
---

## Enable The Interactive Graph

Create a small view that renders the graph page from the application container:

```python title="mysite/wireup_graph.py"
from django.http import HttpRequest, HttpResponse
from wireup.integration.django import get_app_container
from wireup.renderer.full_page import GraphEndpointOptions, render_graph_page


def wireup_graph(_request: HttpRequest) -> HttpResponse:
return HttpResponse(
render_graph_page(
get_app_container(),
title="My Django App - Wireup Graph",
options=GraphEndpointOptions(base_module="mysite"),
),
content_type="text/html",
)
```

Then mount it in your URLconf:

```python title="mysite/urls.py"
from django.conf import settings
from django.urls import path

from mysite.wireup_graph import wireup_graph

urlpatterns = [
# ...your existing routes...
]

if settings.DEBUG:
urlpatterns.append(path("_wireup", wireup_graph))
```

Then open `http://127.0.0.1:8000/_wireup`.

## What It Shows

The graph can include:

- services and factories
- configuration nodes
- singleton, scoped, and transient lifetimes
- discovered Django consumers that the graph can infer from the loaded app state

## Environment Gating

Because the graph exposes internal implementation details, it is best treated as a development tool.

A typical pattern is to mount the route only in local or non-production environments:

```python title="mysite/urls.py"
if settings.DEBUG:
urlpatterns.append(path("_wireup", wireup_graph))
```

If you need stricter control, omit the route entirely in production or protect it like any other internal debug page.

## Related

- [Django Integration](index.md)
- [General Interactive Graph Docs](../../interactive_graph.md)
- [Django Request-Time Injection](request_time_injection.md)
20 changes: 16 additions & 4 deletions docs/pages/integrations/fastapi/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@ description: FastAPI dependency injection with Wireup: type-safe DI for routes,

</div>

!!! tip "Migrating from FastAPI Depends?"
!!! interactive-graph "Interactive Graph"

Evaluating Wireup for your FastAPI project? Check out the migration page which includes common pain points with FastAPI Depends and how to solve them with Wireup as well
as a low-friction migration path:
Turn your container into an interactive dependency graph. Explore routes, functions, services, factories,
configuration, and scopes in a live page with search, grouping, and dependency tracing.

[Migrate from FastAPI Depends to Wireup](../../migrate_to_wireup/fastapi_depends.md).

Learn how it works and explore it on an demo pet store app:

[Documentation](interactive_graph.md){ .md-button target="_blank" }
[:octicons-arrow-right-24: Live Demo](../../wireup_graph/pet_store.html){ .md-button .md-button--primary target="_blank" }

## Quick Start

Expand Down Expand Up @@ -103,6 +107,14 @@ See [What Wireup Validates](../../what_wireup_validates.md) for the full rules.
- [FastAPI Testing](testing.md): `TestClient` lifespan usage, overrides, and request-lifecycle tests.
- [Troubleshooting](troubleshooting.md): common setup/runtime errors and fast fixes.

!!! tip "Migrating from FastAPI Depends?"

Evaluating Wireup for your FastAPI project? Check out the migration page which includes common pain points with FastAPI Depends and how to solve them with Wireup as well
as a low-friction migration path:

[Migrate from FastAPI Depends to Wireup](../../migrate_to_wireup/fastapi_depends.md).


## API Reference

- [fastapi_integration](../../class/fastapi_integration.md)
22 changes: 22 additions & 0 deletions docs/pages/integrations/flask/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ Dependency injection for Flask is available in the `wireup.integration.flask` mo

</div>

!!! interactive-graph "Interactive Graph"

Turn your container into an interactive dependency graph. Explore routes, functions, services, factories,
configuration, and scopes in a live page with search, grouping, and dependency tracing.

Learn how it works and explore it on an demo pet store app:

[Documentation](interactive_graph.md){ .md-button target="_blank" }
[:octicons-arrow-right-24: Live Demo](../../wireup_graph/pet_store.html){ .md-button .md-button--primary target="_blank" }

### Initialize the integration

First, [create a sync container](../../container.md) with your dependencies:
Expand Down Expand Up @@ -46,6 +56,18 @@ Then initialize the integration by calling `wireup.integration.flask.setup` afte
wireup.integration.flask.setup(container, app)
```

To expose the interactive dependency graph page at `/_wireup`, enable the graph endpoint during setup:

```python
from wireup.integration.flask import GraphEndpointOptions

wireup.integration.flask.setup(
container,
app,
add_graph_endpoint=True,
)
```

### Inject in Flask Views

To inject dependencies, add the type to the view's signature and annotate with `Injected[T]` or
Expand Down
93 changes: 93 additions & 0 deletions docs/pages/interactive_graph.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Interactive Graph

!!! interactive-graph "Interactive Graph"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edge-direction convention should be documented. The renderer emits source = provider, target = consumer, which is the opposite of UML's dependency-arrow convention (where the arrow points from the dependent to the depended-upon). Tools and readers built on the graph JSON will silently make the wrong inference without this.

Fix: Consider reversing the direction to match UML, or adding a note to this page clarifying the current convention.


Turn your container into an interactive dependency graph. Explore routes, functions, services, factories,
configuration, and scopes in a live page with search, grouping, and dependency tracing.

Learn how it works and explore it on an demo pet store app:

[:octicons-arrow-right-24: Live Demo](wireup_graph/pet_store.html){ .md-button .md-button--primary target="_blank" }

Wireup can render your dependency graph as an interactive page, including:

- routes and injected functions for selected frameworks
- services and factories
- configuration nodes
- singleton, scoped, and transient lifetimes

This is one of the fastest ways to understand how a real application is wired together without relying on a static dump
or a handwritten diagram.

## Preview

![Wireup interactive dependency graph demo](img/pet_store_demo.gif)


## Automatic with FastAPI and Flask

FastAPI and Flask can expose the graph page automatically at `/_wireup`.

### FastAPI

```python
from wireup.integration.fastapi import GraphEndpointOptions
import wireup.integration.fastapi

wireup.integration.fastapi.setup(
container,
app,
add_graph_endpoint=True,
)
```

### Flask

```python
from wireup.integration.flask import GraphEndpointOptions
import wireup.integration.flask

wireup.integration.flask.setup(
container,
app,
add_graph_endpoint=True,
)
```

## Use in other frameworks

If your framework does not have automatic graph-page setup, you can still generate the graph yourself from Python.

### 1. Build graph data

```python
from wireup.renderer.core import GraphOptions, to_graph_data

graph_data = to_graph_data(
container, # or get_app_container() if the integration provides it
options=GraphOptions(base_module="myapp"),
)
```

### 2. Render it as HTML

```python
from wireup.renderer.full_page import full_page_renderer

html = full_page_renderer(graph_data, title="My App - Wireup Graph")
```

### 3. Return it from a route

```python
@app.get("/_wireup")
def wireup_graph():
graph_data = to_graph_data(container, options=GraphOptions(base_module="myapp"))
html = full_page_renderer(graph_data, title="My App - Wireup Graph")

return HTMLResponse(html)
```


!!! tip
Make sure to permission this endpoint appropriately in production since it exposes internal implementation details. You can disable it by omitting `add_graph_endpoint=True` or by not registering the route at all.
1 change: 0 additions & 1 deletion docs/pages/packaging_injectables.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ class Cache(Protocol): ...
@injectable(as_type=Cache)
class RedisCache: ...


@injectable(as_type=Cache)
class MemcachedCache: ...

Expand Down
23 changes: 22 additions & 1 deletion docs/pages/stylesheets/extra.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,25 @@ body[data-md-color-scheme="slate"] .grid.cards>ul>li {

.color-django {
color: #0C4B33 !important;
}
}

:root {
--md-admonition-icon--interactive-graph: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path d="M42.3 24l3.4-5.1a2 2 0 0 0 .2-1.7 1.8 1.8 0 0 0-1.2-1.2l-5.9-2.4-.5-5.9a2.1 2.1 0 0 0-.7-1.5 2 2 0 0 0-1.7-.3l-6.3 1.3-4.1-4.6a2.2 2.2 0 0 0-3 0l-4.1 4.6-6.3-1.3a2 2 0 0 0-1.7.3 2.1 2.1 0 0 0-.7 1.5l-.5 5.9L3.3 16a1.8 1.8 0 0 0-1.2 1.2 2 2 0 0 0 .2 1.7L5.7 24l-3.4 5.1a2 2 0 0 0 1 2.9l5.9 2.4.5 5.9a2.1 2.1 0 0 0 .7 1.5 2 2 0 0 0 1.7.3l6.3-1.3 4.1 4.5a2 2 0 0 0 3 0l4.1-4.5 6.3 1.3a2 2 0 0 0 1.7-.3 2.1 2.1 0 0 0 .7-1.5l.5-5.9 5.9-2.4a2 2 0 0 0 1-2.9ZM18 31.1l-4.2-3.2-1.1-.9h-.1l.6 1.4 1.7 4-2.1.8-3.5-8.6 2.1-.8 4.3 3.2 1.1.9h0a11.8 11.8 0 0 0-.6-1.3l-1.6-4.1 2.1-.9 3.5 8.6Zm3.3-1.3-3.5-8.7 6.6-2.6.7 1.8L20.7 22l.6 1.6L25.1 22l.7 1.7L22 25.2l.7 1.9 4.5-1.8.7 1.8Zm13.9-5.7-2.6-3.7-.9-1.5h-.1a14.7 14.7 0 0 1 .4 1.7l.8 4.5-2.1.9-5.9-7.7 2.2-.9 2.3 3.3 1.3 2h0a22.4 22.4 0 0 1-.4-2.3l-.7-4 2-.8L33.8 19 35 20.9h0s-.2-1.4-.4-2.4L34 14.6l2.1-.9 1.2 9.6Z"/></svg>');
}

.md-typeset .admonition.interactive-graph,
.md-typeset details.interactive-graph {
border-color: #007acc;
}

.md-typeset .interactive-graph > .admonition-title,
.md-typeset .interactive-graph > summary {
background-color: rgba(0, 122, 204, 0.12);
}

.md-typeset .interactive-graph > .admonition-title::before,
.md-typeset .interactive-graph > summary::before {
background-color: #007acc;
-webkit-mask-image: var(--md-admonition-icon--interactive-graph);
mask-image: var(--md-admonition-icon--interactive-graph);
}
Loading
Loading