Metadata-Version: 2.5
Name: pyreorder
Version: 2026.09.6
Summary: AST-based Python module reorganizer
Project-URL: Homepage, https://jr2804.github.io/pyreorder/
Project-URL: Repository, https://github.com/jr2804/pyreorder
Project-URL: Issues, https://github.com/jr2804/pyreorder/issues
Project-URL: Changelog, https://github.com/jr2804/pyreorder/blob/main/CHANGELOG.md
Author-email: Jan Reimes <github@jan-reimes.de>
License: MIT
License-File: LICENSE
Keywords: ast,clean-code,cst,refactor,sort,sorting
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Code Generators
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: libcst>=1.1.0
Requires-Dist: typer>=0.12.0
Description-Content-Type: text/markdown

# pyreorder

[![status: beta](https://img.shields.io/badge/status-beta-yellow)](https://github.com/jr2804/pyreorder)
[![docs](https://img.shields.io/badge/docs-jr2804.github.io-blue)](https://jr2804.github.io/pyreorder/)
[![license: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
[![python](https://img.shields.io/badge/python-3.11+-blue)](https://www.python.org)

**AST-based Python module reorganizer.**

`pyreorder` reorders the top-level statements of a Python module into a canonical
section layout (imports → globals → constants → classes → functions → `main`)
and reorders the methods inside each class by visibility and type. It is built
on [`libcst`](https://github.com/Instagram/LibCST), so comments and formatting
are preserved.

It is a **module reorganizer**: it focuses on grouping and ordering
imports/globals/constants/classes/methods/etc. It does not integrate with
other sorting tools (isort, undersort, etc.) or provide ruff subcommands.

## Install

```shell
uv tool install pyreorder
pyreorder --version        # `rord` is installed as a short alias
```

## Quick start

```shell
pyreorder run src/                 # sort files in place
pyreorder check src/               # exit 1 if anything would change (CI / pre-commit)
pyreorder diff src/                # preview changes
pyreorder config generate          # write/print a pyreorder.toml template (--with-comments, --with-config)
```

A short alias `rord` is installed alongside `pyreorder`, so every command also
works as `rord run src/`, `rord check src/`, `rord diff src/`, and so on.

### Before → after

Given this module:

```python
import sys

def main():
    greet()

def greet():
    print("hi")

class Service:
    def _close(self):
        ...
    def start(self):
        ...

MAX_CONN = 10

if __name__ == "__main__":
    main()
```

`pyreorder run` (with `functions = "stepdown"`) produces:

```python
import sys

MAX_CONN = 10

class Service:
    def start(self):
        ...
    def _close(self):     # public methods first, then protected

def main():               # caller before callee (step-down rule)
    greet()

def greet():
    print("hi")

if __name__ == "__main__":
    main()
```

## Configuration

Discovered from (first wins, walking up from the target file): `--config`,
`pyreorder.toml`, `.config/pyreorder.toml`, `[tool.pyreorder]` in `pyproject.toml`.

```toml
[tool.pyreorder.module]
sections = [
    "imports", "typing_imports", "module_constants", "enums",
    "dataclasses", "classes", "functions", "dunder_exports", "main_block",
]

[tool.pyreorder.strategy]            # per-section; omit => "keep"
enums = "alpha"
functions = "stepdown"           # "alpha" | "stepdown" | "abstraction" | "keep"

[tool.pyreorder.class_methods]       # undersort-style ordering within each class
enabled = true
order = ["public", "protected", "private"]
method_type_order = ["instance", "class", "static"]

```

### Strategies

| value         | meaning                                          | applies to         |
| ------------- | ------------------------------------------------ | ------------------ |
| `keep`        | preserve original order (default)                | any section        |
| `alpha`       | alphabetical by primary name                     | imports, enums     |
| `stepdown`    | caller before callee (top-down narrative)        | functions, classes |
| `abstraction` | callee before caller (low-level utilities first) | functions, classes |

> **Caution:** `alpha` on `module_constants` / `classes` / `dataclasses` can
> break runtime order (interdependent constants, inheritance). Always preview
> with `pyreorder diff` first.

## Safety model

`pyreorder` is conservative by design:

- **Barriers** — statements that don't map to a configured section (runtime
  setup like `app = typer.Typer()`) are never moved. Recognised statements only
  reorder _within_ their contiguous barrier-free run, so pyreorder never moves code
  across a statement it might depend on.
- **Pinned** — the module docstring and `from __future__ import ...` always stay
  first.
- **Opt-out** — a `# pyreorder: off` (or `# nosort`) comment in a file's header
  skips the file; `class C:  # pyreorder: off` skips that class.
- **Idempotent** — running `pyreorder` twice never changes a file a second time.

## Programmatic API

```python
from pyreorder import sort_source, Config

cfg = Config(strategies={"functions": "stepdown"})
sorted_text = sort_source(source_text, cfg)
```

## Agent skill

An installable agent skill lives in [`skills/pyreorder`](skills/pyreorder).
Install it for your AI assistant:

```shell
bun x skills add https://github.com/jr2804/pyreorder.git -s pyreorder -a universal -y
```

## Documentation

Full documentation: **<https://jr2804.github.io/pyreorder/>** — architecture,
configuration reference, section layout, sorting modes, comparison with other
tools, ADRs, and the API reference.

Contributor setup, the check/test tasks, the docs build, pre-commit hooks, and
the release process are on the
[Development](https://jr2804.github.io/pyreorder/development/) page.

## Acknowledgements

The in-class method sorter is an adapted reimplementation of
[undersort](https://github.com/kivicode/undersort) (MIT). Dependency-aware
function ordering was inspired by [ssort](https://github.com/bwhmather/ssort),
[sdsort](https://github.com/eirikurt/sdsort) and
[ABSort](https://github.com/MapleCCC/ABSort). See
[Credits](https://github.com/jr2804/pyreorder/blob/main/docs/credits.md).

## License

MIT — see [LICENSE](LICENSE).
