Transform ID:Documentation Index
Fetch the complete documentation index at: https://docs.refactron.dev/llms.txt
Use this file to discover all available pages before exploring further.
pep604_optional_union
Language: Python
What it does
Rewrites the verbosetyping.Optional[X] and typing.Union[A, B, …] annotations to the PEP 604 pipe syntax (X | None, A | B). Handles both the attribute form (typing.Optional[…]) and the bare form imported via from typing import Optional, Union. Collapses nested unions (Union[A, Union[B, C]] → A | B | C), unwraps single-arg unions (Union[A] → A), de-duplicates components, and moves None to the end for readability. The cleanup pass drops Optional / Union from from typing import … when no other references survive. Sidecar at src/transform/transforms/python/_py/pep604_optional_union.py.
Detector pattern
The detector atsrc/analyze/detectors/python/typing-optional-union.ts matches Subscript nodes whose value is Optional or Union — either bare (after from typing import …) or attribute-accessed (typing.Optional, <alias>.Union).
Preconditions
python_version_too_low— refuses when the resolved Python version is< 3.10and the file does not start withfrom __future__ import annotations. The pipe-union syntax (A | B) is a 3.10 runtime feature; under__future__.annotationsit is valid as an annotation on 3.7+.runtime_subscript_unsafe— refuses files that useisinstance(x, Union[int, str])on a< 3.10interpreter even with the__future__override.int | stris not a validisinstancearg on Python< 3.10.runtime_type_eval_unsafe— same conservative refusal aspep585_generics: Pydantic v1 ortyping.get_type_hintswithout__future__.annotations. Pydantic v1 evaluates annotations at runtime; the pipe-union form may fail on older interpreters.- Only bare (or no-op-aliased)
from typing import Optional, Unionbinds the canonical names we rewrite. Genuine renames are skipped.
Before / after
Edge cases NOT handled (skip via precondition)
- Pydantic v1 models or
get_type_hintsin the same file without__future__.annotations—runtime_type_eval_unsafe. - Runtime
isinstance(x, Union[...])on a< 3.10interpreter using the__future__override —runtime_subscript_unsafe. - Aliased imports (
from typing import Optional as Opt) — the alias rebinds the name; rewrite is skipped to avoidNameErrors. from typing import *— every target name is conservatively assumed in scope but no cleanup is performed.
The 3.10 cutoff is one minor version newer than
pep585_generics (3.9) because PEP 604’s pipe-union runtime semantics landed later. Annotations-only use under from __future__ import annotations works on 3.7+.