Preserve tuple item types in Python SDKs - #44
Conversation
|
👋 Hello @glenn-jocher, thank you for submitting a
For more guidance, please refer to our Contributing Guide. Don't hesitate to leave a comment if you have any questions. Thank you for contributing to Ultralytics! 🚀 |
UltralyticsAssistant
left a comment
There was a problem hiding this comment.
🔍 PR Review
Made with ❤️ by Ultralytics Actions
Reviewed the Python renderer, example schema, and response-model regression. The numeric regression is covered, but the new prefixItems handling is not semantically correct for unconstrained suffixes or schemas containing both prefixItems and items, and it loses named object models in tuple positions. Not LGTM.
💬 Posted 2 inline comments
- 💡 MEDIUM
lib/generators/python.ts:89This treatsprefixItemsas the complete element domain, but JSON Schema allows additional unconstrained elements whenitemsis absent; the addedshapeschema therefore permits[1, 2, "x"]while generatinglist[float]. When both keywords are present, this branch also drops the prefix types by selecting onlyitems. Combine the prefix types with theitemstype, or includeAnyfor an unconstrained suffix unlessmaxItemsproves the tuple is bounded. turn0search3 - 📝 LOW
lib/generators/python.ts:522For a valid tuple such astype: array, prefixItems: [{ "$ref": "#/components/schemas/Foo" }], this routes the item throughpythonArrayItemTypeand thenpythonType, which resolves object schemas todict[str, Any]. Unlike the existingitemspath, it never callsmodelType/addModel, so the generated SDK loses the referencedFooTypedDict. Keep prefix-item model references on the model-aware path when generating response models.
|
|
||
| function pythonArrayItemType(document: OpenApiDocument, schema: JsonSchema, collection = "list"): string { | ||
| const items = schema.items ? [schema.items] : (schema.prefixItems ?? []); | ||
| return [...new Set(items.map((item) => pythonType(document, item, collection)))].join(" | ") || "Any"; |
There was a problem hiding this comment.
💡 MEDIUM: This treats prefixItems as the complete element domain, but JSON Schema allows additional unconstrained elements when items is absent; the added shape schema therefore permits [1, 2, "x"] while generating list[float]. When both keywords are present, this branch also drops the prefix types by selecting only items. Combine the prefix types with the items type, or include Any for an unconstrained suffix unless maxItems proves the tuple is bounded. turn0search3
| const type = Array.isArray(schema.type) ? schema.type.find((item) => item !== "null") : schema.type; | ||
| if (type === "array") return result(`list[${modelType(schema.items, `${name}Item`)}]`); | ||
| if (type === "array") { | ||
| const itemType = schema.items ? modelType(schema.items, `${name}Item`) : pythonArrayItemType(document, schema); |
There was a problem hiding this comment.
📝 LOW: For a valid tuple such as type: array, prefixItems: [{ "$ref": "#/components/schemas/Foo" }], this routes the item through pythonArrayItemType and then pythonType, which resolves object schemas to dict[str, Any]. Unlike the existing items path, it never calls modelType/addModel, so the generated SDK loses the referenced Foo TypedDict. Keep prefix-item model references on the model-aware path when generating response models.
|
Closing in favor of the smaller contract-owner fix. The review correctly identified that generic prefixItems handling must account for unconstrained suffixes, combined items, and model-aware tuple members. Portal's affected shapes are homogeneous fixed-length arrays and will be represented precisely there instead. |
Summary
prefixItemswhenitemsis absentlist[...]output while deduplicating homogeneous tuple item typesWhy
SDK PR ultralytics/sdk#28 exposes valid tuple schemas for image and depth shapes. The Python renderer currently ignores
prefixItems, degrading those fields from numeric lists tolist[Any]. This fixes the generic renderer owner instead of patching generated SDK files.Validation
bun run lintbun run typecheckbun run knipbun run test(19 passed, 280 assertions)types.pychanges, reducinglist[Any]occurrences from 40 to 25🛠️ PR Summary
Made with ❤️ by Ultralytics Actions
🌟 Summary
Updated the Python SDK generator to derive array element types from OpenAPI
prefixItemswhenitemsis absent, preserving specific tuple-derived list types instead of generatinglist[Any].📊 Key Changes
itemswhen present.prefixItemsfor tuple schemas.Anywhen no item types are available.shapetuple schema.shapegenerates asNotRequired[list[float]].🎯 Purpose & Impact
Python SDKs now preserve usable element types for array fields defined with OpenAPI
prefixItems, reducing unnecessarylist[Any]output while keeping homogeneous tuple items represented as a single list type.