openapi-generators / openapi-generators/openapi-python-client
Incorrect generation of `_parse_response `
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
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- 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