Skip to content

APIBlueprint

APIBlueprint ⚓︎

Bases: APIScaffold, Blueprint

Source code in flask_openapi3/blueprint.py
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
class APIBlueprint(APIScaffold, Blueprint):
    def __init__(
            self,
            name: str,
            import_name: str,
            *,
            abp_tags: Optional[List[Tag]] = None,
            abp_security: Optional[List[Dict[str, List[str]]]] = None,
            abp_responses: Optional[ResponseDict] = None,
            doc_ui: bool = True,
            operation_id_callback: Callable = get_operation_id_for_path,
            **kwargs: Any
    ) -> None:
        """
        Based on Flask Blueprint

        Args:
            name: The name of the blueprint. It Will be prepared to each endpoint name.
            import_name: The name of the blueprint package, usually ``__name__``.
                         This helps locate the ``root_path`` for the blueprint.
            abp_tags: APIBlueprint tags for every API.
            abp_security: APIBlueprint security for every API.
            abp_responses: API responses should be either a subclass of BaseModel, a dictionary, or None.
            doc_ui: Enable OpenAPI document UI (Swagger UI, Redoc, and Rapidoc). Defaults to True.
            operation_id_callback: Callback function for custom operation_id generation.
                                   Receives name (str), path (str) and method (str) parameters.
                                   Defaults to `get_operation_id_for_path` from utils
            **kwargs: Flask Blueprint kwargs
        """
        super(APIBlueprint, self).__init__(name, import_name, **kwargs)

        # Initialize instance variables
        self.paths: Dict = dict()
        self.components_schemas: Dict = dict()
        self.tags: List[Tag] = []
        self.tag_names: List[str] = []

        # Set values from arguments or default values
        self.abp_tags = abp_tags or []
        self.abp_security = abp_security or []

        abp_responses = abp_responses or {}
        # Convert key to string
        self.abp_responses = convert_responses_key_to_string(abp_responses)

        self.doc_ui = doc_ui

        # Set the operation ID callback function
        self.operation_id_callback: Callable = operation_id_callback

    def register_api(self, api: "APIBlueprint") -> None:
        """Register a nested APIBlueprint"""

        # Check if the APIBlueprint is being registered on itself
        if api is self:
            raise ValueError("Cannot register a api blueprint on itself")

        # Merge tags from the nested APIBlueprint
        for tag in api.tags:
            if tag.name not in self.tag_names:
                self.tags.append(tag)

        # Merge paths from the nested APIBlueprint
        for path_url, path_item in api.paths.items():
            # Parse rule: merge url_prefix and format rule from /pet/<petId> to /pet/{petId}
            uri = parse_rule(path_url, url_prefix=self.url_prefix)

            self.paths[uri] = path_item

        # Merge component schemas from the nested APIBlueprint
        self.components_schemas.update(**api.components_schemas)

        # Register the nested APIBlueprint as a blueprint
        self.register_blueprint(api)

    def _add_url_rule(
            self,
            rule,
            endpoint=None,
            view_func=None,
            provide_automatic_options=None,
            **options,
    ) -> None:
        self.add_url_rule(rule, endpoint, view_func, provide_automatic_options, **options)

    def _collect_openapi_info(
            self,
            rule: str,
            func: Callable,
            *,
            tags: Optional[List[Tag]] = None,
            summary: Optional[str] = None,
            description: Optional[str] = None,
            external_docs: Optional[ExternalDocumentation] = None,
            operation_id: Optional[str] = None,
            responses: Optional[ResponseDict] = None,
            deprecated: Optional[bool] = None,
            security: Optional[List[Dict[str, List[Any]]]] = None,
            servers: Optional[List[Server]] = None,
            openapi_extensions: Optional[Dict[str, Any]] = None,
            doc_ui: bool = True,
            method: str = HTTPMethod.GET
    ) -> ParametersTuple:
        """
        Collects OpenAPI specification information for Flask routes and view functions.

        Args:
            rule: Flask route
            func: Flask view_func
            tags: Adds metadata to a single tag.
            summary: A short summary of what the operation does.
            description: A verbose explanation of the operation behavior.
            external_docs: Additional external documentation for this operation.
            operation_id: Unique string used to identify the operation.
            responses: API responses should be either a subclass of BaseModel, a dictionary, or None.
            deprecated: Declares this operation to be deprecated.
            security: A declaration of which security mechanisms can be used for this operation.
            servers: An alternative server array to service this operation.
            openapi_extensions: Allows extensions to the OpenAPI Schema.
            doc_ui: Declares this operation to be shown. Default to True.
        """
        if self.doc_ui is True and doc_ui is True:
            if responses is None:
                new_responses = {}
            else:
                # Convert key to string
                new_responses = convert_responses_key_to_string(responses)
            # Global response: combine API responses
            combine_responses = deepcopy(self.abp_responses)
            combine_responses.update(**new_responses)
            # Create operation
            operation = get_operation(
                func,
                summary=summary,
                description=description,
                openapi_extensions=openapi_extensions
            )
            # Set external docs
            operation.externalDocs = external_docs
            # Unique string used to identify the operation.
            operation.operationId = operation_id or self.operation_id_callback(
                name=self.name, path=rule, method=method
            )
            # Only set `deprecated` if True, otherwise leave it as None
            operation.deprecated = deprecated
            # Add security
            if security is None:
                security = []
            operation.security = security + self.abp_security or None
            # Add servers
            operation.servers = servers
            # Store tags
            tags = tags + self.abp_tags if tags else self.abp_tags
            parse_and_store_tags(tags, self.tags, self.tag_names, operation)
            # Parse parameters
            header, cookie, path, query, form, body, raw = parse_parameters(
                func,
                components_schemas=self.components_schemas,
                operation=operation
            )
            # Parse response
            get_responses(combine_responses, self.components_schemas, operation)

            # Parse rule: merge url_prefix and format rule from /pet/<petId> to /pet/{petId}
            uri = parse_rule(rule, url_prefix=self.url_prefix)

            # Parse method
            parse_method(uri, method, self.paths, operation)
            return header, cookie, path, query, form, body, raw
        else:
            # Parse parameters
            header, cookie, path, query, form, body, raw = parse_parameters(func, doc_ui=False)
            return header, cookie, path, query, form, body, raw

