-
-
Notifications
You must be signed in to change notification settings - Fork 177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deep update components instead of overwriting components for OpenAPI 3 #222
Conversation
I think the behavior here is correct. @Guoli-Lyu Would you mind adding tests, please? |
|
||
ret.update(self.options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ret.update(self.options)
can be kept factorized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I explicitly pass components in options, this line of code would shadow ret['components'] that is generated by codes above. And that is why I have to differentiate the behaviors between OpenAPI 2 and 3.
Tests is added. And I feel like adding an example for this case as it demonstrates how to adopt specification on security and to add arbitrary top level fields. import yaml
from apispec import APISpec
from apispec.utils import validate_swagger
OPENAPI_SPEC = """
openapi: 3.0.1
info:
description: Server API document
title: Server API
version: 1.0.0
servers:
- url: http://localhost:{port}/
description: The development API server
variables:
port:
enum:
- '3000'
- '8888'
default: '3000'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
"""
settings = yaml.load(OPENAPI_SPEC)
# retrieve version, title and openapi or swagger version
version = str(settings.pop('openapi', None) or settings.pop('swagger', None))
title = settings['info'].pop('title')
spec_version = settings['info'].pop('version')
spec = APISpec(
title=title,
version=spec_version,
plugins=(
'apispec.ext.marshmallow',
),
openapi_version=version,
**settings
)
validate_swagger(spec) I don't know where to put this example, maybe in docs. Though I prefer to create an example folder and put examples in it. |
@Guoli-Lyu Good idea on documentation. I'd prefer examples to go in the docs, as they're more discoverable there. I think your example could go in the "Special Topics" section of the documentation. |
Let's get this merged. I'll write up some docs for this when I have time. |
For the record, there was an issue in this change as it popped stuff our of This change makes sense, however, this specific use case (defining security components) should be addressed by creating a component registrar (#245). |
Also for the record, we could do the same when using OpenAPI v2: merge definitions and parameters passed as |
In my case, I would like to specify securitySchemes in components
object. However, currently there is no predefined function to meet my
need. So I would like to specify components object when initialize
APISpec object.
The document says that the keyword arguments are optional top-level
keys. And I have managed to add optional top-level keys like server
objects.
However, the components objects I specified is shadowing components that is generated by apispec code. Relevant code locates in to_dict function in apispec.core:
I think it better to update component objects instead of
overwriting component objects. In this way, we can take advantages of both
custom settings and apispec functions.
Furthermore, I am rewriting relevant code to deep update components objects. In other words, the definitions defined by APISpec are merged with given schemas defined in top-level components objects. So do parameters in components objects.