diff --git a/examples/openapi.json b/examples/openapi.json index 85263a3..5904a3e 100644 --- a/examples/openapi.json +++ b/examples/openapi.json @@ -43,6 +43,7 @@ "metadata": { "anyOf": [{ "type": "object", "properties": { "source": { "type": "string" } } }, { "type": "null" }] }, + "shape": { "type": "array", "prefixItems": [{ "type": "number" }, { "type": "number" }] }, "opaque": { "anyOf": [{}, { "type": "null" }] }, "exclusiveOpaque": { "oneOf": [{}, { "type": "string" }], "anyOf": [{}] } } diff --git a/lib/generators/python.test.ts b/lib/generators/python.test.ts index 9c344c6..a6df6ee 100644 --- a/lib/generators/python.test.ts +++ b/lib/generators/python.test.ts @@ -1223,6 +1223,7 @@ describe("Python generator", () => { expect(types).toContain('"widgetId": str'); expect(types).toContain('"displayName": str | None'); expect(types).toContain('"metadata": NotRequired[WidgetsRetrieveResponseValueMetadata | None]'); + expect(types).toContain('"shape": NotRequired[list[float]]'); expect(types).toContain('"opaque": NotRequired[Any]'); expect(types).toContain('"exclusiveOpaque": NotRequired[Any | str | None]'); expect(types).toContain("WidgetsRetrieveResponse = WidgetsRetrieveResponseValue | None"); diff --git a/lib/generators/python.ts b/lib/generators/python.ts index d2c2caf..13eb39f 100644 --- a/lib/generators/python.ts +++ b/lib/generators/python.ts @@ -84,6 +84,11 @@ function literalValues(document: OpenApiDocument, input: JsonSchema, depth = 0): return values.every((value) => value !== undefined) ? values.flatMap((value) => value ?? []) : undefined; } +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"; +} + function pythonType(document: OpenApiDocument, input: JsonSchema | undefined, collection = "list"): string { const schema = resolveSchema(document, input); if (!schema) return "Any"; @@ -115,7 +120,7 @@ function pythonType(document: OpenApiDocument, input: JsonSchema | undefined, co if (type === "integer") return result("int"); if (type === "number") return result("float"); if (type === "boolean") return result("bool"); - if (type === "array") return result(`${collection}[${pythonType(document, schema.items, collection)}]`); + if (type === "array") return result(`${collection}[${pythonArrayItemType(document, schema, collection)}]`); if (type === "object" || schema.properties) return result("dict[str, Any]"); return result("Any"); } @@ -513,7 +518,10 @@ function modelSource(document: OpenApiDocument, resources: Map 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); + return result(`list[${itemType}]`); + } if (type === "object" && typeof schema.additionalProperties === "object") { return result(`dict[str, ${modelType(schema.additionalProperties, `${name}Value`)}]`); }