May 27, 2026 · v0.2.3
Ten New Deterministic Transforms
Six Python and four TypeScript transforms, roughly doubling coverage, plus a pythonVersion key so version-gated rewrites can be opted in safely.
Added: Python
- super_no_args.
super(ClassName, self).method(...)becomessuper().method(...). Refuses sibling and parent class names and nested-class shadows to preserve MRO. - lru_cache_to_cache.
@functools.lru_cache(maxsize=None)becomes@functools.cacheon 3.9+; also rewrites thefrom functools importline. - pep585_generics.
typing.List,Dict,Tuple,Iterableand friends becomelist,dict,tuple,collections.abc.Iterableon 3.9+, or withfrom __future__ import annotations. Refuses files with Pydantic v1 orget_type_hintsto avoid runtime-eval crashes. - pep604_optional_union.
Optional[X]becomesX | None;Union[A, B]becomesA | Bon 3.10+, or withfrom __future__ import annotations. - datetime_utc_alias.
datetime.timezone.utcbecomesdatetime.UTCon 3.11+. No__future__override: UTC is a runtime attribute. - yield_from_for_loop.
for x in y: yield xbecomesyield from y. Refuses insideasync def, a CPython compile-stage SyntaxError that LibCST's parser does not catch.
Added: TypeScript
- indexof_to_includes.
arr.indexOf(x) !== -1and friends becomearr.includes(x). Type-aware via ts-morph for String, Array, and ReadonlyArray receivers. Gated on tsconfig target ES2016+. - object_assign_to_spread.
Object.assign({}, a, b)becomes{ ...a, ...b }. The first argument must be an object literal; refuses spread-element sources. Gated on target ES2018+. - string_concat_to_template_literal. String concatenation chains become template literals. Refuses
any,unknown, and non-primitive operands. Gated on target ES2015+. - vue_set_delete_to_assignment.
Vue.setandthis.$setbecome direct assignment;Vue.deleteandthis.$deletebecomedelete obj.k. Plain.jsand.tsonly:.vueSFC parsing is deferred to v0.4. Refusesdeletein expression context, and on Vue 2 codebases this is a semantic change.
Configuration
- pythonVersion. Pin the Python target version, 3.9, 3.11 and so on, for the four version-gated transforms. Auto-detected from pyproject.toml's
requires-pythonwhen unset; falls back to refusing version-gated transforms rather than guessing.
Changed
- Engine composition. Multi-transform composition is now order-stable: when several transforms touch the same file, each emits its own FileChange carrying the cumulative content, and the last one per path is what is written to disk. Fixes a silent-data-loss bug where only the last transform's rewrite survived under
run --apply.
