API Reference¶
When integrating µfmt into an existing toolchain or workflow, it is highly recommended to use the simple, or high-level, API whenever possible. It is designed to provide easy mechanisms for customizing configuration and post-processing file content, while handling the boring parts of formatting large codebases, like file discovery, reading or writing bytes from disk, or managing workers processes to optimize performance.
When in doubt, ufmt_paths()
should be the go-to method of using µfmt
within other tools.
Simple API¶
- ufmt.ufmt_paths(paths, *, dry_run=False, diff=False, return_content=False, ufmt_config_factory=None, black_config_factory=None, usort_config_factory=None, pre_processor=None, post_processor=None, concurrency=None, root=None)¶
Format one or more paths, recursively, ignoring any files excluded by configuration.
Uses trailrunner to first walk all paths, and then to run
ufmt_file()
on each matching file found. If more than one eligible file is discovered after walking the given paths, all files will be formatted using a process pool for improved performance and CPU utilization.Returns a generator yielding
Result
objects for each file formatted. Any errors that occur during formatting will be caught, and those exceptions will be attached to theResult.error
property of the result object. It is the responsibility of code calling this function to check for errors in results and handle or surface them appropriately.If the first given path is STDIN (
Path("-")
), then content will be formatted from STDIN usingufmt_stdin()
. Results will be printed to STDOUT. A second path argument may be given, which represents the original content’s true path name, and will be used when printing status messages, diffs, or errors. Any further path names will result in a runtime error.See
ufmt_file()
for details on parameters, config factories, and post processors. All parameters are passed through toufmt_file()
.Note
Factory and post processing functions must be pickleable when using
ufmt_paths()
.
- ufmt.ufmt_file(path, *, dry_run=False, diff=False, return_content=False, ufmt_config_factory=None, black_config_factory=None, usort_config_factory=None, pre_processor=None, post_processor=None, root=None)¶
Format a single file on disk, and returns a
Result
.Passing
dry_run = True
will only format the file in memory, without writing changes to disk. Passingdiff = True
will generate a unified diff of changes onResult.diff
. Passingreturn_content = True
will also populateResult.before
andResult.after
with the bytes content of the file from before and after formatting, respectively.Any errors that occur during formatting will be caught, and those exceptions will be attached to the
Result.error
property of the result object. It is the responsibility of code calling this function to check for errors in results and handle or surface them appropriately.Optionally takes
black_config_factory
orusort_config_factory
to override the default configuration detection for each respective tool. Factory functions must take apathlib.Path
object and return a validBlackConfig
orUsortConfig
object respectively.Optionally takes a pre- or post-processor matching the
Processor
protocol. If given, the pre-processor will be called with the original byte string content before it has been run through µsort or black. The return value of the pre-processor will be used in place of the original content when formatting. If given, the post processor will be called with the updated byte string content after it has been run through µsort and black. The return value of the post processor will replace the final return value ofufmt_bytes()
.Raising
ufmt.SkipFormatting
from a pre- or post-processor will result in “skipping” the file currently being formatted. The final contents will be unchanged, and theResult.skipped
attribute will be set with the string message from the skip exception, orTrue
if no message is given.
- class ufmt.Result(path, changed=False, written=False, skipped=False, diff=None, error=None, before=b'', after=b'')¶
Basic metadata results from formatting files.
- Parameters:
- class ufmt.UfmtConfig(project_root: Optional[pathlib.Path] = None, pyproject_path: Optional[pathlib.Path] = None, excludes: List[str] = <factory>, formatter: ufmt.types.Formatter = <Formatter.black: 'black'>, sorter: ufmt.types.Sorter = <Sorter.usort: 'usort'>)¶
- Parameters:
- ufmt.BlackConfig¶
alias of
Mode
- class ufmt.Processor(*args, **kwargs)¶
- class ufmt.SkipFormatting¶
Raise this exception in a pre/post processor to skip formatting a file.
Low-level API¶
- class ufmt.types.Formatter(value)¶
Select preferred formatter implementation.
- black = 'black'¶
Use black (default).
- class ufmt.types.Sorter(value)¶
Preferred import sorter implementation.
- ruff_api = 'ruff-api'¶
Experimental: Use Ruff’s isort lint rules via unofficial ruff-api extension.
Note
This implementation still depends on and uses the
[tool.usort]
configuration table frompyproject.toml
rather than Ruff’s own configuration options. This may change in future updates.
- skip = 'skip'¶
Skip sorting imports
- usort = 'usort'¶
Use µsort (default).
- ufmt.ufmt_bytes(path, content, *, encoding='utf-8', black_config, usort_config, ufmt_config=UfmtConfig(project_root=None, pyproject_path=None, excludes=[], formatter=<Formatter.black: 'black'>, sorter=<Sorter.usort: 'usort'>), pre_processor=None, post_processor=None)¶
Format arbitrary bytes for the given path.
Requires passing valid config objects for both black and µsort. If the given path represents a type stub (has a
.pyi
suffix), the black config object will be updated to setis_pyi = True
.This function will not catch any errors during formatting, except for “everything is fine” messages, like
black.NothingChanged
. All other errors must be handled by the code calling this function; seeufmt_file()
for example error handling.Optionally takes a pre- or post-processor matching the
Processor
protocol. If given, the pre-processor will be called with the original byte string content before it has been run through µsort or black. The return value of the pre-processor will be used in place of the original content when formatting. If given, the post processor will be called with the updated byte string content after it has been run through µsort and black. The return value of the post processor will replace the final return value ofufmt_bytes()
.Experimental: The optional
ufmt_config
parameter allows passing alternativeFormatter
andSorter
values, to choose formatting and sorting implementations instead of black and µsort. This should be passed by alternate frontends, and be based on the project’s configuration inpyproject.toml
. Optionally can be passed through fromufmt_file()
orufmt_paths()
asufmt_config_factory
.Note
Content will be decoded before passing to black, and re-encoded to bytes again. Be sure to pass a known-valid unicode encoding for the content.
Specifying the correct encoding is important! µfmt cannot do the right thing without the correct encoding if files contain PEP 263 coding lines, or byte values unrepresentable in UTF-8 (like
\ud800
).When in doubt, use :func:`ufmt_file` or :func:`ufmt_paths`.
ufmt.util.read_file()
can be used to both read bytes from disk, and make a best guess at file encodings. Otherwise, usetokenize.detect_encodings()
.
- ufmt.ufmt_stdin(path, *, dry_run=False, diff=False, return_content=False, ufmt_config_factory=None, black_config_factory=None, usort_config_factory=None, pre_processor=None, post_processor=None)¶
Wrapper around
ufmt_file()
for formatting content from STDIN.If given
dry_run = False
, the resulting formatted content will be printed to STDOUT. Diff content and changed status will be returned as part of theResult
object as normal.Requires passing a path that represents the filesystem location matching the contents to be formatted. Reads bytes from STDIN until EOF, writes the content to a temporary location on disk, and formats that file on disk using
ufmt_file()
. TheResult
object will be updated to match the location given bypath
.See
ufmt_file()
for details on parameters, config factories, and post processors. All parameters are passed through toufmt_file()
.
- ufmt.util.normalize_result(content, newline)¶
Convert bytes content with UNIX style line endings to the given style.
No-op if
newline
is given asb"\n"
.
- ufmt.util.read_file(path)¶
Read a file from disk, detect encoding, and normalize newlines.
Returns a tuple of file contents, file encoding, and original newline style. File contents are in bytes, with newlines normalized to UNIX style “n”. File encoding is detected either by PEP 263 coding line or encoding cookie. Newline is detected from the first line ending, and assumes that all lines in the file will have (or should have) consistent line endings.
Intended for use with
write_file()
, where newlines get converted back to the original newline style before being written to disk.
- ufmt.util.write_file(path, content, newline)¶
Write to a file on disk, normalizing to the given newline style.
Expects given content in bytes, with UNIX style line endings. UNIX style newlines will be converted to the given newline style before writing bytes to disk.
Intended for use with content and newline style from
read_file()
, so that newlines are correctly normalized back to their original style when writing to disk.