Skip to main content

Prauga FlexDoc Python adapter

prauga-flexdoc 0.8.0 packages one framework-neutral Python host plus ASGI and WSGI transports. The wheel is self-contained, includes the canonical renderer assets, and keeps FastAPI, Flask, and Django optional.

FastAPI / ASGI

from fastapi import FastAPI
from prauga_flexdoc import setup_fastapi_flexdoc

app = FastAPI(docs_url=None, redoc_url=None)
setup_fastapi_flexdoc(app, '/docs', title='My API')

FastAPI can opt into FlexDoc 3.0 Runtime Intelligence:

setup_fastapi_flexdoc(
    app,
    '/docs',
    title='My API',
    runtime_intelligence=True,
)

When enabled, the helper inspects the live FastAPI/Starlette route tree and serves a no-store snapshot from /docs/__flexdoc/runtime. It compares runtime route presence with app.openapi(), reports Python/FastAPI runtime metadata and request-derived server origin, normalizes Starlette path converters, and marks opaque mounts partial rather than inventing routes. Runtime Intelligence is FastAPI-only in this adapter release; generic ASGI, Flask, Django, and WSGI hosts do not advertise it yet.

Runtime snapshots may reveal endpoints intentionally omitted from OpenAPI. The Python adapter currently relies on application middleware or upstream access control rather than a FlexDoc-native docs-auth option, so protect the FlexDoc docs subtree before enabling Runtime Intelligence on non-private documentation.

Native API-host execution (3.3)

FastAPI can also opt into the existing FlexDoc host-execution protocol:

setup_fastapi_flexdoc(
    app,
    '/docs',
    title='My API',
    try_it_host_execution=True,
    try_it_host_execution_allowed_origins=[
        'https://api.example.internal',
    ],
)

When enabled, the ASGI transport owns POST /docs/__flexdoc/execute and the renderer advertises hostExecution.available: true. The allowlist is server-side and accepts exact HTTP(S) origins only; paths, queries, credentials, and wildcards are rejected. The execute route requires X-FlexDoc-Execute: 1, strips unsafe browser-controlled transport headers, revalidates same-origin redirects, blocks link-local/cloud-metadata targets and dangerous DNS answers, bounds request/response sizes, and consumes the same JSON/multipart envelope used by the Node host and FlexDoc Runner.

This first Python slice intentionally advertises an empty host-only capability list. Basic, Bearer, OAuth2 bearer-token, and header/query API-key request auth are supported because they are part of the canonical request draft; session cookie jars, client certificates, Digest, Hawk, NTLM/Negotiate, OAuth 1.0, and AWS Signature V4 remain unavailable until implemented natively.

For every outbound request and redirect hop, the Python standard-library transport resolves the original hostname, rejects link-local/cloud-metadata answers, and then connects only to that validated address set. The request still retains the original hostname for the HTTP Host header and, for HTTPS, TLS SNI and certificate verification. The executor uses http.client directly and does not route through environment/system HTTP proxies. DNS lookup itself uses the platform's synchronous resolver; the execution deadline is checked immediately after resolution and applies to connection, response headers, and the complete response body, but Python cannot forcibly interrupt a resolver call that is already blocked inside the operating system. Keep exact-origin allowlists narrow and use network egress policy as an additional defense in depth where appropriate.

Flask, Django, and generic WSGI hosts serve the same execute route from 0.8.0. The executor is framework-neutral and synchronous, so a WSGI worker runs it directly rather than dispatching to a thread; see the sections below for the per-framework opt-in and the CSRF requirements that come with it.

For a generic ASGI host that owns its execution policy explicitly:

from prauga_flexdoc import FlexDocASGI, FlexDocConfig, FlexDocHostExecution

executor = FlexDocHostExecution(['https://api.example.internal'])
docs = FlexDocASGI(
    FlexDocConfig(
        path='/docs',
        spec_url='/openapi.json',
        title='My API',
        try_it_host_execution=True,
    ),
    host_execution=executor,
)
app.mount('/docs', docs)

For a generic ASGI host without native execution:

from prauga_flexdoc import FlexDocASGI, FlexDocConfig

app.mount('/docs', FlexDocASGI(
    FlexDocConfig(path='/docs', spec_url='/openapi.json', title='My API')
))

FlexDocConfig and the FastAPI/Flask/Django helpers also accept expand, try_it_default_server, try_it_credentials, and try_it_api_client_persistence_key; the persistence key may be a string or False, and unset values are omitted from renderer options.

Flask / WSGI

from flask import Flask
from prauga_flexdoc import setup_flask_flexdoc

app = Flask(__name__)
setup_flask_flexdoc(app, '/docs', spec_url='/openapi.json', title='My API')

For another WSGI server or framework, use FlexDocWSGI(FlexDocConfig(...)) directly.

Native API-host execution (0.8.0)

setup_flask_flexdoc(
    app,
    '/docs',
    spec_url='/openapi.json',
    try_it_host_execution=True,
    try_it_host_execution_allowed_origins=[
        'https://api.example.internal',
    ],
)

