CLI tool to convert a python project's %-formatted strings to f-strings.
Project description
flynt - string formatting converter
flynt is a command line tool to automatically convert a project's Python code from old "%-formatted" and .format(...) strings into Python 3.6+'s "f-strings".
F-Strings:
Not only are they more readable, more concise, and less prone to error than other ways of formatting, but they are also faster!
Installation
pip install flynt. It requires Python version 3.9+.
Usage
Flynt will modify the files it runs on. Add your project to version control system before using flynt.
To run: flynt {source_file_or_directory}
- Given a single file, it will 'f-stringify' it: replace all applicable string formatting in this file (file will be modified).
- Given a folder, it will search the folder recursively and f-stringify all the .py files it finds. It skips some hard-coded folder names:
blacklist = {'.tox', 'venv', 'site-packages', '.eggs'}.
It turns the code it runs on into Python 3.6+, since 3.6 is when "f-strings" were introduced.
Command line options
From the output of flynt -h:
usage: flynt [-h] [-v | -q] [--no-multiline | -ll LINE_LENGTH] [-d |
--stdout] [-s] [--no-tp] [--no-tf] [-tc] [-tj] [-f]
[-a] [-e EXCLUDE [EXCLUDE ...]] [-nb] [--version]
[--report]
[src ...]
flynt v.1.0.3
positional arguments:
src source file(s) or directory (or a single `-`
to read stdin and output to stdout)
options:
-h, --help show this help message and exit
-v, --verbose run with verbose output
-q, --quiet run without outputting statistics to stdout
--no-multiline convert only single line expressions
-ll, --line-length LINE_LENGTH
for expressions spanning multiple lines,
convert only if the resulting single line
will fit into the line length limit. Default
value is 88 characters.
-d, --dry-run Do not change the files in-place and print
the diff instead. Note that this must be
used in conjunction with '--fail-on-change'
when used for linting purposes.
--stdout Do not change the files in-place and print
the result instead. This argument implies
--quiet, i.e. no statistics are printed to
stdout, only the resulting code. It is
incompatible with --dry-run and --verbose.
-s, --string Interpret the input as a Python code snippet
and print the converted version. The snippet
must use single quotes or escaped double
quotes.
--no-tp, --no-transform-percent
Don't transform % formatting to f-strings
(default: do so)
--no-tf, --no-transform-format
Don't transform .format formatting to
f-strings (default: do so)
-tc, --transform-concats
Replace string concatenations (defined as +
operations involving string literals) with
f-strings. Available only if flynt is
installed with a 3.9+ interpreter.
-tj, --transform-joins
Replace static joins (where the joiner is a
string literal and the joinee is a static-
length list) with f-strings. Available only
if flynt is installed with a 3.9+
interpreter.
-f, --fail-on-change Fail when changing files (for linting
purposes)
-a, --aggressive Include conversions with potentially changed
behavior. Use -aa to omit int() wrapping for
%d conversions.
-e, --exclude EXCLUDE [EXCLUDE ...]
ignore files with given strings in it's
absolute path.
-nb, --notebook Also search and transform Jupyter notebooks
(.ipynb files). Warning: feature in alpha
and was not thoroughly tested.
--version Print the current version number and exit.
--report Show detailed conversion report
Sample output of a successful run:
$ git clone https://github.com/pallets/flask.git
Cloning into 'flask'...
...
Resolving deltas: 100% (12203/12203), done.
$ flynt flask
Running flynt v.1.0.3
Modified 21 of 70 files in 0.79s
$
Pre-commit hook
To make sure all formatted strings are always converted to f-strings, you can add flynt to your pre-commit hooks.
Add a new section to .pre-commit-config.yaml:
- repo: https://github.com/ikamensh/flynt/
rev: ''
hooks:
- id: flynt
This will run flynt on all modified files before committing.
You can skip conversion of certain lines by adding # noqa [: anything else] flynt [anything else] or # flynt: skip
Configuration files
Since v0.71 flynt can be configured using pyproject.toml file on a per-project basis.
Use same arguments as in CLI, and add them to [tool.flynt] section. CLI arguments takes precedence over the config file.
It can also be configured globally with a toml file located in ~/.config/flynt.toml on Unix / ~/.flynt.toml on Windows.
About
Read up on f-strings here:
After obsessively refactoring a project at work, and not even covering 50% of f-string candidates, I realized there was some place for automation. Also it was very interesting to work with ast module.
Dangers of conversion
It is not guaranteed that formatted strings will be exactly the same as before conversion.
'%s' % var is converted to f'{var}'. There is a case when this will behave different from the original - if var is a tuple of one element. In this case, %s displays the element, and f-string displays the tuple. Example:
foo = (1,)
print('%s' % foo) # prints '1'
print(f'{foo}') # prints '(1,)'
Furthermore, some arguments cause formatting of strings to throw exceptions. One example where f-strings are inconsistent with previous formatting is %d vs {:d} - new format no longer accepts floats. While most cases are covered by taking the formatting specifiers to the f-strings format, the precise exception behaviour might differ as well. Make sure you have sufficient test coverage.
Other Credits / Dependencies / Links
- Python's built-in
ast.unparseis used to turn the transformed AST back into code. - Thanks to folks from pyddf for their support, advice and participation during spring hackathon 2019, in particular Holger Hass, Farid Muradov, Charlie Clark.
- Logic finding the pyproject.toml and parsing it was partially copied from black
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flynt-1.0.6.tar.gz.
File metadata
- Download URL: flynt-1.0.6.tar.gz
- Upload date:
- Size: 25.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
471b7ff00756678e2912d4261dcbcd8fc1395129b66bf6977f88a3b3ad220c90
|
|
| MD5 |
ded781f40beff87eb93f79eb240cd2ea
|
|
| BLAKE2b-256 |
23eabe0bd620182b18af37cc784c6f0e1766246982084776702cd1b5649b6885
|
File details
Details for the file flynt-1.0.6-py3-none-any.whl.
File metadata
- Download URL: flynt-1.0.6-py3-none-any.whl
- Upload date:
- Size: 36.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e837c9597036b634a347855a89acf1483c4f8b73daa82c49372b10b6e1d1778
|
|
| MD5 |
9d147ffcdc9409498b434921e167673d
|
|
| BLAKE2b-256 |
d78014dc476cf6b6897a613f242beda253ba380f0e25d6355cb299e6b95f2aee
|