luolingchun / flask-openapi3

Generate REST API and OpenAPI documentation for your Flask project.
https://luolingchun.github.io/flask-openapi3/
MIT License
203 stars 33 forks source link

Setting an example value for a field in query object generates deprecation warnings with pydantic >= 2.8 #177

Closed guillaume-alvarez closed 2 months ago

guillaume-alvarez commented 2 months ago

Environment:

/!\ This issue is similar to https://github.com/luolingchun/flask-openapi3/issues/176 but this time for a model used in a query

Warning

If I define a model setting Field.example (not defined in pydantic):

class Query(BaseModel):
    stream_id: str = Field(..., example="test_stream")

then it causes warnings because it is not officially supported by pydantic:

PydanticDeprecatedSince20: Using extra keyword arguments on `Field` is deprecated and will be removed. Use `json_schema_extra` instead. (Extra keys: 'example'). Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.9/migration/

Crash

If I define a model setting the Field.examples as advised by pydantic:

class Query(BaseModel):
    stream_id: str = Field(..., examples="test_stream")

Then it crashes the application:

  File "/project/.venv/lib/python3.12/site-packages/flask_openapi3/scaffold.py", line 163, in decorator
    self._collect_openapi_info(
  File "/project/.venv/lib/python3.12/site-packages/flask_openapi3/blueprint.py", line 181, in _collect_openapi_info
    header, cookie, path, query, form, body, raw = parse_parameters(
                                                   ^^^^^^^^^^^^^^^^^
  File "/project/.venv/lib/python3.12/site-packages/flask_openapi3/utils.py", line 458, in parse_parameters
    _parameters, _components_schemas = parse_query(query)
                                       ^^^^^^^^^^^^^^^^^^
  File "/project/.venv/lib/python3.12/site-packages/flask_openapi3/utils.py", line 246, in parse_query
    parameters.append(Parameter(**data))
                      ^^^^^^^^^^^^^^^^^
  File "/project/.venv/lib/python3.12/site-packages/pydantic/main.py", line 209, in __init__
    validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 1 validation error for Parameter
examples
  Input should be a valid dictionary [type=dict_type, input_value='test_stream', input_type=str]
    For further information visit https://errors.pydantic.dev/2.9/v/dict_type

This field was added in pydantic 2.5.0 by https://github.com/pydantic/pydantic/pull/8013

Debugging the code I see that flask_openapi3.utils.parse_query will try to parse the examples value as an Optional[Dict[str, Union[Example, Reference]]], which seems in line with the OpenAPI 3.1.0 spec. Maybe some conversion could be made in flask_openapi3.utils.parse_query to support a list[str] example that is valid in pydantic?

luolingchun commented 2 months ago

OpenAPI and pydantic have completely different definitions for examples, so they can't be mixed.

OpenAPI-Parameter Object:

image

Pydantic-Field:

image

In fact, Flask-openapi3 already supports customizing the examples field, please refer to the documentation.

guillaume-alvarez commented 2 months ago

Thanks for the explanation.