Skip to content

Cannot use models generated by datamodel-codegen from OpenAPI 3.0 spec with property-level example:s #4476

Closed
@nlykkei

Description

@nlykkei
Contributor

Expected Behaviour

I would like to use models generated by datamodel-codegen from OpenAPI 3.0 spec with property-level example:s

Current Behaviour

The following components.schemas.LddProjectsList:

LddProjectsList:
  title: LddProjectsList
  type: object
  properties:
    pagination:
      type: object
      properties:
        next:
          type: string
          description: The next page uri
          format: uri
          example: http://www.example.com/some/path?cursor=SW0gYW4gb3BhcXVlIGN1cnNvcg==
        current:
          type: integer
          description: The current page number
        total:
          description: The total number of pages
          type: integer
      required:
        - next
        - current
        - total
    projects:
      type: array
      items:
        $ref: "#/components/schemas/LddProject"
    cursor:
      type: string
  required:
    - pagination
    - projects

Results in the following model being output by datamodel-codegen:

class Pagination(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True,
    )
    next: AnyUrl = Field(..., examples=["http://www.example.com/some/path?cursor=SW0gYW4gb3BhcXVlIGN1cnNvcg=="])
    """
    The next page uri
    """
    current: int
    """
    The current page number
    """
    total: int
    """
    The total number of pages
    """

When using the Pagination model with AWS Lambda Powertools REST API Event Handler, as part of Response[T], the following error is generated when attempting to generate OpenAPI 3.0 spec, as it expects either a valid dict or Example:

❯ poetry run python src/lego/bff/application/lambda_handlers/api_gateway_proxy_handler.py
/Users/dknilyiv/projects/lddprobff/lego/.venv/lib/python3.12/site-packages/pydantic/_internal/_fields.py:160: UserWarning: Field "model_bags" has conflict with protected namespace "model_".

You may be able to resolve this warning by setting `model_config['protected_namespaces'] = ()`.
  warnings.warn(
/Users/dknilyiv/projects/lddprobff/lego/.venv/lib/python3.12/site-packages/aws_lambda_powertools/event_handler/api_gateway.py:1550: UserWarning: You are using Pydantic v2, which is incompatible with OpenAPI schema 3.0. Forcing OpenAPI 3.1
  openapi_version = self._determine_openapi_version(openapi_version)
Traceback (most recent call last):
  File "/Users/dknilyiv/projects/lddprobff/lego/src/lego/bff/application/lambda_handlers/api_gateway_proxy_handler.py", line 874, in <module>
    app.get_openapi_json_schema(
  File "/Users/dknilyiv/projects/lddprobff/lego/.venv/lib/python3.12/site-packages/aws_lambda_powertools/event_handler/api_gateway.py", line 1717, in get_openapi_json_schema
    self.get_openapi_schema(
  File "/Users/dknilyiv/projects/lddprobff/lego/.venv/lib/python3.12/site-packages/aws_lambda_powertools/event_handler/api_gateway.py", line 1617, in get_openapi_schema
    return OpenAPI(**output)
           ^^^^^^^^^^^^^^^^^
  File "/Users/dknilyiv/projects/lddprobff/lego/.venv/lib/python3.12/site-packages/pydantic/main.py", line 176, in __init__
    self.__pydantic_validator__.validate_python(data, self_instance=self)
pydantic_core._pydantic_core.ValidationError: 3 validation errors for OpenAPI
components.schemas.Pagination.Schema.properties.next.Schema.examples.0
  Input should be a valid dictionary or instance of Example [type=model_type, input_value='http://www.example.com/s...W4gb3BhcXVlIGN1cnNvcg==', input_type=str]
    For further information visit https://errors.pydantic.dev/2.7/v/model_type
components.schemas.Pagination.Schema.properties.next.bool
  Input should be a valid boolean [type=bool_type, input_value={'examples': ['http://www...Next', 'type': 'string'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.7/v/bool_type
components.schemas.Pagination.Reference.$ref
  Field required [type=missing, input_value={'properties': {'next': {...tion', 'type': 'object'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.7/v/missing

Code snippet

Possible Solution

No response

Steps to Reproduce

See current behavior

Powertools for AWS Lambda (Python) version

latest

AWS Lambda function runtime

3.12

Packaging format used

PyPi

Debugging logs

No response

Activity

added
bugSomething isn't working
triagePending triage from maintainers
on Jun 10, 2024
heitorlessa

heitorlessa commented on Jun 10, 2024

@heitorlessa
Contributor

hey @nlykkei , thank you for reporting it - got any code snippet to make it easier to reproduce it?

Edit: brew latest upgrade broke openssl on my machine so I'll take longer to debug.

moved this from Triage to Working on it in Powertools for AWS Lambda (Python)on Jun 10, 2024
self-assigned this
on Jun 10, 2024
heitorlessa

heitorlessa commented on Jun 10, 2024

@heitorlessa
Contributor

@leandrodamascena are you able to look into it tomorrow? had a rough day today and w/ development setup suddenly broken it was hard to concentrate. It almost looks like either input or a type we can't deserialize (AnyUrl?).

leandrodamascena

leandrodamascena commented on Jun 10, 2024

@leandrodamascena
Contributor

Hey @nlykkei! Thanks for reporting this situation.

In your components.schemas.LddProjectsList, you are using a single example entry: example: http://www.example.com/some/path?cursor=SW0gYW4gb3BhcXVlIGN1cnNvcg==. However, in your model, you are using multiple entries for the example field when you use the examples field. To achieve what you're looking for, your code should be something like this:

from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from pydantic import AnyUrl, BaseModel, ConfigDict, Field

app = APIGatewayRestResolver(enable_validation=True)

class Pagination(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True,
    )
    next: AnyUrl = Field(..., example="http://www.example.com/some/path?cursor=SW0gYW4gb3BhcXVlIGN1cnNvcg==")
    """
    The next page uri
    """
    current: int
    """
    The current page number
    """
    total: int
    """
    The total number of pages
    """

@app.get("/hello")
def hello() -> Pagination:
    ...

def lambda_handler(event, context):
    print(app.get_openapi_json_schema())
    app.resolve(event, context)

Perhaps you genuinely desire to utilize the examples field at the component level. However, you mentioned that you're employing OpenAPI 3.0, and while it is indeed feasible to define examples in OpenAPI 3.0, you may encounter difficulties in validating them within Swagger, as Swagger only accepts examples at the component level from version 3.1.0 onward.

image

Please let me know if you have any additional question.

Thanks

moved this from Working on it to Pending customer in Powertools for AWS Lambda (Python)on Jun 10, 2024

32 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingevent_handlerson-holdThis item is on-hold and will be revisited in the futureopenapi-schema

Type

No type

Projects

Status

Shipped

Milestone

No milestone

Relationships

None yet

    Participants

    @heitorlessa@leandrodamascena@dreamorosi@nlykkei

    Issue actions

      Cannot use models generated by `datamodel-codegen` from OpenAPI 3.0 spec with property-level `example:`s · Issue #4476 · aws-powertools/powertools-lambda-python