Summary
The generated request variants for array-root schemas contain a spurious empty BaseModel unioned with the list type. Affected files:
src/ucp_sdk/models/schemas/shopping/types/totals_create_request.py
src/ucp_sdk/models/schemas/shopping/types/totals_update_request.py
Each defines a *Request1 class that is an empty BaseModel (just model_config = ConfigDict(extra="allow")), and the top-level RootModel unions a list with this empty model. Flagged by Gemini on #28:
Root cause
ucp/source/schemas/shopping/types/totals.json is a clean root-level array schema ("type": "array", with items). The bug lives in preprocess_schemas.py::_create_single_variant (lines ~357-384), which unconditionally writes:
new_props = {}
new_required = []
for name, data in schema.get("properties", {}).items(): # empty for an array root
...
variant["properties"] = new_props # injects empty {}
variant["required"] = new_required # injects []
So the variant ends up with "type": "array", "items": {...}, plus "properties": {} and "required": []. datamodel-codegen interprets this as a schema satisfying both an array form and an object form, and emits RootModel[list[Item] | EmptyBaseModel] - exactly the *Request1 artifact Gemini flagged.
Secondary bug
Variant creation never recurses into items, so the nested ucp_request: "omit" marker on lines is silently lost - TotalsCreateRequestItem / TotalsUpdateRequestItem are functionally identical to Total, defeating the purpose of the variant.
Proposed fix
Patch _create_single_variant in preprocess_schemas.py:
- Guard the object-shape mutation. Only set
variant["properties"] / variant["required"] when the schema is object-shaped (type == "object" or already has properties). For array roots, leave them absent.
- Recurse into
items. When type == "array" and items is an object schema, run the same ucp_request filtering on items.properties (and on each allOf branch's properties, since totals uses allOf inside items).
Sketch:
def _apply_ucp_request_to_object(obj, op, file_path, variant_needs):
# filter properties + required in-place, pop ucp_request, rewrite refs
...
def _create_single_variant(schema, op, stem, file_path, variant_needs):
variant = copy.deepcopy(schema)
update_variant_identity(variant, op, stem)
rewrite_refs_to_variants(variant, op, file_path, variant_needs)
if variant.get("type") == "array" and isinstance(variant.get("items"), dict):
for node in iter_nodes(variant["items"]):
if isinstance(node, dict) and "properties" in node:
_apply_ucp_request_to_object(node, op, ...)
elif "properties" in variant or variant.get("type") == "object":
_apply_ucp_request_to_object(variant, op, ...)
return variant
This is a pipeline bug - the source schema is fine; post-processing the generated .py would be brittle.
Verification
After fix, regenerate and confirm:
- No
class TotalsCreateRequest1 / TotalsUpdateRequest1 in the output.
TotalsCreateRequestItem / TotalsUpdateRequestItem reflect the ucp_request: "omit" filtering on nested lines.
References
Summary
The generated request variants for array-root schemas contain a spurious empty
BaseModelunioned with the list type. Affected files:src/ucp_sdk/models/schemas/shopping/types/totals_create_request.pysrc/ucp_sdk/models/schemas/shopping/types/totals_update_request.pyEach defines a
*Request1class that is an emptyBaseModel(justmodel_config = ConfigDict(extra="allow")), and the top-levelRootModelunions a list with this empty model. Flagged by Gemini on #28:Root cause
ucp/source/schemas/shopping/types/totals.jsonis a clean root-level array schema ("type": "array", withitems). The bug lives inpreprocess_schemas.py::_create_single_variant(lines ~357-384), which unconditionally writes:So the variant ends up with
"type": "array","items": {...}, plus"properties": {}and"required": []. datamodel-codegen interprets this as a schema satisfying both an array form and an object form, and emitsRootModel[list[Item] | EmptyBaseModel]- exactly the*Request1artifact Gemini flagged.Secondary bug
Variant creation never recurses into
items, so the nesteducp_request: "omit"marker onlinesis silently lost -TotalsCreateRequestItem/TotalsUpdateRequestItemare functionally identical toTotal, defeating the purpose of the variant.Proposed fix
Patch
_create_single_variantinpreprocess_schemas.py:variant["properties"]/variant["required"]when the schema is object-shaped (type == "object"or already hasproperties). For array roots, leave them absent.items. Whentype == "array"anditemsis an object schema, run the sameucp_requestfiltering onitems.properties(and on eachallOfbranch'sproperties, since totals usesallOfinsideitems).Sketch:
This is a pipeline bug - the source schema is fine; post-processing the generated
.pywould be brittle.Verification
After fix, regenerate and confirm:
class TotalsCreateRequest1/TotalsUpdateRequest1in the output.TotalsCreateRequestItem/TotalsUpdateRequestItemreflect theucp_request: "omit"filtering on nestedlines.References