Change Log

codesorter follows semantic versioning.

Unreleased

0.2.8 (2026/06/15)

Fixed

  • Keep a module-level assignment that calls a local definition after the names that call needs at runtime. APP = App() only references App syntactically, but instantiating it runs App.__init__, which may read a module-level function defined later in the file. Such an assignment was previously hoisted above that function and raised NameError at import. The runtime references reachable through a called class or function (transitively) are now treated as dependencies of the calling assignment.

  • Do not sort the keyword arguments of an OrderedDict call. OrderedDict(b=2, a=1) iterates in argument order and is a distinct value from OrderedDict(a=1, b=2), so reordering its keyword arguments changed the resulting object. Calls to OrderedDict (bare or dotted, such as collections.OrderedDict) are now left untouched.

0.2.7 (2026/06/15)

Fixed

  • Do not treat a class’s own attribute as a dependency on a same-named outer definition. An enum member or class variable named like the module constant that aliases it (for example CACHE_MISS = _Sentinel.CACHE_MISS beside class _Sentinel(Enum): CACHE_MISS = auto()) previously forged a false class -> constant edge that closed a cycle with the real constant -> class edge, hoisting the constant above the class it references and raising NameError at import. A name bound in a class’s own body is now recognized as belonging to that class’s namespace and imposes no ordering on outer definitions.

0.2.6 (2026/06/14)

Added

  • Documentation page describing how barriers limit sorting to segments between side-effecting statements, and how to relocate a statement that should not be a barrier.

Changed

  • Refresh the documentation: the installation instructions use uv-native commands, the class-method ordering reference and example now match the implementation, and the barrier relocation example is split into separate, color-tinted before and after blocks.

0.2.5 (2026/06/14)

Changed

  • Depend on ruff directly so the formatter is always installed alongside codesorter. The CLI shells out to ruff format, which previously only worked when ruff happened to be on PATH from another source; it is now a runtime dependency, so codesorter is self-contained in a clean environment and in the isolated pre-commit hook.

0.2.4 (2026/06/14)

Fixed

  • Never reorder a definition across a side-effecting statement. A bare statement such as sys.path.insert(0, str(REPO_ROOT)) is now a barrier, and sorting happens only within each segment between barriers, so a constant the statement uses is no longer hoisted after it (which raised NameError).

0.2.3 (2026/06/14)

Fixed

  • Keep an assignment that rebinds a name also bound by a sibling in its original position relative to that sibling. For example ten = cachedproperty(ten, ...) following def ten now stays after the method it wraps instead of being hoisted ahead of it (which raised NameError and changed which binding wins). Property getter/setter/deleter groups, which carry no assignment, are still ordered by their sort key.

0.2.2 (2026/06/14)

Changed

  • Format reordered files with ruff by default instead of black, so a downstream project no longer needs a .libcst.codemod.yaml to use the codesorter CLI or pre-commit hook. ruff must be importable on the PATH when sorting.

0.2.1 (2026/06/14)

Fixed

  • Treat a name used inside a module- or class-level comprehension as a real dependency. Such a comprehension runs eagerly when the definition executes, so an assignment like values = {key: build(key) for key in keys} now sorts after the build function it calls instead of ahead of it (which raised NameError). A comprehension inside a function body stays deferred and still imposes no ordering.

0.2.0 (2026/06/14)

Added

  • Sort module- and class-level assignments. Within every scope the order is now assignments, then classes, then functions/methods, so methods always follow nested classes and assignments are grouped at the top. Assignments are split into uppercase CONSTANTS first and then other variables; each group sorts with a leading underscore first (so __dunder__ and _private precede public names), and dependencies are respected (B = A + 1 stays after A). As a result, module-level functions now sort after module-level classes. The attribute order of enums, dataclasses, and NamedTuple/TypedDict classes is preserved; the base or decorator is resolved through QualifiedNameProvider so aliased imports (from enum import IntEnum as IE) are recognized.

  • Keep blank-line spacing with its position rather than the moved definition, so reordering no longer drags a blank line onto a different statement (for example the blank line after a class docstring stays at the top of the block). Comment lines that sit directly above a definition still travel with it.

  • Keep an augmented assignment anchored to the constant it augments, so __all__ += extra stays directly after __all__ = [...] instead of being left behind as a fixed barrier when another assignment sorts between them.

  • Sort keyword arguments in calls, keyword-only parameters in function definitions, and string keys in dict literals alphabetically. In a call, keyword arguments are sorted and ** unpackings moved to the end (positional arguments and * unpackings stay put), which is safe because a call raises TypeError on any duplicate keyword regardless of order. In a dict literal, ** spreads and non-string keys act as barriers so last-wins merge semantics are preserved.

Changed

  • Sort _-prefixed (private and dunder) names ahead of public names at every level rather than after capitalized names. A plain string sort placed _ after A-Z because of its higher code point; names are now ordered on a leading-underscore flag first so private definitions, methods, keyword arguments, and dict keys group together ahead of the public ones.

Fixed

  • Ignore a name used only in a lazy annotation (under from __future__ import annotations) when ordering definitions, since the annotation is never evaluated at runtime and imposes no real dependency. A forward reference in an annotation (for example nxt: list[Instr] where Instr is a type-alias union of classes defined later) previously forged a false dependency cycle that could hoist the runtime alias above the classes it unions and raise NameError.

  • Order definitions with a proper priority topological sort so a class or function is always placed after every sibling it depends on. The previous dependency heuristic compared per-node dependency vectors and could emit a dependent before its dependency (for example, Subreddit’s SubredditFlair was sorted ahead of the flair-template classes it instantiates).

0.1.0 (2026/06/14)

Added

  • Initial release of CodeSorter.

  • CLI interface with directory walking, sensible default excludes, .gitignore honoring, and -e/--exclude / --no-default-excludes / --no-gitignore flags.

  • Pre-commit hooks (codesorter and codesorter-check) for downstream consumers.

  • Comprehensive test suite covering function, method, property, fixture, decorator, and inheritance sort behaviors.

  • Example before/after files in examples/.