Configuration

Once you have successfully installed the openapi_builder package, it’s time to properly configure it such that it suits your needs. The configuration consist of the following two steps:

  1. Configuring the extension

  2. Adding resources

In case you are using blueprints in your application, we recommend you to read the Resource defaults (blueprints) section. If you are using custom marshmallow attributes, then we recommend you to read the Processing resources section.

Configuring the extension

The extension can be added to the Flask app using the following snippet.

from flask import Flask
from openapi_builder import OpenApiDocumentation

app = Flask(__name__)

documentation = OpenApiDocumentation(app=app)

It is also possible to bind the app in a later stage. This can be achieved using the following snippet.

from flask import Flask
from openapi_builder import OpenApiDocumentation

documentation = OpenApiDocumentation()

app = Flask(__name__)
documentation.init_app(app)

The following configuration options are applicable for passing to OpenApiDocumentation.

Argument

Type

Default value

Explanation

app

Optional[Flask]

None

The Flask application for iterating the endpoints to find out the documentation. It not passed directly, it must be passed via the init_app function.

title

str

"Open API REST documentation"

The title of the API.

version

str

"1.0.0"

The version of the OpenAPI document (which is distinct from the OpenAPI Specification version or the API implementation version).

options

Optional[DocumentationOptions]

None

Additional optional documentation options that are global for the entire app. If not specified, a new DocumentationOptions() will be created and used. For all possible values, see the Documentation options section.

Documentation options

The following options are applicable for passing to DocumentationOptions. This class can be imported using the following line:

from openapi_builder import DocumentationOptions

Argument

Type

Default value

Explanation

include_head_response

bool

True

Whether the HEAD operation is included in the documentation. By default, a Flask endpoint automatically exposes the HEAD operation. Since this is often not very useful, it is advised to remove it from the documentation.

include_options_response

bool

True

Whether the OPTIONS operation is included in the documentation. By default, a Flask endpoint automatically exposes the OPTIONS operation. Since this is often not very useful, it is advised to remove it from the documentation.

server_url

str

"/"

A URL to the target host. This URL supports Server Variables and MAY be relative, to indicate that the host location is relative to the location where the OpenAPI document is being served. Variable substitutions will be made when a variable is named in {brackets}.

include_marshmallow_converters

bool

True

Whether default marshmallow converters are included in the OpenAPIBuilder. In case a different serialization library than marshmallow is used, this value must be set to False.

include_halogen_converters

bool

False

Whether default halogen converters are included in the OpenAPIBuilder. In case a different serialization library than halogen is used, this value must be set to False.

include_documentation_blueprint

bool

True

Whether a documentation blueprint is exposed in the Flask application. This blueprint contains two endpoints. One for exposing the documentation UI, and one for exposing the documentation configuration (data collected by inspecting all endpoints). If a custom documentation UI is used, the value must be set to False.

strict_mode

DocumentationOptions.StrictMode

DocumentationOptions.StrictMode.SHOW_WARNINGS

Whether something unforeseen happened, should the extension crash (preferred in testing), using DocumentationOptions.StrictMode.FAIL_ON_ERROR or only print out warnings, using DocumentationOptions.StrictMode.SHOW_WARNINGS.

request_content_type

str

"application/json"

The content type used for requests throughout the entire application.

response_content_type

str

"application/json"

The content type used for responses throughout the entire application.

schema_converter_classes

List[Type[SchemaConverter]]

[]

See Schema converters for more info about this option.

defaults_converter_classes

List[Type[DefaultsConverter]]

[]

See Defaults converters for more info about this option.

parameter_converter_classes

List[Type[ParameterConverter]]

[]

See Parameter converters for more info about this option.

Adding resources

Resources can be exposed by adding the add_documentation decorator to the corresponding endpoint. The following options are applicable for passing to the function. This decorator can be imported using the following line:

from openapi_builder import add_documentation

Argument

Type

Default value

Explanation

responses

Optional[Dict[Union[HTTPStatus, int], Any]]

None

A dictionary from HTTPStatus (passing the status code as an int is also supported) to the class that is serialized. A converter must be registered in the OpenAPIBuilder for all values of the dictionary, including the attributes of the schemas that it serializes. Otherwise a MissingConverter exception is raised. An example of this argument is: {HTTPStatus.OK: UserSchema(many=True), HTTPStatus.NOT_FOUND: ErrorSchema()}

input_schema

Optional[Any]

None

This argument is similar to the responses, except that this class/value is used for deserializing data as the input of the endpoint. A converter must be registered in the OpenAPIBuilder for the specified value, including the attributes of the schemas that it deserializes. Otherwise a MissingConverter exception is raised.

parameters

Optional[List[Parameter]]

None

A list of parameters that the endpoint uses. Parameters can be query-arguments, header-values, path-values or cookies. See the parameter documentation for more info about the Parameter. This class can be imported using: from openapi_builder.specification import Parameter.

summary

Optional[str]

None

A short summary of what the operation does.

description

Optional[str]

None

A verbose explanation of the operation behavior. CommonMark syntax MAY be used for rich text representation.

tags

Optional[List[str]]

None

Optional list of strings that represent the endpoint. A typical value for this argument is the name of the resource where this endpoint belongs to. Tags are also used by the documentation UI to group related endpoints (with the same tags) together.

Processing resources

An important feature that the openapi_builder offers it to ability to process custom attributes for your schema. Custom attributes can be processed by custom converters. There are three types of custom converters:

Schema converters

Schema converters can be used to convert custom fields in your schema to SchemaObjects. Suppose you have the following custom field (taken from the Marshmallow doc):

from marshmallow import fields, Schema, ValidationError


