Multi-body endpoints with required requestBody emit `| Unset` without importing `Unset`
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 72/100
Hướng nghiên cứu
Tái tạo client được tạo từ openapi.yaml được cung cấp, sau đó kiểm tra templates/endpoint_macros.py.jinja, parser/properties/protocol.py, parser/openapi.py và templates/endpoint_module.py.jinja. Theo dõi cách các đối số body bắt buộc cho nhiều body và các import được thu thập. Hoàn tất khi request body bắt buộc được tạo không có giá trị mặc định Unset không cần thiết, không có kiểu bị trùng lặp và ruff không báo cáo tên Unset chưa được định nghĩa.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Describe the bug
When an endpoint has a required requestBody with multiple content types, the generator appends | Unset = UNSET to the type annotation - even though the body is required.
Furthermore, Unset is not added to the imports, so the generated file references an undefined name - this causes ruff to report multiple instances of F821 Undefined name 'Unset'.
To Reproduce
Create openapi.yaml with the following spec:
openapi: 3.0.3
info:
title: Unset Bug Demo
version: 1.0.0
paths:
/items/{id}:
put:
operationId: updateItem
parameters:
- name: id
in: path
required: true
schema:
type: string
requestBody:
required: true # <-- must be true
content:
application/json: # <-- must have multiple content types
schema:
$ref: '#/components/schemas/Item'
multipart/form-data: # <-- must have multiple content types
schema:
$ref: '#/components/schemas/Item'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Item'
components:
schemas:
Item:
type: object
properties:
name:
type: string
Generate the client and lint:
# Tested on CachyOS with uv 0.11.21 and the following:
uvx --python 3.14 openapi-python-client==0.29.0 generate --path openapi.yaml --output-path out
uvx ruff==0.15.17 check out
Generated code snippet
In out/unset_bug_demo_client/api/default/update_item.py:
from ...types import UNSET, Response # <-- Unset is not imported
def _get_kwargs(
id: str,
*,
body: Item | Item | Unset = UNSET, # <-- F821: Undefined name 'Unset' (also note how Item is duplicated)
) -> dict[str, Any]:
...
Potential root cause (unverified)
The following was generated by an LLM and has not been verified!
I'm not really familiar with the codebase, but I might take a deeper look in the coming weeks if I find time and turn this into a proper fix/PR...
1. The template always appends
| Unset— even for required bodiesIn
templates/endpoint_macros.py.jinja, the multi-body branch of theargumentsmacro uses an uninitialized variable >body_required:{% elif endpoint.bodies | length > 1 %} body: {%- for body in endpoint.bodies -%}{% set body_required = body_required and body.prop.required %} {{ body.prop.get_type_string(no_optional=True) }} {% if not loop.last %} | {% endif %} {%- endfor -%}{% if not body_required %} | Unset = UNSET{% endif %} , {% endif %}
body_requiredis referenced before it is ever initialized. On the first loop iterationbody_requiredis JinjaUndefined, andUndefined and body.prop.requiredevaluates toUndefined(falsy). So it stays falsy for the whole loop, and after the loop{% if not body_required %}is alwaysTrue. Result:| Unset = UNSETis appended for every multi-body endpoint, regardless of whether the bodies are required. (It should have been seeded toTrue> before the loop so theandchain actually reflects "all bodies required".)2. The
Unsetimport is never added for required bodiesEach member is rendered with
get_type_string(no_optional=True), and the import set is driven byget_imports():# parser/properties/protocol.py def get_imports(self, *, prefix: str) -> set[str]: ... imports = set() if not self.required: imports.add(f"from {prefix}types import UNSET, Unset") return imports
Unset/UNSETare only imported when the property is not required. Endpoint imports are collected from exactly this > method:# parser/openapi.py result.bodies.append(body) result.relative_imports.update(body.prop.get_imports(prefix=models_relative_prefix))And the module's static imports include only
UNSET, neverUnset:# templates/endpoint_module.py.jinja from ...types import Response, UNSET
- Ngôn ngữ chính
- Python
- Star
- 2k
- Fork
- 293
- Merge trung bình
- 34 phút
- Pull request đã merge (30 ngày)
- 1
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của openapi-generators/openapi-python-client
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 52/100
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 64/100
openapi-generators/openapi-python-client#1435 · 1 bình luận ·
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
Tất cả issue của openapi-generators/openapi-python-client
Issue tương tự
-
triage/confirmed
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
agentscope-ai/agentscope#2775 ·
-
comp/desktop P3 type/bug
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 92/100
NousResearch/hermes-agent#118866 ·
-
bug
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
apache/cloudstack#14222 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100