Skip to content

Configuration

Configuration

pyreorder is configured with a small TOML schema. The same schema is read from a standalone pyreorder.toml, a .config/pyreorder.toml, or a [tool.pyreorder] table in pyproject.toml. A minimal config needs no file at all — the defaults below already produce a canonical layout.

Discovery order

When pyreorder processes a file it searches for configuration, first match wins, walking up from the file's own directory:

  1. --config PATH passed on the command line (explicit path).
  2. pyreorder.toml in the current / target directory.
  3. .config/pyreorder.toml.
  4. [tool.pyreorder] table inside pyproject.toml.

If no configuration is found, built-in defaults are used.

Legacy [tool.undersort] / [undersort]

For backwards compatibility, class_methods.order and class_methods.method_type_order are read from a [tool.undersort] table (in pyproject.toml) or a top-level [undersort] table (in standalone configs) when [tool.pyreorder.class_methods] is absent. The enabled flag predates the legacy schema and is pyreorder-only. Prefer [tool.pyreorder].

Schema

Table Key Type / values
module sections ordered list of section names
strategy <section> keep | alpha | stepdown | abstraction
class_methods enabled bool
class_methods order permutation of public, protected, private
class_methods method_type_order permutation of instance, class, static
classification constants_pattern regex (default ^[A-Z_][A-Z0-9_]*$)
classification dunder_exports_names list of dunder names (default ["__all__"])

Any value of sections that is not a recognised section name acts as a barrier (see Section layout).

Examples

Minimal: defaults only

No file required. pyreorder uses the canonical section order and keep strategy everywhere except enums, which default to alpha.

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

[tool.pyreorder.strategy]
enums = "alpha"
# functions = "stepdown"   # caller before callee (top-down narrative)
# classes = "keep"

[tool.pyreorder.class_methods]
enabled = true
order = ["public", "protected", "private"]
method_type_order = ["instance", "class", "static"]

Per-section strategy overrides

Set a strategy only for the sections you care about. Omitted sections keep their original order (keep).

[tool.pyreorder.strategy]
enums = "alpha"
functions = "stepdown"
classes = "abstraction"

Customising constant detection

By default a top-level assignment is treated as a module constant when its target matches ^[A-Z_][A-Z0-9_]*$ (e.g. MAX_CONN, __version__). Change the pattern to widen or narrow it:

[tool.pyreorder.classification]
constants_pattern = "^[A-Z][A-Z0-9_]*$"

Dunder names like __all__ classify into a dedicated dunder_exports section that is placed after functions and before main_block. By default only __all__ is treated this way; extend the list to keep __version__, __author__, etc. near the bottom of the module too:

[tool.pyreorder.classification]
dunder_exports_names = ["__all__", "__version__", "__author__"]

Any dunder not listed here still classifies into module_constants.

Command-line overrides

Five flags let you deviate from the file config without editing it:

Flag Effect
--section-only Restrict reordering to the given comma-separated sections.
--strategy-overrides Override per-section strategy, e.g. functions=alpha.
--class-methods-order Override method visibility order, e.g. private,public,protected.
--method-type-order Override method-type order, e.g. static,instance,class.
--fail / --no-fail Control whether pyreorder run exits non-zero when files change (run only).

The order/type flags accept a permutation of public/protected/private or instance/class/static respectively; an invalid permutation warns and falls back to the configured order.

--fail / --no-fail (pyreorder run only) controls the exit code when files were modified. The default is controlled by [cli] fail_on_changed (see below); --no-fail is useful when running pyreorder from a formatter task that always writes and should not surface as a failure.

# Only reorder the functions section, using step-down ordering:
pyreorder run src/ --section-only functions --strategy-overrides functions=stepdown

# Restrict to several sections; each reorders independently:
pyreorder run src/ --section-only functions,classes --strategy-overrides functions=stepdown,classes=keep

# Reorder methods so private comes first, regardless of the file config:
pyreorder run src/ --class-methods-order private,protected,public

These map onto the corresponding Config fields and are resolved on top of the discovered file config.

[cli] table

[cli]
# Exit non-zero when `pyreorder run` modifies files (default: true).
# Pre-commit hooks and CI rely on this to detect drift. Override per-invocation
# with `--no-fail` (useful from formatter tasks that always write).
fail_on_changed = true

# Content-hash skip cache: avoids re-parsing already-sorted files.
# Default: on, stored in ~/.cache/pyreorder/<project-slug>/cache.json
# cache = true
# cache_dir = ".pyreorder-cache"  # override location (relative to cwd or absolute)

# Parallel file processing: 0 = serial, negative = auto (int(0.75*cpu_count())).
# Default: 0 (serial). Use --jobs/-j to override per-invocation.
# jobs = 0
# Parallel backend: "process" (multiprocessing) or "thread" (threading).
# Default: "process". Use --parallel-backend to override per-invocation.
# parallel_backend = "process"

The cache stores sha256(sorted_output) keyed by (config_signature, source_hash). On a repeat run, if the file's current content hash matches the cached sorted hash, the file is skipped entirely — no parse, no sort, no write. The cache is safe by construction: any edit changes the source hash and forces a full sort; any config or version change changes the signature and forces a full sort.

Disable per-invocation with --no-cache, or permanently with [cli] cache = false.

Parallel processing uses a process pool ("process") or thread pool ("thread"). The process pool is recommended for CPU-bound work (libcst parsing/sorting); the thread pool may be useful when I/O (file reads) is the bottleneck. Stdin mode always runs serially regardless of the jobs setting.

[discovery] table

Controls which files pyreorder scans when given a directory.

[discovery]
# Glob patterns to exclude (merged with --exclude flags on the command line).
exclude = ["vendor/**", "**/_generated.py"]
# Whether to descend into subdirectories (default: true).
# --no-recursive overrides this per-invocation.
recursive = true

exclude patterns are matched with :mod:fnmatch against both the full path and the file name; patterns from the config are combined with any --exclude flags (CLI patterns append, they do not replace).

Opt-out directives

  • Whole file: a # pyreorder: off (or # nosort) comment anywhere in the module header skips the file entirely.
  • Single class: class C: # pyreorder: off leaves that class's methods untouched.

Generating a config template

pyreorder config generate produces a pyreorder.toml template from the current config schema. Without options it prints the default template to stdout.

# Print the default template
pyreorder config generate

# Write it to a file (must end in .toml)
pyreorder config generate --output pyreorder.toml

# Add explanatory comments for each setting
pyreorder config generate --with-comments --output pyreorder.toml

# Merge values from an existing config (upgrade path for new versions):
# recognized keys are carried forward; unknown/deprecated keys are dropped
# with a warning on stderr.
pyreorder config generate --with-config old-pyreorder.toml --output pyreorder.toml

The schema is the single source of truth: generate only emits keys that the currently-installed pyreorder recognizes. This makes it the right tool for upgrading an old config when new options appear or old ones are removed.

Programmatic configuration

from pyreorder import Config, sort_source

cfg = Config(
    strategies={"functions": "stepdown", "enums": "alpha"},
    class_methods_enabled=True,
    class_methods_order=["public", "protected", "private"],
    class_methods_type_order=["instance", "class", "static"],
)
sorted_text = sort_source(source_text, cfg)

See the API reference for the full Config surface.