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:
--config PATHpassed on the command line (explicit path).pyreorder.tomlin the current / target directory..config/pyreorder.toml.[tool.pyreorder]table insidepyproject.toml.
If no configuration is found, built-in defaults are used.
Legacy
[tool.undersort]/[undersort]¶For backwards compatibility,
class_methods.orderandclass_methods.method_type_orderare read from a[tool.undersort]table (inpyproject.toml) or a top-level[undersort]table (in standalone configs) when[tool.pyreorder.class_methods]is absent. Theenabledflag 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.
Recommended starting point¶
[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: offleaves 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.