OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.49k stars 6.5k forks source link

[BUG][Python Client] oneOf for different constrainted types fails to resolve with missing patterns #19034

Open RonnyPfannschmidt opened 3 months ago

RonnyPfannschmidt commented 3 months ago

Bug Report Checklist

Description

when generating modles fo one-of/any-of of multiple string, a intermediate models for pydantic is generated, which ignores patterns and passes/fails in a confusing manner

https://github.com/RonnyPfannschmidt-RedHat/openapi-codegen-show-issues/blob/9659d501374b493fe1dd43aa18c48ba2c3b924d0/oapi_codegen_broken_string/models/pass_string_mangled_string_any.py#L29-L115

https://github.com/RonnyPfannschmidt-RedHat/openapi-codegen-show-issues/blob/9659d501374b493fe1dd43aa18c48ba2c3b924d0/oapi_codegen_broken_string/models/pass_string_mangled_string_one.py#L27C1-L118C1

openapi-generator version

7.6.0

OpenAPI declaration file content or url

https://github.com/RonnyPfannschmidt-RedHat/openapi-codegen-show-issues/blob/9659d501374b493fe1dd43aa18c48ba2c3b924d0/openapi/openapi.BrokenString.yaml#L1-L42

openapi: 3.0.0
info:
  title: Broken Examples Home
  version: 0.0.0
tags: []
paths:
  /string-example:
    get:
      operationId: Mangled_get
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PassString'
components:
  schemas:
    HereBeDragons:
      type: string
      pattern: here
    PassString:
      type: object
      properties:
        mangled_string_one:
          oneOf:
            - $ref: '#/components/schemas/PettyNumber'
            - $ref: '#/components/schemas/HereBeDragons'
        mangled_string_any:
          anyOf:
            - $ref: '#/components/schemas/PettyNumber'
            - $ref: '#/components/schemas/HereBeDragons'
    PettyNumber:
      type: string
      pattern: '[0-9]{2,8}'
servers:
  - url: https://example.com
    description: The service endpoint
    variables: {}
Generation Details
npm run openapi-compile -- \
    -i openapi/openapi.BrokenString.yaml\
    --package-name=oapi_codegen_condused_values
Suggest a fix

a starting point would be to re-attach the patterns to the validation

optional strings with a string constraints should be used

additionally the nesting is quite a pain wrt choice of object models, i'd strongly prefer if no indirection models where introduced

https://github.com/RonnyPfannschmidt-RedHat/openapi-codegen-show-issues/blob/9659d501374b493fe1dd43aa18c48ba2c3b924d0/manual_pydantic_broken_string.py is a minimal version of using pydantic validators to pass over those values

my recommendation for openapi-codegen would be to create type aliases for constrainted strings (using either type statements or the runtime backport for them

RonnyPfannschmidt commented 3 months ago

>>> import oapi_codegen_condused_values.models
>>> oapi_codegen_condused_values.models.PassString.from_dict({"mangled_string_one": "here"})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...openapi-codegen-show-issues/oapi_codegen_condused_values/models/pass_string.py", line 92, in from_dict
    "mangled_string_one": PassStringMangledStringOne.from_dict(obj["mangled_string_one"]) if obj.get("mangled_string_one") is not None else None,
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../oapi_codegen_condused_values/models/pass_string_mangled_string_one.py", line 82, in from_dict
    return cls.from_json(json.dumps(obj))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../oapi_codegen_condused_values/models/pass_string_mangled_string_one.py", line 115, in from_json
    raise ValueError("No match found when deserializing the JSON string into PassStringMangledStringOne with oneOf schemas: str. Details: " + ", ".join(error_messages))
ValueError: No match found when deserializing the JSON string into PassStringMangledStringOne with oneOf schemas: str. Details: 1 validation error for PassStringMangledStringOne
actual_instance
  Value error, Multiple matches found when setting `actual_instance` in PassStringMangledStringOne with oneOf schemas: str. Details:  [type=value_error, input_value='here', input_type=str]
    For further information visit https://errors.pydantic.dev/2.7/v/value_error, 1 validation error for PassStringMangledStringOne
actual_instance
  Value error, Multiple matches found when setting `actual_instance` in PassStringMangledStringOne with oneOf schemas: str. Details:  [type=value_error, input_value='here', input_type=str]
    For further information visit https://errors.pydantic.dev/2.7/v/value_error
>>>