Configuration
Contents
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:
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 |
---|---|---|---|
|
|
|
The Flask application for iterating the endpoints to find out the documentation. It not passed directly, it must
be passed via the |
|
|
|
The title of the API. |
|
|
|
The version of the OpenAPI document (which is distinct from the OpenAPI Specification version or the API implementation version). |
|
|
|
Additional optional documentation options that are global for the entire app. If not specified, a new
|
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 |
---|---|---|---|
|
|
|
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. |
|
|
|
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. |
|
|
|
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}. |
|
|
|
Whether default marshmallow converters are included in the |
|
|
|
Whether default halogen converters are included in the |
|
|
|
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 |
|
|
|
Whether something unforeseen happened, should the extension crash (preferred in testing), using
|
|
|
|
The content type used for requests throughout the entire application. |
|
|
|
The content type used for responses throughout the entire application. |
|
|
|
See Schema converters for more info about this option. |
|
|
|
See Defaults converters for more info about this option. |
|
|
|
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 |
---|---|---|---|
|
|
|
A dictionary from |
|
|
|
This argument is similar to the |
|
|
|
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
|
|
|
|
A short summary of what the operation does. |
|
|
|
A verbose explanation of the operation behavior. CommonMark syntax MAY be used for rich text representation. |
|
|
|
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 |
---|---|---|---|
|
|
|
The resource for which defaults need to be configured. |
|
|
|
A list of |