You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
_some_function__foo=0defsome_function():
# Indented intentionally for readabilityglobal_some_function__foo_some_function__foo+=1return_some_function__fooclassBar:
_some_method__bar=1@staticmethoddefsome_method():
# Indented intentionally for readabilityBar._some_method__bar<<4returnBar._some_method__bar
RemoveDummyAssignments (REQUIRES_IMPORT_RESOLVE)
Remove assignments to oneself (x = x, same binding on both side) or assignments to make the type checker happy (_ = some_method_w_return())
RemoveLiteralStatements
Remove expressions that are just a literal constant. CHANGED BEHAVIOR: Docstrings are no longer handled in this transform. (Moved to a separate transform)
RemoveDocstrings (REQUIRES_IMPORT_RESOLVE)
When True, remove docstrings that have not been preserved. The removal of module docstrings is determined by --also-modules.
REQUIRES_IMPORT_RESOLVE — due to the mark decorator
RemoveAnnotations (REQUIRES_IMPORT_RESOLVE)
Remove type annotations. CHANGED BEHAVIOR:
typing.Annotated will not be removed regardless of the option.
RemoveTypeStatements
Drop type X = ... (PEP695) type alias statements.
RemoveTypingClass (REQUIRES_IMPORT_RESOLVE)
Remove bare typing.Protocol-based classes (unless decorated with @typing.runtime_checkable) and typing.TypedDict-based classes (converted to dict)
RemoveGenerics (REQUIRES_IMPORT_RESOLVE)
Strip generic [T] type aliases (PEP695) from function/class definitions.
RemoveOverloads (REQUIRES_IMPORT_RESOLVE)
Drop @typing.overload-decorated stub defines. Always True when RemoveTypingDecorators is True.
RemoveDeadBlocks (runs after FoldConstants)
Collapse if <literal>: <body> and <body> if <literal> else <other> into just the taken branch.
ConvertEarlyExits
Invert the condition and/or inline if there's an escape keyword in the else or elif body.
Merge if <condition>: return a immediately followed by return b into return a if <condition> else b
ConvertDynamicAttributes (REQUIRES_IMPORT_RESOLVE)
Convert getattr/setattr call into bare access/assignment (getattr(obj, "name") → obj.name, setattr(obj, "name", value) → obj.name=value) name should be a constant literal and a valid keyword identifier.
Ignored when getattr is called with a default value (3-arg form).
ConvertToInline
Convert conditions with a single-statement body into inline conditions. (if cond: func(x) → cond and func(x), if foo: bar(); else: baz() → bar() if foo else baz())
ConvertToLambda
Convert functions with a single-return body into lambdas. (def func(...): return expr → func=lambda ...:expr)
CombineImports
Merges consecutive import statements where possible. from module import * is not handled.
OptimizeImports (REQUIRES_IMPORT_RESOLVE)
Remove imports that are not used or are no longer used by transform.
Module import optimization can be set to three modes via --optimize-module-imports:
always: if there's no __all__ or external reference (always optimize)
removed: if no longer used by transforms
False: always preserve
ConvertPass
Drop pass statements or convert to smallest expression (0).
ConvertPosArgs (INFLUENCES_MANGLING)
Remove positional-only parameter notation (PEP 570/).
Performed last since name mangling uses information about positional-only parameter.
RemoveDunderAll (INFLUENCES_MANGLING)
Drops the top-level __all__ assignment.
Experimental transforms
ConvertTypeImports
Rewrites from typing_extensions import ... to from typing import ... for a fixed set of symbols long-stable in typing, only when the name is on that list.
Rewrites from typing import <collections.abc re-exports> to from collections.abc import ..., same as above.
InlineFunctions
Completely remove the function marked with the @terser_hints.inline decorator, and inserts the body at the referenced location.
InlineIntFlags
Remove the enum.IntFlag declaration and replace it with a constant operation.
Implement every transforms planned in
src/terser/_pipeline/transforms/README.md.[TODO]Separateterser_hintspackage (usemonorepo)[TODO]Create a new example package to test transformsFlags:
REQUIRES_IMPORT_RESOLVE: Name resolving/binding must be performed first.REQUIRES_MODULE_RESOLVE: Module linking must be performed first.INFLUENCES_MANGLING: May affect the operation of name mangling; will performed after mangling.Transforms
Contracts(REQUIRES_IMPORT_RESOLVE)Apply contracts with syntax:
<function_def> -> <transform>. Similar to JetBrains' Code contract annotations.Default contracts:
typing.cast(_, value) -> value(e.g.,func_ = cast("Callable", func)→func_ = func)typing.assert_never(_) -> None(e.g.,assert_never(unreachable)→pass)typing.assert_type(value, _) -> value(e.g.,d = assert_type(obj, dict)→d=obj)terser_hints.not_none(value) -> value(e.g.,t = not_none(optional_t)→t=optional_t)InlineIIFE(REQUIRES_IMPORT_RESOLVE)Inline Immediately-Invoked Function Expressions (
@lambda _: _())Examples
Original:
Minified:
RemoveDummyAssignments(REQUIRES_IMPORT_RESOLVE)Remove assignments to oneself (
x = x, same binding on both side) or assignments to make the type checker happy (_ = some_method_w_return())RemoveLiteralStatementsRemove expressions that are just a literal constant.
CHANGED BEHAVIOR: Docstrings are no longer handled in this transform. (Moved to a separate transform)
RemoveDocstrings(REQUIRES_IMPORT_RESOLVE)When
True, remove docstrings that have not been preserved. The removal of module docstrings is determined by--also-modules.REQUIRES_IMPORT_RESOLVE— due to the mark decoratorRemoveAnnotations(REQUIRES_IMPORT_RESOLVE)Remove type annotations.
CHANGED BEHAVIOR:
typing.Annotatedwill not be removed regardless of the option.foo: "Foo") are always removed without evaluation.RemoveTypeStatementsDrop
type X = ...(PEP695) type alias statements.RemoveTypingClass(REQUIRES_IMPORT_RESOLVE)Remove bare
typing.Protocol-based classes (unless decorated with@typing.runtime_checkable) andtyping.TypedDict-based classes (converted todict)RemoveGenerics(REQUIRES_IMPORT_RESOLVE)Strip generic
[T]type aliases (PEP695) from function/class definitions.RemoveOverloads(REQUIRES_IMPORT_RESOLVE)Drop
@typing.overload-decorated stub defines. AlwaysTruewhenRemoveTypingDecoratorsisTrue.RemoveTypingDecorators(REQUIRES_IMPORT_RESOLVE)Strip
@typing.override,@typing.final.RemoveExplicitReturnNoneConvert
return Noneto barereturnand drops trailingreturn/return Nonefrom a function body.RemoveExplicitBaseClassRemove unnecessary base/meta classes. Currently only removes
objectfrom a class's bases.RemoveExceptionBrackets(REQUIRES_IMPORT_RESOLVE)Remove empty brackets from built-in exception constructors (
raise RuntimeError()→raise RuntimeError)CHANGED BEHAVIOR: now transform-based.
FoldConstantsFold constant by evaluating them.
UNIT_D = 60 * 60 * 24→UNIT_D=86400,INT_MAX_VALUE = 2 << 31 - 1→INT_MAX_VALUE=2147483647bool-identity comparisons:x == True/x is True→x,x == False/x is False→not x(wherex is not None)list()→[],dict()→{},tuple()→(),("some", "values")→"some","values",set((1, 2))→{1,2}RemoveDeadBlocks(runs afterFoldConstants)Collapse
if <literal>: <body>and<body> if <literal> else <other>into just the taken branch.ConvertEarlyExitselseorelifbody.if <condition>: return aimmediately followed byreturn bintoreturn a if <condition> else bConvertDynamicAttributes(REQUIRES_IMPORT_RESOLVE)Convert
getattr/setattrcall into bare access/assignment (getattr(obj, "name")→obj.name,setattr(obj, "name", value)→obj.name=value)nameshould be a constant literal and a valid keyword identifier.Ignored when
getattris called with a default value (3-arg form).ConvertToInlineConvert conditions with a single-statement body into inline conditions. (
if cond: func(x)→cond and func(x),if foo: bar(); else: baz()→bar() if foo else baz())ConvertToLambdaConvert functions with a single-return body into lambdas. (
def func(...): return expr→func=lambda ...:expr)CombineImportsMerges consecutive import statements where possible.
from module import *is not handled.OptimizeImports(REQUIRES_IMPORT_RESOLVE)Remove imports that are not used or are no longer used by transform.
Module import optimization can be set to three modes via
--optimize-module-imports:always: if there's no__all__or external reference (always optimize)removed: if no longer used by transformsFalse: always preserveConvertPassDrop
passstatements or convert to smallest expression (0).ConvertPosArgs(INFLUENCES_MANGLING)Remove positional-only parameter notation (PEP 570
/).Performed last since name mangling uses information about positional-only parameter.
RemoveDunderAll(INFLUENCES_MANGLING)Drops the top-level
__all__assignment.Experimental transforms
ConvertTypeImportsfrom typing_extensions import ...tofrom typing import ...for a fixed set of symbols long-stable intyping, only when the name is on that list.from typing import <collections.abc re-exports>tofrom collections.abc import ..., same as above.InlineFunctionsCompletely remove the function marked with the
@terser_hints.inlinedecorator, and inserts the body at the referenced location.InlineIntFlagsRemove the
enum.IntFlagdeclaration and replace it with a constant operation.