class PinCode(fields.Field):
    """Field that serializes to a string of numbers and deserializes
    to a list of numbers.
    """

    def _serialize(self, value, attr, obj, **kwargs):
        if value is None:
            return ""
        return "".join(str(d) for d in value)

    def _deserialize(self, value, attr, data, **kwargs):
        try:
            return [int(c) for c in value]
        except ValueError as error:
            raise ValidationError("Pin codes must contain only digits.") from error


class UserSchema(Schema):
    name = fields.String()
    email = fields.String()
    created_at = fields.DateTime()
    pin_code = PinCode()

When OpenAPIBuilder is trying to generate the documentation for your UserSchema-class, it doesn’t know how to generate the documentation for the PinCode class. In order to configure a schema converter for the OpenAPIBuilder, you’ll need to create a custom converter class:

from openapi_builder.converters.schema.base import SchemaConverter
from openapi_builder.specification import Schema


class PinCodeConverter(SchemaConverter):
    converts_class = PinCode

    def convert(self, value, name) -> Schema:
        return Schema(type="int", format="pincode", example=1234)

This PinCodeConverter can be passed to the OpenAPIBuilder via the DocumentationOptions:

from flask import Flask
from openapi_builder import OpenApiDocumentation, DocumentationOptions

app = Flask(__name__)

documentation = OpenApiDocumentation(
    app=app,
    options=DocumentationOptions(
        schema_converter_classes=[PinCodeConverter],
    ),
)

Note that the class should be passed, and not an instance.

Defaults converters

Suppose we have the following marshmallow schema:

from datetime import datetime

from marshmallow import fields, Schema


class RegisterSchema(Schema):
    name = fields.String()
    email = fields.String()
    created_at = fields.DateTime(dump_default=lambda: datetime.now())

This would be problematic for the OpenAPIBuilder, since datetime is not JSON-serializable. As a consequence, the documentation can’t be generated for this type.

By using a defaults converter, this issue can be overcome. A defaults converter for a datetime might look like this:

from datetime import datetime

from marshmallow import fields
from openapi_builder.converters.defaults.base import DefaultsConverter


class DateTimeConverter(DefaultsConverter):
    converts_class = datetime

    def convert(self, value) -> Any:
        return fields.DateTime()._serialize(value=value, attr="", obj={})

Thus, we are using the power of Marshmallow to serialize the default datetime value. This DateTimeConverter can be passed to the OpenAPIBuilder via the DocumentationOptions:

from flask import Flask
from openapi_builder import OpenApiDocumentation, DocumentationOptions

app = Flask(__name__)

documentation = OpenApiDocumentation(
    app=app,
    options=DocumentationOptions(
        defaults_converter_classes=[DateTimeConverter],
    ),
)

Note that the class should be passed, and not an instance.

Parameter converters

Flask allows custom validators to be passed for an endpoint. This allows you to do the following:

from http import HTTPStatus

from flask import abort, Flask
from werkzeug.routing import BaseConverter


class UUIDValidator(BaseConverter):
    """Validates the `UID` bit of the route."""

    def to_python(self, value):
        """Check if the value is a valid `UID`."""
        try:
            return uuid.UUID(value).hex
        except ValueError:
            abort(HTTPStatus.BAD_REQUEST, f"Invalid UID {value}")


app = Flask(__name__)

app.url_map.converters["uid"] = validators.UUIDValidator


@app.get("/pet/<uid:uid>")
@serialization.serialize(schema.Pet)
def get(uid):
    ...

This would be problematic for the OpenAPIBuilder, since it doesn’t know how to generate documentation for uid: path params. As a consequence, the documentation can’t be generated for this type.

By using a parameter converter, this issue can be overcome. A parameter converter for a uid might look like this:

import uuid

from openapi_builder.converters.parameter.base import ParameterConverter
from openapi_builder.specification import Schema


class UUIDConverter(ParameterConverter):
    converts_class = UUIDValidator

    @property
    def schema(self) -> Schema:
        return Schema(type="string", format="hex", example=uuid.uuid4().hex)

This UUIDConverter can be passed to the OpenAPIBuilder via the DocumentationOptions:

from flask import Flask
from openapi_builder import OpenApiDocumentation, DocumentationOptions

app = Flask(__name__)

documentation = OpenApiDocumentation(
    app=app,
    options=DocumentationOptions(
        parameter_converter_classes=[UUIDConverter],
    ),
)

Note that the class should be passed, and not an instance.

Resource defaults (blueprints)

It is common practice to group several Flask related resources together in a Blueprint. Blueprints can greatly simplify how large applications work and provide a central means for Flask extensions to register operations on applications. Take for example the petstore example, which is an API with three resources: pet, store and user. This API could be designed using three blueprints, one for each resource. The pet resource might look the following:

from flask import Blueprint

blueprint = Blueprint(
    name="pet",
    import_name=__name__,
    url_prefix="/pet",
)

from . import upload_image, post, put, find_by_status, find_by_tags, get, post, delete

All these endpoints would use the same Tag, which groups them under the pet resource. It would bad design to copy this tag for all endpoints, and therefore defaults can be configured on the blueprint variable:

from openapi_builder import set_resource_options
from openapi_builder.specification import Tag

set_resource_options(
    resource=blueprint,
    tags=[Tag(name="Pet", description="A description for the pet resource.")],
)

The following configuration options are applicable for passing to set_resource_options:

Argument

Type

Default value

Explanation

resource

Blueprint

<no-default>

The resource for which defaults need to be configured.

tags

Optional[List[Union[str, Tag]]]

None

A list of openapi_builder.specification.Tag objects to hold default tags for each endpoint in the resource.