-
Notifications
You must be signed in to change notification settings - Fork 71
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
[RFC] Deprecate Blueprint.doc decorator #71
Comments
It's likely that most of these issues would be solved by #49, no? Users could simply set I think that doing so satisfies the "Document specific API features" use case and the "Document parameters / responses" use case. Granted, I don't know much about the goals here, so it may be completely off base. Do things like specific API features or extra info to responses need to be easily accessible such as being a key in a dict? For example, is this needed? {'summary': "Summary line.",
'description': "Long description",
'api_feature': "Some API feature",
} or can it just be in the description? {'summary': "Summary line.",
'description': "Long description\n\nSome info about an API feature",
} |
@dougthor42, nope. flask-rest-api and apispec mean to actually use the features defined in the OpenAPI spec. Cramming all information in the "description" field in an unstructured way defeats the point of the spec. For instance, it does not allow tools to display the features properly. Besides, you don't need to use |
We are using the doc decorator to specify an operationId which is consumed by openapi-generator for generating client method names, unique to each path not just the route: @blp.doc(operationId="getSomeData")
def get(self):
return someData
@blp.doc(operationId="setSomeData")
def post(self, newData):
someData.update(newData) will generate a client method like: const someData = await myApi.getSomeData();
await myApi.setSomeData(otherData); |
@aiham This looks like a legit use case. I didn't know about that OAS feature. We could try to add a feature to provide default unique IDs based on blueprint/route/endpoint/method if that is deemed useful. But anyway, users may want to force their own
|
Obviously, another option is to keep the doc decorator as it is and document what it should not be used for. It sounds a bit cheap and dirty, but it could be the most pragmatic and future-proof choice. |
Auto generating I think keeping We are also using @blp.doc(security=[{"mySecurityScheme":[]}]) I think these are examples that you can't necessarily guarantee the whole spec has been implemented by this library, but there's also the case of new fields being added to the spec in the future that you can't predict. It would be better to let library users extend it rather than restrict them. If that is via a differently named decorator I'd be happy with that too. Also one comment on the known issue:
Maybe whatever is specified with
These are just my thoughts, hopefully you get some value from them. Thanks for |
Thanks for the valuable feedback, really. Yeah, I guess trying to cover every feature explicitly in this lib is a chimera. Ultimately, we're probably gonna keep Another limitation of The issues with arguments is that they are a list. You can deep merge dicts but not lists. So introducing an argument in there erases all auto documented arguments rather than adding to them. I get your point with taking precedence, but erasing all auto documented arguments (i.e. having to recreate them manually) just to add or complete a single argument is really a pity. We could try to fix this specific issue by adding a specific logic for this case, but that would be just the beginning of a whole series of alike troubles. My stance on this is to not use it to tweak response/arguments. Rather than trying to prevent this, we could just document it and let the user know what he is doing. I'm still not comfortable with this. Regarding the security schema, my advice would be to modify the decorator you're using to enforce it so that it also documents what it does. => DRYer resources. I agree about |
Yes, the decorator which enforces access control is the one that calls |
Ah, OK. We do the same but instead of calling |
Idea: dynamically create decorators for OpenAPI documentation keys.
For example, to set an operation ID, mark the operation as deprecated, and include code samples, you'd use: @blp.route('/')
class Pets(MethodView):
@blp.arguments(TagsSchema, location='query')
@blp.response(200, PetSchema(many=True))
@blp.operation.operation_id("findPetsByTags")
@blp.operation.deprecated(True)
@blp.operation.x_code_samples([dict(lang="Python", source="import requests\n\n...")])
def get(self, tags):
"""Finds Pets by tags
Multiple tags can be provided with comma separated strings. Use tag1,
tag2, tag3 for testing.
""" The name @blp.oas2.consumes(...) # only applies to OpenAPI v2
@blp.oas30.oas31.callbacks(...) # only applies to OpenAPI v3.0 and v3.1 For operation keys that have existing methods, you could throw an exception, or raise a warning, and in the exception or warning message include information about better ways to set the specific key (e.g. Instead of using @blp.operation.summary, give your function a docstring. The first line automatically becomes the operation summary. See [documentation link]). For invalid key-names you can redirect the developer to the These attributes just produce a generic decorator function with the target OpenAPI key and version information as a closure. Yes, this is just the same thing as the The decorator is not intended to support merging. |
Sorry for the delay. Thanks to user feedback and own experience, my mind is moving towards keeping this decorator in a form or another. As I wrote above, for the security decorator case, the best thing to do IMHO is to override the decorator to let it auto-document (currently by writing in My main concern is how to merge with autodoc, especially for the parameters case (because it is a list). I haven't been giving it much thought since then and I don't expect a solution to come out of the blue. @mjpieters the feature you describe above sounds neat. I don't see myself implementing this any soon. High work / benefit ratio. And the whole thing is not in my priorities. But thanks for sharing a clear specification to build upon. Meanwhile, this issue is 2 year old and the status quo still stands. BTW, this makes me think of another design issue. Theoretically, view functions can be decorated by calling the decorator as a function rather than with the decorator syntax, and one may even decorate the same view func with two different unnested decorators. def view_func(self):
return stuff
# View func decorated with decorator 1
blp.route('/path_1')(decorator_1(view_func))
# View func decorated with decorator 2
blp.route('/path_2')(decorator_2(view_func)) Because of this, I always deepcopy the doc structure to avoid two resources docs being mixed up. To do so, even if the decorator doesn't affect the function, only the doc, I still need to wrap the function in another function. flask-smorest/flask_smorest/blueprint.py Lines 220 to 232 in 16f7677
The deepcopy in itself is not an issue, but the wrapping adds to the call stack. I don't think it matters as long as the number of nested decorators is limited, but it matters more when decorators pile up. In any case, the impact on performance is probably negligible. I always thought it was a pity to waste this just for the corner case described above, but I couldn't come up with a better solution. |
Perhaps you could substitute the wrapper with
Use |
Never mind; a partialmethod can't itself easily be decorated (it can't be called directly, it must be bound). |
Perhaps this SO post or this one would help. Keeping this for later. |
The
Blueprint.doc
decorator is meant to add documentation that can't be inferred from the code or added by dedicated decorators. It allows the user to pass manual documentation that will be deep-merged with the automatically generated documentation. Unfortunately, it is not the silver bullet one would expect. It suffers from a few intrinsic issues.We could try to play smart and improve the way the structure received by
doc
is used, but I'd rather add dedicated decorators or other explicit means to allow the user to pass documentation in a structured fashion, with a clear and thin abstraction layer.I'd like to use this issue to list known issues about
Blueprint.doc
and use cases that should be covered by other means. The goal being to make it useless, and to deprecate it if possible.Known issues
response
decorator (Support for http.HTTPStatus #60 (comment)).['content']['application/json']
when using v3 which makes it more verbose to the user.Use cases
response
/arguments
decorators._apidoc
attribute mechanism becomes public API.Blueprint.route
. (See No way to add description to path parameters #23)The text was updated successfully, but these errors were encountered: