openapi-generators / openapi-generators/openapi-python-client

Incorrect generation of `_parse_response `

Aberta
#1,125 0 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

Linguagem predominante
Python
Estrelas
2k
Forks
293
Merge médio
34min
PRs com merge (30d)
1

Descrição

Lovely package BTW!

Describe the bug
Code generation for parsing API response does not generate the code that creates the Python model after the response is completed. This happens when using a $ref to define the response instead of just defining the response body inside the path definition.

OpenAPI Spec File

openapi: 3.0.3

info:
  title: Example
  description: |
    Example API definition.
  version: 1.0.0

security:
    - BearerAuth: []

paths:

  /v2/task/{task_id}:
    get:
      summary: Get the summary of a task.
      responses:
        '200':
          $ref: '#/components/responses/task_summary'
        '400':
          $ref: '#/components/responses/bad_request'
        '403':
          $ref: '#/components/responses/not_authorized'
      parameters:
        - $ref: '#/components/parameters/task_id'

components:

  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

  parameters:
    task_id:
      name: task_id
      in: path
      description: The unique identifier of the task targeted by the request.
      required: true
      schema:
        $ref: '#/components/schemas/TaskId'

  responses:

    task_summary:
      description: Summary of the task at the time the request was made.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/TaskSummary'

    bad_submit_task_request:
      description: |
        The request is invalid. This may indicate an error when parsing a parameter, or an error when parsing or validating the request body. The response body may contain a JSON array with a list of validation errors.
      content:
        application/json:
          schema:
            type: object
            properties:
              validation_errors:
                type: array
                minItems: 1
                items:
                  type: string

    not_authorized:
      description: |
        User is not authorized to perform this task. 

    bad_request:
      description: |
        The request is invalid. This may indicate an error when parsing a parameter.

  schemas:
  
    TaskId:
      type: string
      minLength: 1
      maxLength: 256
      pattern: "^[a-zA-Z0-9][a-zA-Z0-9-]*$"
      example: '80cf75f2-4700-4006-9203-4376b091ee4e'
      description: A unique identifier for a task. Must not be an empty string.

    TaskSummary:
      type: "object"
      description: Summary of existing task, including task status.
      properties:
        task_status:
          $ref: '#/components/schemas/TaskStatus'
      required:
        - task_status

    TaskStatus:
      type: string
      enum:
        - Created
        - PayloadProcessing
        - Scheduled
        - Completed
        - Cancelled
        - Failed
      description: |
        Reports status of the task. Lifecycle of a normal task is Created -> PayloadProcessing -> Scheduled -> Completed.
        where PayloadProcessing - the task is going trough additional compilation/validation/optimization, 
        Scheduled - the task is in the qpu queue, Completed - the task has been executed.

the code that gets generated here is:

def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
    if response.status_code == HTTPStatus.OK:
        return None
    if response.status_code == HTTPStatus.BAD_REQUEST:
        return None
    if response.status_code == HTTPStatus.FORBIDDEN:
        return None
    if client.raise_on_unexpected_status:
        raise errors.UnexpectedStatus(response.status_code, response.content)
    else:
        return None

which is not correct. The additional context shows the expected behavior.

Desktop (please complete the following information):

  • OS: macOS: 14.4.1
  • Python Version: 3.12.1
  • openapi-python-client: 0.21.5 [e.g. 0.1.0]

Additional context
Note if I modify the path:

  /v2/task/{task_id}:
    get:
      summary: Get the summary of a task.
      responses:
        '200':
          description: Summary of the task at the time the request was made.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TaskSummary'
        '400':
          $ref: '#/components/responses/bad_request'
        '403':
          $ref: '#/components/responses/not_authorized'
      parameters:
        - $ref: '#/components/parameters/task_id'

it generates the correct code:

def _parse_response(
    *, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Any, TaskSummary]]:
    if response.status_code == HTTPStatus.OK:
        response_200 = TaskSummary.from_dict(response.json())

        return response_200
    if response.status_code == HTTPStatus.BAD_REQUEST:
        response_400 = cast(Any, None)
        return response_400
    if response.status_code == HTTPStatus.FORBIDDEN:
        response_403 = cast(Any, None)
        return response_403
    if client.raise_on_unexpected_status:
        raise errors.UnexpectedStatus(response.status_code, response.content)
    else:
        return None

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Reproduza o cliente gerado usando a especificação OpenAPI fornecida, comparando o caminho de análise da resposta quando a resposta é definida inline em vez de por meio de um $ref. Rastreie o caminho de geração de código que constrói _parse_response; considera-se concluído quando a resposta 200 referenciada gera TaskSummary.from_dict(response.json()), enquanto os outros status mantêm o tratamento esperado.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
openapi, python
Domínio
api, tooling
Tipo de issue
Bug
Dificuldade
3/5
Tempo estimado
1-2 dias
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
48/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.