cog
63c65dfc - feat: support JSON-native union inputs (#3048)

Commit
30 days ago
feat: support JSON-native union inputs (#3048) * feat: support JSON-native union inputs Add support for union input types such as `str | float` and `str | float | None`. Unions are restricted to JSON-native members (str, int, float, bool, dict/Any, list[T], None) so request validation happens at the HTTP edge against the OpenAPI schema. Unions involving Path, File, Secret, custom coders, and BaseModel are rejected at build/schema-generation time, and output unions remain unsupported. - pkg/schema: add a recursive InputType model and resolver, emit OpenAPI anyOf for union inputs, and keep multi-variant nullable unions required when no default is supplied - pkg/predict: parse numeric CLI values for unions that accept a number (schemaAcceptsNumber), and fall back to a string member when a numeric parse fails for number-first unions like `float | str` (schemaAcceptsString) - python/cog/_adt: add deterministic union normalisation with strict per-member compatibility (bool not int/float, scalars not dict/Any, list unions validate elements) and anyOf json_type emission - tests: Go unit tests, Python regression tests, and end-to-end txtar integration tests for HTTP, CLI, and list unions - docs: document union inputs and nullable semantics * fix: correct CLI numeric parsing for integer-only and float unions Address two related bugs in CLI `-i` parsing of union inputs: - `int | float` resolves to the integer member first, so a fractional value like `1.5` failed ParseInt and errored instead of falling back to the float member. - `str | int` resolves to the string member, then the schemaAcceptsNumber branch parsed `1.5` as a float even though the union only accepts an integer, sending an invalid float. Add a schemaAcceptsFloat helper that matches number members but not integer-only members, and gate float parsing behind it in both the integer branch (with a float fallback) and the schemaAcceptsNumber branch. Add unit tests for `int | float` and `str | int` unions. * docs: clarify optional vs multi-variant union required behaviour The previous table conflated plain single-type optionals with multi-variant nullable unions. A plain Optional[T] / T | None is never placed in required, while a multi-variant union like A | B | None stays required unless a default is supplied. Split these into separate rows and add a runtime caveat: an optional needs a Python-level default (via = Input(...) or default=None) so an omitted value resolves to None; a bare Optional[T] annotation raises TypeError when omitted.
Author
Parents
Loading