__init__(name, import_name, *, abp_tags=None, abp_security=None, abp_responses=None, doc_ui=True, operation_id_callback=get_operation_id_for_path, **kwargs) ⚓︎

Based on Flask Blueprint

Parameters:

Name Type Description Default
name str

The name of the blueprint. It Will be prepared to each endpoint name.

required
import_name str

The name of the blueprint package, usually __name__. This helps locate the root_path for the blueprint.

required
abp_tags Optional[List[Tag]]

APIBlueprint tags for every API.

None
abp_security Optional[List[Dict[str, List[str]]]]

APIBlueprint security for every API.

None
abp_responses Optional[ResponseDict]

API responses should be either a subclass of BaseModel, a dictionary, or None.

None
doc_ui bool

Enable OpenAPI document UI (Swagger UI, Redoc, and Rapidoc). Defaults to True.

True
operation_id_callback Callable

Callback function for custom operation_id generation. Receives name (str), path (str) and method (str) parameters. Defaults to get_operation_id_for_path from utils

get_operation_id_for_path
**kwargs Any

Flask Blueprint kwargs

{}
Source code in flask_openapi3/blueprint.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
def __init__(
        self,
        name: str,
        import_name: str,
        *,
        abp_tags: Optional[List[Tag]] = None,
        abp_security: Optional[List[Dict[str, List[str]]]] = None,
        abp_responses: Optional[ResponseDict] = None,
        doc_ui: bool = True,
        operation_id_callback: Callable = get_operation_id_for_path,
        **kwargs: Any
) -> None:
    """
    Based on Flask Blueprint

    Args:
        name: The name of the blueprint. It Will be prepared to each endpoint name.
        import_name: The name of the blueprint package, usually ``__name__``.
                     This helps locate the ``root_path`` for the blueprint.
        abp_tags: APIBlueprint tags for every API.
        abp_security: APIBlueprint security for every API.
        abp_responses: API responses should be either a subclass of BaseModel, a dictionary, or None.
        doc_ui: Enable OpenAPI document UI (Swagger UI, Redoc, and Rapidoc). Defaults to True.
        operation_id_callback: Callback function for custom operation_id generation.
                               Receives name (str), path (str) and method (str) parameters.
                               Defaults to `get_operation_id_for_path` from utils
        **kwargs: Flask Blueprint kwargs
    """
    super(APIBlueprint, self).__init__(name, import_name, **kwargs)

    # Initialize instance variables
    self.paths: Dict = dict()
    self.components_schemas: Dict = dict()
    self.tags: List[Tag] = []
    self.tag_names: List[str] = []

    # Set values from arguments or default values
    self.abp_tags = abp_tags or []
    self.abp_security = abp_security or []

    abp_responses = abp_responses or {}
    # Convert key to string
    self.abp_responses = convert_responses_key_to_string(abp_responses)

    self.doc_ui = doc_ui

    # Set the operation ID callback function
    self.operation_id_callback: Callable = operation_id_callback

register_api(api) ⚓︎

Register a nested APIBlueprint

Source code in flask_openapi3/blueprint.py
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
def register_api(self, api: "APIBlueprint") -> None:
    """Register a nested APIBlueprint"""

    # Check if the APIBlueprint is being registered on itself
    if api is self:
        raise ValueError("Cannot register a api blueprint on itself")

    # Merge tags from the nested APIBlueprint
    for tag in api.tags:
        if tag.name not in self.tag_names:
            self.tags.append(tag)

    # Merge paths from the nested APIBlueprint
    for path_url, path_item in api.paths.items():
        # Parse rule: merge url_prefix and format rule from /pet/<petId> to /pet/{petId}
        uri = parse_rule(path_url, url_prefix=self.url_prefix)

        self.paths[uri] = path_item

    # Merge component schemas from the nested APIBlueprint
    self.components_schemas.update(**api.components_schemas)

    # Register the nested APIBlueprint as a blueprint
    self.register_blueprint(api)