-
-
Notifications
You must be signed in to change notification settings - Fork 158
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: Use annotations for parsing arguments #353
Comments
I was searching the web looking exactly for a solution to have method signature read by a decorator, parsed from request and fed to the method. Hoping to see this in webargs soon. |
But... I would prefer a different name. Annotations are a different thing. Maybe @use_type_hints or @args_from_method_signature |
I keep circling back to this to think about it, but with the same concern. How would such a decorator distinguish between type annotations meant for it, vs ones which are just part of a view function? In particular, if a view function is already decorated with user-defined decorators, it may be receiving a variety of arguments. I think that for really simple cases like your example it's very nice. But what if instead of def index(request, name: str = "World") it's @get_authenticated_username # passes username
@use_annotations(location="query")
def index(request, username: str, name: str = "World") or something similar? Would we simply not support such usages? Maybe that's okay, and just has to be documented, or maybe there's a workaround? |
I was just looking at webargs-starlette for inspiration, thinking about whether or not we could do this as part of v7 (and whether there are any backwards-incompatible changes we'd like to make for it, which would make now a good time for it). I think my above concern is basically a non-issue. First because nothing would force people to use such a feature, but also because we could easily add an optional |
Not sure how active this undertaking is, but usability could be improved even further by using PEP593 For instance, sqlalchemy uses them for its dataclass integration to augment to allow for more fine-grained configuration than what you can do with a type map. |
To elaborate, the objective is that passing e.g. For instance, the following snippet with vanilla @bp.route('/accounts/<int:account_id>/json')
@use_kwargs({
"style": fields.String(),
"limit": fields.Int(),
"offset": fields.Int(),
"sort_by": fields.String(data_key="sort", missing="valid_on"),
"sort_order": fields.String(data_key="order", missing="desc"),
"search": fields.String(),
"splitted": fields.Bool(missing=False),
}, location="query")
def accounts_show_json(
account_id: int,
*,
style: str | None = None,
limit: int | None = None,
offset: int | None = None,
sort_by: str,
sort_order: str,
search: str | None = None,
splitted: bool,
): ... However, clearly the information here is rendundant, so inferring the type information from the annotations is desirable. Now with @bp.route('/accounts/<int:account_id>/json')
@use_annotations(location="query", exclude={"account_id"})
def accounts_show_json(
account_id: int,
*,
style: str | None = None,
limit: int | None = None,
offset: int | None = None,
sort_by: fields.String(data_key="sort") = "valid_on",
sort_order: fields.String(data_key="order") = "desc",
search: str | None = None,
splitted: bool = False,
):
... However, as mentioned the above would not type check. PEP593 import typing as t
@bp.route('/accounts/<int:account_id>/json')
@use_annotations(location="query", exclude={"account_id"})
def accounts_show_json(
account_id: int,
*,
style: str | None = None,
limit: int | None = None,
offset: int | None = None,
sort_by: t.Annotated[str, fields.String(data_key="sort")] = "valid_on",
sort_order: t.Annotated[str, fields.String(data_key="order")] = "desc",
search: str | None = None,
splitted: bool = False,
):
... Note that in the example, I expect default values to be incorporated in the field's |
Add a decorator that will parse request arguments from the view function's type annotations.
I've built a working proof of concept of this idea in webargs-starlette.
A marshmallow
Schema
is generated from the annotations usingSchema.TYPE_MAPPING
to construct fields.The code for
use_annotations
mostly isn't tied to Starlette and could be adapted forAsyncParser
(andcore.Parser
when we drop Python 2 support).The text was updated successfully, but these errors were encountered: