<#630 fix: Handle list[Model], dict[str, Model] an...
# flyte-github
a
#630 fix: Handle list[Model], dict[str, Model] and Optional[Model] in nested type detection Pull request opened by andreahlert ## Motivation PR #426 added support for nested Pydantic/dataclass schema detection via
$ref
, but as noted in flyteorg/flyte#6887 (item 1), it does not handle
list
and
map
containers with nested models. When a schema contains
list[NestedModel]
,
dict[str, NestedModel]
, or
Optional[NestedModel]
, the
$ref
inside
items
,
additionalProperties
, or
anyOf
was not resolved, causing
KeyError
or incorrect type inference (falling back to
str
). ## Changes ### Centralized
$ref
resolution Instead of inlining
$ref
resolution at every call site, this PR follows the same approach as flytekit PR #3375:
_get_element_type
now accepts an optional
schema
parameter and resolves
$ref
centrally. This means any container type (
list
,
dict
,
Optional
, or nested combinations) automatically gets
$ref
support. ### New helper functions •
_resolve_ref
: Centralized
$ref
path resolution to schema definition •
_resolve_property_type
: Resolves a JSON schema property to a
(name, type)
tuple, handling
$ref
,
anyOf
, and all type variants •
_resolve_single_type
: Resolves the inner type of
Optional[T]
from the first
anyOf
element, properly handling
$ref
,
array
,
object
, and primitive types •
_resolve_typed_property
: Resolves a property with a known type string (array, object, primitives) •
_is_optional_anyof
: Validates that an
anyOf
truly represents
Optional[T]
(exactly 2 elements, second is
null
) instead of blindly assuming any
anyOf
with
$ref
is Optional ### Bug fixes •
Optional[T]
default values
: Fields not in the schema's
required
list now get
default=None
in the generated dataclass, so constructing with omitted optional fields works correctly •
Optional[List[Model]]
/
Optional[Dict[str, Model]]
: Previously would crash with
KeyError
because the code accessed
property_val["items"]
instead of
anyOf[0]["items"]
- now handled correctly via
_resolve_single_type
•
Union[TypeA, TypeB]
: Previously any
anyOf
with
$ref
was blindly wrapped in
Optional
- now properly validated • Optional field inclusion: Properties not in
required
are included in
property_order
so fields with defaults (like
Optional[X] = None
) are not skipped during schema traversal ###
__init__
wrapper Extended dict-to-object conversion to handle
list[dict]
->
list[Model]
and
dict[str, dict]
->
dict[str, Model]
. ## Tests Added
test_nested_lists_maps.py
with 10 test cases covering: •
list[NestedModel]
roundtrip (Pydantic + dataclass) •
dict[str, NestedModel]
roundtrip (Pydantic + dataclass) •
Optional[NestedModel]
with value and with
None
•
Optional[NestedModel]
omitted (default to
None
) • Mixed initialization (dict + object in same list) • Empty collections (
[]
,
{}
) All existing type engine tests pass with zero regressions. Ref: flyteorg/flyte#6887 flyteorg/flyte-sdk