Skip to main content

CLI tool to convert a python project's %-formatted strings to f-strings.

Project description

A new tool: try kodo, open source agentic coding orchestrator.

flynt - string formatting converter

Actions Status License: MIT PyPI Downloads Code style: black

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!

flynt 2.0: now a native binary 🦀

Since 2.0, flynt is implemented in Rust and ships as a native executable in the PyPI wheel — same CLI and output as 1.x, 10–20× faster, with parallel file processing. The Python import API was removed (CLI-only); if you need import flynt, pin flynt<2. Details: CHANGELOG, RESULTS.md, DIVERGENCES.md.

Installation

pip install flynt (2.0 betas: pip install --pre flynt).

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.2.0.0-beta.1

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.
  -tj, --transform-joins
                        Replace static joins (where the joiner is a
                        string literal and the joinee is a static-
                        length list) with f-strings.
  -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: '1.0.6'
    hooks:
    -   id: flynt

This will run flynt on all modified files before committing.

Note (2.0 beta): keep rev: '1.0.6' for now. Pointing rev at a 2.0 checkout makes pre-commit build flynt from source, which requires a Rust toolchain. A wheel-backed hook (installing the prebuilt binary from PyPI) will ship with the final 2.0 release.

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.unparse is 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

flynt-2.0.0b1.tar.gz (197.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

flynt-2.0.0b1-py3-none-win_amd64.whl (1.4 MB view details)

Uploaded Python 3Windows x86-64

flynt-2.0.0b1-py3-none-musllinux_1_2_x86_64.whl (1.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

flynt-2.0.0b1-py3-none-musllinux_1_2_aarch64.whl (1.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

flynt-2.0.0b1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

flynt-2.0.0b1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

flynt-2.0.0b1-py3-none-macosx_11_0_arm64.whl (1.4 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

flynt-2.0.0b1-py3-none-macosx_10_12_x86_64.whl (1.4 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file flynt-2.0.0b1.tar.gz.

File metadata

  • Download URL: flynt-2.0.0b1.tar.gz
  • Upload date:
  • Size: 197.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for flynt-2.0.0b1.tar.gz
Algorithm Hash digest
SHA256 6714b9260b8900308c2cfdc1f3443162c3ee31e6dfedd0d985bfb825da6b37ce
MD5 ff5bdb666398595bda14a819d2c85ad9
BLAKE2b-256 68f705e49fb91d85d83d2af13604d74aa41c34ff08f0a39d0a98e980e47498c4

See more details on using hashes here.

File details

Details for the file flynt-2.0.0b1-py3-none-win_amd64.whl.

File metadata

  • Download URL: flynt-2.0.0b1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for flynt-2.0.0b1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 e2d6262fa524fa04427cd8fe683bfd056e98ea2730d78ed6a565719f70c23905
MD5 02ab3f7aa7fb84d150d1016883dbd348
BLAKE2b-256 2da9187d9dd2810a083c8ada62ccf7f20e20cebe574f39e244e354af8cfd9d69

See more details on using hashes here.

File details

Details for the file flynt-2.0.0b1-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for flynt-2.0.0b1-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 f2badda56565dd177518c5753b5027fbb3b19d78c9a5a26accfdc50899aea198
MD5 0b6d36a5f3bf88af7b051081fb2c0aa4
BLAKE2b-256 2c8620fc8da89a102d6d9a90518fcae74599285091a42d34a6683766dd502c4e

See more details on using hashes here.

File details

Details for the file flynt-2.0.0b1-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for flynt-2.0.0b1-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 179eb84506b34d561485f14a3297fc76525e2dcec041d00b206edc2df33032b2
MD5 9bbd47d236adc29f50f2eb35a7d563ba
BLAKE2b-256 1b489132c51966e90bcb7057d2747dd0e299e0b414b419c56206ba3b71cba231

See more details on using hashes here.

File details

Details for the file flynt-2.0.0b1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for flynt-2.0.0b1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0172ed8d40b9441ea62502e4075ca8ec4a73ac41cf1b493b7ec486dac6634f60
MD5 69027f544a1f73098241ea73de54f76e
BLAKE2b-256 5ae98813b8dfb6b7b054098ed2cfac8be1438414879848e05c7e40d3b2a59754

See more details on using hashes here.

File details

Details for the file flynt-2.0.0b1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for flynt-2.0.0b1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e0479d370b80b1e4f7e35c15000cb4cfbbcdc41e8f8aa2356182b5555aa28b3e
MD5 ca3d150e36d8b2f1186fbc118c310235
BLAKE2b-256 1c6342e96520f3fb610d2d32af4044fc6428155fde188b15368740ecd5c6a001

See more details on using hashes here.

File details

Details for the file flynt-2.0.0b1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for flynt-2.0.0b1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 665f0532a2a47d593f68d629646e6a8ed3261e35d3b4dd55a3b4a8f4f32c8af8
MD5 593c02e0a39fa500eef21b2083529931
BLAKE2b-256 954be9006a1be26ec0c385ed1bfac970b051f55bf2c6a1253845d7fce047233e

See more details on using hashes here.

File details

Details for the file flynt-2.0.0b1-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for flynt-2.0.0b1-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 983314f0e9eda77c3015e63d5aa978c6cb8b1c6d2cb9da1d253e749845f4f015
MD5 c23f7ee4e352ecff782bc00bdd58af05
BLAKE2b-256 35aed0476268fd99ebfbfb0de9cc4e6b5937d2d867ba07f8ea4d7839324d1074

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page