Skip to main content

Generate an OpenAPI specification from a Python class

PyOpenAPI produces an OpenAPI specification in JSON, YAML or HTML format with endpoint definitions extracted from member functions of a strongly-typed Python class.

Features

  • supports standard and asynchronous functions (async def)
  • maps function name prefixes such as get_ or create_ to HTTP GET, POST, PUT, DELETE, PATCH
  • handles both simple and composite types (int, str, Enum, @dataclass)
  • handles generic types (list[T], dict[K, V], T | None, T1 | T2 | T3)
  • maps Python positional-only and keyword-only arguments (of simple types) to path and query parameters, respectively
  • maps composite types to HTTP request body
  • supports user-defined routes, request and response samples with decorator @webmethod
  • extracts description text from class and function doc-strings (__doc__)
  • recognizes parameter description text given in reStructuredText doc-string format (:param name: ...)
  • converts exceptions declared in doc-strings into HTTP 4xx and 5xx responses (e.g. :raises TypeError:)
  • recursively converts composite types into JSON schemas
  • groups frequently used composite types into a separate section and re-uses them with $ref
  • displays generated OpenAPI specification in HTML with ReDoc

Live examples

User guide

The specification object

In order to generate an OpenAPI specification document, you should first construct a Specification object, which encapsulates the formal definition:

specification = Specification(
    MyEndpoint,
    Options(
        server=Server(url="http://example.com/api"),
        info=Info(
            title="Example specification",
            version="1.0",
            description=description,
        ),
        default_security_scheme=SecuritySchemeHTTP(
            "Authenticates a request by verifying a JWT (JSON Web Token) passed in the `Authorization` HTTP header.",
            "bearer",
            "JWT",
        ),
        extra_types=[ExampleType, UnreferencedType],
        error_wrapper=True,
    ),
)

The first argument to Specification is a Python class (type) whose methods will be inspected and converted into OpenAPI endpoint operations. The second argument is additional options that fine-tune how the specification is generated.

Defining endpoint operations

Let's take a look at the definition of a simple endpoint called JobManagement:

class JobManagement:
    def create_job(self, items: list[URL]) -> uuid.UUID:
        ...

    def get_job(self, job_id: uuid.UUID, /, format: Format) -> Job:
        ...

    def remove_job(self, job_id: uuid.UUID, /) -> None:
        ...

    def update_job(self, job_id: uuid.UUID, /, job: Job) -> None:
        ...

The name of each method begins with a prefix such as create, get, remove or update, each of which maps to an HTTP verb, e.g. POST, GET, DELETE or PATCH. The rest of the function name serves as an identifier, e.g. job. The self argument to the function is ignored. Other arguments indicate what path and query parameter objects, and what HTTP request body the operation accepts.

Function signatures for operations

Function signatures for operations must have full type annotation, including parameter types and return type.

Python positional-only arguments map to path parameters. Python positional-or-keyword arguments map to query parameters if they are of a simple type (e.g. int or str). If a composite type (e.g. a class, a list or a union) occurs in the Python parameter list, it is treated as the definition of the HTTP request body. Only one composite type may appear in the parameter list. The return type of the function is treated as the HTTP response body. If the function returns None, it corresponds to an HTTP response with no payload (i.e. a Content-Length of 0).

The JSON schema for the HTTP request and response body is generated with the library json_strong_typing, and is automatically embedded in the OpenAPI specification document.

User-defined operation path

By default, the library constructs the operation path from the Python function name and positional-only parameters. However, it is possible to supply a custom path (route) using the @webmethod decorator:

@webmethod(
    route="/person/name/{family}/{given}",
)
def get_person_by_name(self, family: str, given: str, /) -> Person:
    ...

The custom path must have placeholders for all positional-only parameters in the function signature, and vice versa.

Documenting operations

Use Python ReST (ReStructured Text) doc-strings to attach documentation to operations:

