0b01001001 / spectree

API spec validator and OpenAPI document generator for Python web frameworks.
https://0b01001001.github.io/spectree/
Apache License 2.0
316 stars 74 forks source link

bug: SecuritySchemeData root_validator conflicts with alias #350

Open jelmerk opened 11 months ago

jelmerk commented 11 months ago

Describe the bug

Impossible to create SecuritySchemeData with field_in field because of the alias="in" field on the pydantic field_in field

To Reproduce

from spectree.models import InType, SecureType, SecuritySchemeData

if __name__ == "__main__":
    foo = SecuritySchemeData(
        type=SecureType.API_KEY,
        name="X-MIRO-ID",
        field_in=InType.HEADER,
        description="Miro passport authentication",
        scheme="passport",
    )

Expected behavior

Should create a valid SecuritySchemeData but instead raises this exception

pydantic.error_wrappers.ValidationError: 1 validation error for SecuritySchemeData
__root__
  For `apiKey` type `name, field_in` field(s) is required. (type=value_error)

The spectree version

Name: spectree Version: 1.2.3 Summary: generate OpenAPI document and validate request&response with Python annotations. Home-page: Author: Author-email: Keming Yang kemingy94@gmail.com License: Apache-2.0 Location: /Users/jkuperus/Library/Caches/pypoetry/virtualenvs/data-workflow-service-VxjL5469-py3.8/lib/python3.8/site-packages Requires: pydantic Required-by: Darwin Jelmers-MacBook-Pro.local 22.6.0 Darwin Kernel Version 22.6.0: Wed Jul 5 22:22:05 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T6000 arm64 Python 3.8.10

Additional context

As a workaround you can do

SecuritySchemeData(
        **{
             "type": SecureType.API_KEY,
             "name": "X-MIRO-ID",
             "in": InType.HEADER,
             "scheme": "passport",
             "description": "Miro passport authentication",
         }
     )
kemingy commented 11 months ago

Hi @jelmerk, thanks for the feedback.

This is a bit tricky. Alias here is necessary since “in” is a keyword in Python. Let me check if we can make it work with the “root_validator”.

kemingy commented 11 months ago

I found that field with alias need to pass the aliased name.

class Model(BaseModel):
    schema_x: str = Field(
        description="xxx",
        alias="schema"
    )
Model(schema_x="xyz")

This will panic since schema is required. But in is a keyword, so the only way to use it is passing it in a dict ("in" instead of in).

I didn't find any other solutions.