Skip to main content

DefSpec

Python Check PyPI

Create the OpenAPI spec and document from dataclass, attrs, msgspec, etc.

Why not ...

This project is a legacy of a private initiative. During the development, I discovered that using msgspec could elegantly define and generate the API schema. The OpenAPI component can be utilized to generate the API documentation for various projects. As a result, I made the decision to extract it and transform it into a public project.

You can use this project as a low-level component or a drop-in module when you don't want to introduce too many other dependencies.

Installation

pip install defspec
# to enable the offline feature
pip install defspec[offline]

Examples

You can run the above examples and open the OpenAPI document in your browser:

Usage

from dataclasses import dataclass
from typing import List

from defspec import OpenAPI, OpenAPIComponent, SecuritySchemeHTTP


@dataclass
class User:
    name: str
    age: int


openapi = OpenAPI(
    components=OpenAPIComponent(
        security_schemes={"token": SecuritySchemeHTTP(scheme="bearer")}
    ),
    security=[{"token": []}],
)
openapi.register_route("/", method="get", summary="Hello World")
openapi.register_route(
    "/users", method="post", summary="Get all the user info", response_type=List[User]
)

# get the OpenAPI spec
print(openapi.to_dict())
# get the OpenAPI spec bytes
with open("openapi.json", "wb") as f:
    f.write(openapi.to_json())

# serve as a HTTP server
openapi.serve_as_http_daemon(port=8000, run_in_background=True)

OpenAPI compatibility

Starting with DefSpec 0.7, the default is OpenAPI 3.2.0. Both 3.2.x and 3.1.x are supported. To keep generating 3.1 documents for existing consumers:

openapi = OpenAPI(openapi="3.1.0")

The existing model, parameter, and security APIs work with both versions. OpenAPI 3.2 also accepts method="QUERY" with a request body; 3.1 rejects it. Construction and JSON decoding reject operations unsupported by the selected version, including query in 3.1. Operation keys in supplied paths must use lowercase names; register_route accepts methods in any letter case. Custom HTTP methods (additionalOperations), whole-query-string parameters, and streaming item schemas do not yet have dedicated generation APIs.

  • Models use components.schemas and #/components/schemas/... references. When migrating, update saved $defs references. The defs= constructor argument is removed; openapi.defs remains an alias for openapi.components.schemas.
  • Query, header, cookie, and path models expand into one parameter per encoded field name; generated msgspec tags are omitted. Wrap unions such as int | str in a model. Named scalars, such as int or UUID, use the type name as the parameter name. Defaults make non-path fields optional unless the schema requires them. Path fields must match the URL placeholders and cannot have defaults or default factories. TypedDict path keys must be required. Each placeholder must have a unique name.
  • Field constraints and descriptions are preserved; parameter schemas are copied independently. Model titles, descriptions, and forbid_unknown_fields are ignored during expansion. Constraints that cannot be expanded raise ValueError, including additionalProperties: false annotations that forbid declared fields.
  • Header names Authorization, Accept, and Content-Type are rejected regardless of case. Use security schemes and request/response content types instead.
  • request_type=None omits the body; response_type=None omits response content. Use type(None) for JSON null. Routes document a 200 response by default.
  • Omit security to inherit global security; use security=[] for public routes. OAuth flows omit absent fields and keep the required scopes map.
  • Default operation IDs include a stable path hash: _users_<hash>_get for GET /users. Set operation_id to choose your own name.
  • Invalid routes, equivalent path templates, duplicate operation IDs, and empty or conflicting schema names raise ValueError without changing the document. HTTP methods are case-insensitive. Use distinct model names and operation_id values to resolve conflicts.

Custom schema hooks follow msgspec's rules: return a schema dictionary or True for an unconstrained schema. The tests validate generated documents against both supported versions with openapi-spec-validator, including JSON round trips. Validate custom schemas and direct edits before use. Swagger UI, ReDoc, and Scalar are pinned to releases that render OpenAPI 3.2 documents, including QUERY operations. The offline renderer (offapi) pins the same versions. Third-party renderer and client generator compatibility depends on the upstream version. Select 3.1 when your consumer requires it.

Metadata

Release files for defspec 0.7.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 defspec 0.7.1
File Size Uploaded
defspec-0.7.1.tar.gz 36.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for defspec 0.7.1
File Interpreter ABI Platform
defspec-0.7.1-py3-none-any.whl Python 3 none any Details

Total release size: 55.8 kB

Release files / defspec-0.7.1.tar.gz

Download URL defspec-0.7.1.tar.gz
Size 36.0 kB
Tags Source
SHA-256 checksum
How to use checksums
2407875ead134f86c3d444df2e365a4d257337a133fc743bc921996653e4e563
BLAKE2b-256 checksum
How to use checksums
99eba3be19e0746a8b278fb683cb28830aab5d92017dbb97aaf0a4a8ee234753
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / defspec-0.7.1-py3-none-any.whl

Download URL defspec-0.7.1-py3-none-any.whl
Size 19.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5f6ad5afc8c41e4177fe1a50e38a8a66b1dc5e8cbf8431d88a123dc0f998c44a
BLAKE2b-256 checksum
How to use checksums
c9c4af3772be89e132f85cad292bd5660aebecbfcbe801d48f7b8999ae797af8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.7.1 This release

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

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