* Emit a "$ref-based discriminated union" — a Python equivalent of the * polymorphic hierarchies that TS / Rust / .NET / Go produce for the same * schema shape. Given a definition like * * "PermissionRequest": { "anyOf": [ {"$ref": "#/.../PermissionRequestShell"}, ... ] } * * where every v
(
aliasName: string,
resolved: JSONSchema7,
ctx: PyCodegenCtx
)
| 1560 | * expected shape (caller falls back to other paths). |
| 1561 | */ |
| 1562 | function tryEmitPyRefBasedDiscriminatedUnion( |
| 1563 | aliasName: string, |
| 1564 | resolved: JSONSchema7, |
| 1565 | ctx: PyCodegenCtx |
| 1566 | ): PyResolvedType | undefined { |
| 1567 | const variants = (resolved.anyOf ?? resolved.oneOf) as JSONSchema7[] | undefined; |
| 1568 | if (!Array.isArray(variants) || variants.length < 2) return undefined; |
| 1569 | |
| 1570 | const variantRefNames: string[] = []; |
| 1571 | for (const v of variants) { |
| 1572 | if (!v || typeof v !== "object") return undefined; |
| 1573 | const ref = (v as JSONSchema7).$ref; |
| 1574 | if (typeof ref !== "string" || !ref.startsWith("#/definitions/")) { |
| 1575 | return undefined; |
| 1576 | } |
| 1577 | variantRefNames.push(refTypeName(ref, ctx.definitions)); |
| 1578 | } |
| 1579 | |
| 1580 | const resolvedVariants = variants.map( |
| 1581 | (v) => |
| 1582 | resolveObjectSchema(v, ctx.definitions) ?? |
| 1583 | resolveSchema(v, ctx.definitions) ?? |
| 1584 | (v as JSONSchema7) |
| 1585 | ); |
| 1586 | if (resolvedVariants.some((rv) => !rv || rv.properties === undefined)) { |
| 1587 | return undefined; |
| 1588 | } |
| 1589 | const discriminator = findPyDiscriminator(resolvedVariants as JSONSchema7[]); |
| 1590 | if (!discriminator) return undefined; |
| 1591 | |
| 1592 | const variantTypeNames: string[] = []; |
| 1593 | const dispatch: Array<{ value: string; typeName: string }> = []; |
| 1594 | for (let i = 0; i < variants.length; i++) { |
| 1595 | const variantTypeName = toPascalCase(variantRefNames[i]); |
| 1596 | const variantSchema = resolveObjectSchema(variants[i], ctx.definitions); |
| 1597 | if (variantSchema) { |
| 1598 | emitPyClass(variantTypeName, variantSchema, ctx, variantSchema.description); |
| 1599 | } |
| 1600 | variantTypeNames.push(variantTypeName); |
| 1601 | const discProp = resolvedVariants[i].properties?.[discriminator.property] as JSONSchema7; |
| 1602 | dispatch.push({ value: String(discProp.const), typeName: variantTypeName }); |
| 1603 | } |
| 1604 | |
| 1605 | if (!ctx.aliasesByName.has(aliasName)) { |
| 1606 | const lines: string[] = []; |
| 1607 | if (resolved.description) { |
| 1608 | lines.push(`# ${resolved.description}`); |
| 1609 | } |
| 1610 | lines.push(`${aliasName} = ${variantTypeNames.join(" | ")}`); |
| 1611 | ctx.aliasesByName.add(aliasName); |
| 1612 | ctx.aliases.push(lines.join("\n")); |
| 1613 | ctx.refBasedUnions.push({ |
| 1614 | aliasName, |
| 1615 | discriminatorProp: discriminator.property, |
| 1616 | dispatch, |
| 1617 | }); |
| 1618 | } |
| 1619 |
no test coverage detected
searching dependent graphs…