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.
pep585_generics
Language: Python
What it does
Rewrites the deprecated capitalised generics fromtyping to their built-in / collections.abc / re equivalents introduced in PEP 585. After the rewrite, the cleanup pass drops the now-unused names from any from typing import … line and adds collections.abc / re imports as needed.
The conversion set:
- Builtins:
List→list,Dict→dict,Tuple→tuple,Set→set,FrozenSet→frozenset,Type→type. collections:DefaultDict,OrderedDict,Counter,Deque,ChainMap→ attribute form (collections.defaultdict, etc.); the sidecar addsimport collectionsif needed.collections.abc:Mapping,Sequence,Iterable,Iterator,Awaitable,Callable,Generator,AsyncIterable,AsyncIterator,KeysView,ValuesView,ItemsView,MappingView,AbstractSet(→Set),MutableSet,MutableMapping,MutableSequence,Collection,Container,Hashable,Sized,Reversible,Coroutine.re:Pattern,Match.
Optional[X] and Union[A, B] are intentionally NOT touched — those are owned by pep604_optional_union. The sidecar lives at src/transform/transforms/python/_py/pep585_generics.py.
Detector pattern
The detector atsrc/analyze/detectors/python/typing-generic.ts flags Subscript nodes whose value is one of the recognised typing names — either via from typing import X or via typing.X / <alias>.X.
Preconditions
python_version_too_low— refuses when the resolved Python version is< 3.9and the file does not start withfrom __future__ import annotations. PEP 585 generics aren’t subscriptable on 3.8 at runtime; PEP 563’s__future__.annotationsdefers evaluation so the new syntax is legal as an annotation on 3.7+.runtime_subscript_unsafe— refuses when the__future__.annotationsoverride is the only thing carrying the file but the source usesisinstance(x, List[int])(or any other runtime subscript of a target name). The override covers annotations only — the rewrittenlist[int]wouldTypeErrorat runtime on< 3.9.runtime_type_eval_unsafe— refuses when the file imports Pydantic v1 (from pydantic import BaseModelwithout v2 markers) OR callstyping.get_type_hintswithoutfrom __future__ import annotations. Pydantic v1 evaluates annotations at runtime; the new generics may fail__class_getitem__on Python 3.9-3.10.- Only the bare (or no-op
as <same>) form offrom typing import Xbinds the canonical name we rewrite. Genuine renames are left untouched.
Before / after
collections.abc / re references:
Edge cases NOT handled (skip via precondition)
- Pydantic v1 models in the same file —
runtime_type_eval_unsaferefusal; Pydantic v1’s runtime annotation eval can fail on the new generics under 3.9 / 3.10. typing.get_type_hints(...)without__future__.annotations— same refusal, same reason.isinstance(x, List[int])on a< 3.9interpreter with the__future__override —runtime_subscript_unsafe. The rewrittenlist[int]is not a validisinstancearg on 3.8.- Aliased imports (
from typing import List as ListOf) — the alias rebinds the name; we don’t follow it. from typing import *— every canonical name is conservatively treated as in scope.
The
__future__ import annotations override lifts the version gate for annotations — but only for annotations. Anything that subscripts a typing name at runtime still needs Python 3.9. The runtime_subscript_unsafe precondition keeps this safe.