Skip to content

TypeParser.get_parser does not dispatch PEP 604 unions (X | None) — "Unsupported type", order-dependent via lru_cache #558

Description

@mgrbyte

Summary

TypeParser.get_parser (nemo_run/cli/cli_parser.py, v0.9.0) dispatches union annotations with:

elif origin is Union:
    return self.parse_union

but for PEP 604 unions (X | None, X | Y) get_origin(...) returns types.UnionType, not typing.Union, so the annotation falls through to "Unsupported type". Any CLI entrypoint annotated with modern union syntax (extraction: Extraction | None = None) fails to parse.

Reproduction

from nemo_run.cli.cli_parser import parse_value
parse_value("200", int | None)   # Unsupported type: int | None

Subtlety: order-dependent behaviour

get_parser is wrapped in @lru_cache(maxsize=128), and typing.Optional[X] == X | None (equal, equal hashes). So if Optional[int] is parsed first, its cached parser is returned for a later int | None — and the failure caches the same way. Symptom: the same annotation works or fails depending on which spelling any earlier code path parsed first, which makes this confusing to diagnose.

Workaround (public API)

import types
from nemo_run.cli.cli_parser import type_parser
type_parser.register_parser(types.UnionType)(type_parser.parse_union)

Suggested fix

elif origin is Union or origin is types.UnionType:
    return self.parse_union

Related minor finding

Enum-valued list annotations (list[SomeEnum]) are unsupported entirely; list[str] with in-factory conversion is the workaround. Happy to split that into a separate issue if preferred.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions