OpenAPITools / OpenAPITools/openapi-generator

[BUG] [Python] [7.6.0] pydantic reports 'Field may not be used twice on the same field' for generated models

Open
#18,960 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

if the model schema have more then 1 constraints like: description and maxLength, the generator generated python model can't work with pydantic.

1, generate the python client using command:
openapi-generator-cli generate -i petstore.yaml -g python -o ./pet
2, run geneated pet.py, like: python3 pet.py

Traceback (most recent call last):
  File "/${home}/workspace/zuora-api/sdk-v1-samples/py-sdk-sample/sample/pet.py", line 26, in <module>
    class Pet(BaseModel):
  File "/${home}/.pyenv/versions/3.9.17/lib/python3.9/site-packages/pydantic/_internal/_model_construction.py", line 171, in __new__
    set_model_fields(cls, bases, config_wrapper, types_namespace)
  File "/${home}/.pyenv/versions/3.9.17/lib/python3.9/site-packages/pydantic/_internal/_model_construction.py", line 361, in set_model_fields
    fields, class_vars = collect_model_fields(cls, bases, config_wrapper, types_namespace, typevars_map=typevars_map)
  File "/${home}/.pyenv/versions/3.9.17/lib/python3.9/site-packages/pydantic/_internal/_fields.py", line 162, in collect_model_fields
    field_info = FieldInfo.from_annotated_attribute(ann_type, default)
  File "/${home}/.pyenv/versions/3.9.17/lib/python3.9/site-packages/pydantic/fields.py", line 310, in from_annotated_attribute
    default.annotation, annotation_metadata = cls._extract_metadata(annotation, default)
  File "/${home}/.pyenv/versions/3.9.17/lib/python3.9/site-packages/pydantic/fields.py", line 398, in _extract_metadata
    raise TypeError('Field may not be used twice on the same field')
TypeError: Field may not be used twice on the same field

pydantic == 2.0, python version: 3.9

openapi-generator version

7.6.0

OpenAPI declaration file content or url

the main reason is property lastName in Pet, which have two contraints: description and maxLength.

openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            maximum: 100
            format: int32
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Pet'
        required: true
      responses:
        '201':
          description: Null response
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      tags:
        - pets
      parameters:
        - name: petId
          in: path
          required: true
          description: The id of the pet to retrieve
          schema:
            type: string
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pet"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
components:
  schemas:
    Pet:
      type: object
      required:
        - id
        - name
        - lastName
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string
        lastName:
          description: 'this is desc'
          maxLength: 100
          type: string
    Pets:
      type: array
      maxItems: 100
      items:
        $ref: "#/components/schemas/Pet"
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string

Generation Details

openapi-generator-cli generate -i petstore.yaml -g python -o ./pet

Steps to reproduce

1, generate the python client using command:
openapi-generator-cli generate -i petstore.yaml -g python -o ./pet
2, run geneated pet.py, like: python3 pet.py

Related issue should be last_name in pet.py:

    last_name: Annotated[str, Field(strict=True, max_length=100)] = Field(description="this is desc", alias="lastName")

My understanding, correct one should be:

    last_name: Annotated[str, Field(strict=True, max_length=100, description="this is desc", alias="lastName")]

Related issues/PRs
Suggest a fix

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Use the supplied petstore.yaml and run the documented openapi-generator-cli command, then execute the generated pet.py with pydantic 2.0. Inspect the last_name declaration and compare it with the expected single-Field form shown in the issue. Done means the generated model loads without the duplicate-Field TypeError while retaining the description, alias, and max_length constraints.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.