This registers POST /docs/__flexdoc/execute and advertises hostExecution.available: true. The same server-side allowlist, header stripping, redirect revalidation, address validation, and size/deadline bounds apply as on ASGI, because both transports call the same executor.

Flask has no built-in CSRF protection. If the application authenticates with cookies, apply its CSRF model to this route and mount the docs subtree behind the same authentication boundary as other privileged developer surfaces — the X-FlexDoc-Execute: 1 marker is protocol friction, not authentication and not a CSRF token. When Flask-WTF's CSRFProtect is active, send the token in the configured header rather than as a form field: reading a form token consumes a multipart/form-data envelope before the execute view can parse it.

For a generic WSGI host that owns its execution policy explicitly:

from prauga_flexdoc import FlexDocConfig, FlexDocHostExecution, FlexDocWSGI

docs = FlexDocWSGI(
    FlexDocConfig(path='/docs', spec_url='/openapi.json', try_it_host_execution=True),
    host_execution=FlexDocHostExecution(['https://api.example.internal']),
)

The WSGI transport reads at most Content-Length bytes, because a WSGI server is only obliged to provide readable input up to that point and an unbounded read can block. A request with no Content-Length is answered 411 Length Required unless the server reports a terminated chunked stream via wsgi.input_terminated, and the shared 32 MiB execute ceiling applies to both paths.

Django

from django.urls import path
from prauga_flexdoc import django_urlpatterns

urlpatterns = [
    # your API/OpenAPI routes
    *django_urlpatterns('/docs', spec_url='/openapi.json', title='My API'),
]

Django ASGI applications can also mount/use FlexDocASGI; Django WSGI applications can use FlexDocWSGI. django_urlpatterns() is the first-class native URL-routing helper.

Native API-host execution (0.8.0)

urlpatterns = [
    *django_urlpatterns(
        '/docs',
        spec_url='/openapi.json',
        try_it_host_execution=True,
        try_it_host_execution_allowed_origins=['https://api.example.internal'],
    ),
]

The execute view is CSRF-enforced by default: it is an ordinary POST view, so CsrfViewMiddleware protects it and a request without a valid token is rejected with 403 before the view runs. Send the token in the CSRF header (X-CSRFToken unless CSRF_HEADER_NAME is customized) rather than as a form field, because the middleware's form fallback consumes a multipart body before the view can read it.

A deployment whose authentication is not cookie-based can opt out explicitly:

django_urlpatterns(
    '/docs',
    try_it_host_execution=True,
    try_it_host_execution_allowed_origins=['https://api.example.internal'],
    try_it_host_execution_csrf_exempt=True,
)

There is no implicit exemption and no way to reach one by accident: the argument must be passed, it is rejected unless host execution is also enabled, and omitting it leaves Django's normal protection in place. Choose it only when a CSRF token is genuinely inapplicable — for example bearer-token or mTLS authentication — never as a way to make a cookie-authenticated deployment stop returning 403.

Architecture

FlexDocHost synchronously owns route matching, the HTML bootstrap, renderer fingerprinting, cache policy, and packaged JS/CSS. FlexDocASGI translates that neutral response to ASGI and can expose a framework-supplied live runtime snapshot or a real native execute route when one is explicitly attached. FlexDocWSGI translates that same response and, when an executor is explicitly attached, owns the native execute route. Framework helpers do not fork renderer behavior.

Pass assets_dir= to FlexDocHost, FlexDocASGI, or FlexDocWSGI only when intentionally overriding the bundled renderer assets during development.

Release files for prauga-flexdoc 0.8.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for prauga-flexdoc 0.8.1
File Size Uploaded
prauga_flexdoc-0.8.1.tar.gz 308.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for prauga-flexdoc 0.8.1
File Interpreter ABI Platform
prauga_flexdoc-0.8.1-py3-none-any.whl Python 3 none any Details

Total release size: 608.1 kB

Release files / prauga_flexdoc-0.8.1.tar.gz

Download URL prauga_flexdoc-0.8.1.tar.gz
Size 308.0 kB
Tags Source
SHA-256 checksum
How to use checksums
8b4fd62e46fe2a5a93f19d67cd85527c1f166ad007ee6c51b08438e1696e3863
BLAKE2b-256 checksum
How to use checksums
dd626d164eb7f885e9b0cf66bef36da61662ddd85ae8b85c098bc4ad1078fdba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / prauga_flexdoc-0.8.1-py3-none-any.whl

Download URL prauga_flexdoc-0.8.1-py3-none-any.whl
Size 300.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
04c0f255bb9c78f066e5d6b80d0986bd56d1348920a614a72561ba0252c2f696
BLAKE2b-256 checksum
How to use checksums
0db1752ee1a741452e8c470e093c529e6d02611b175c8d24893900d2afc10af5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release history Release notifications | RSS feed

0.9.0

2 release files

This release

0.8.1 This release

2 release files

0.8.0

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page