def get_job(self, job_id: uuid.UUID, /, format: Format) -> Job:
    """
    Query status information about a job.

    :param job_id: Unique identifier for the job to query.
    :returns: Status information about the job.
    :raises NotFoundError: The job does not exist.
    :raises ValidationError: The input is malformed.
    """
    ...

Fields such as param and returns help document path and query parameters, HTTP request and response body. The field raises helps document error responses by identifying the exact return type when an error occurs. The Python type for returns and raises is translated to a JSON schema and embedded in the OpenAPI specification document.

Request and response examples

OpenAPI supports specifying examples for the HTTP request and response body of endpoint operations. This is supported via the @webmethod decorator:

    @webmethod(
        route="/member/name/{family}/{given}",
        response_examples=[
            Student("Szörnyeteg", "Lajos"),
            Student("Ló", "Szerafin"),
            Student("Bruckner", "Szigfrid"),
            Student("Nagy", "Zoárd"),
            Teacher("Mikka", "Makka", "Négyszögletű Kerek Erdő"),
            Teacher("Vacska", "Mati", "Négyszögletű Kerek Erdő"),
        ],
    )
    def get_member_by_name(self, family: str, given: str, /) -> Student | Teacher:
        ...

A response example may be an exception or error class (a type that derives from Exception). These are usually shown under an HTTP status code of 4xx or 5xx.

The Python objects in request_examples and response_examples are translated to JSON with the library json_strong_typing.

Mapping function name prefixes to HTTP verbs

The following table identifies which function name prefixes map to which HTTP verbs:

Prefix HTTP verb
create POST
delete REMOVE
do GET or POST
get GET
post POST
put POST
remove REMOVE
set PUT
update PATCH

If the function signature conflicts with the HTTP verb (e.g. a function name starts with get but has a composite type in the parameter list, which maps to a non-empty HTTP request body), the HTTP verb is automatically adjusted.

Associating HTTP status codes with response types

By default, the library associates success responses with HTTP status code 200, and error responses with HTTP status code 500. However, it is possible to associate any Python type with any HTTP status code:

specification = Specification(
    MyEndpoint,
    Options(
        server=Server(url="http://example.com/api"),
        info=Info(
            title="Example specification",
            version="1.0",
            description=description,
        ),
        success_responses={
            Student: HTTPStatus.CREATED,
            Teacher: HTTPStatus.ACCEPTED,
        },
        error_responses={
            AuthenticationError: HTTPStatus.UNAUTHORIZED,
            BadRequestError: 400,
            InternalServerError: 500,
            NotFoundError: HTTPStatus.NOT_FOUND,
            ValidationError: "400",
        },
        error_wrapper=True,
    ),
)

The arguments success_responses and error_responses take a dictionary that maps types to status codes. Status codes may be integers (e.g. 400), strings (e.g. "400" or "4xx") or HTTPStatus enumeration values. The string representation of the status code must be valid as per the OpenAPI specification.

Metadata

Release files for python-openapi 0.3.0

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

Source distribution (sdist)

Source distribution for python-openapi 0.3.0
File Size Uploaded
python_openapi-0.3.0.tar.gz 29.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for python-openapi 0.3.0
File Interpreter ABI Platform
python_openapi-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 53.9 kB

Release files / python_openapi-0.3.0.tar.gz

Download URL python_openapi-0.3.0.tar.gz
Size 29.0 kB
Tags Source
SHA-256 checksum
How to use checksums
fced975249ed987644678d4fae16f5ef5d4e9be69bdfba700696ceac5f529470
BLAKE2b-256 checksum
How to use checksums
cb0d5370735a73860b8bd3e08dec998c4f6d9acc8f8696150e69c33a3fb71379
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release files / python_openapi-0.3.0-py3-none-any.whl

Download URL python_openapi-0.3.0-py3-none-any.whl
Size 24.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
413461b4941f22ec7e47c6855609351851eb83f1a13202f1a3cf2692f0ea44c0
BLAKE2b-256 checksum
How to use checksums
a32a7db3ec6aa594bd13265173afe9eb55fa21c6a28f6778672d53c70307f20b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

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