Skip to main content

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

Project description

flynt - string formatting converter

Build Status Coverage PyPI version 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!

Installation

pip install flynt. It requires Python version 3.6+.

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

flynt v.0.48

usage:  flynt [-h] [-v | -q] 
        [--no-multiline | -ll LINE_LENGTH] 
        [-tc] [-f] [-a] [-e EXCLUDE [EXCLUDE ...]] 
        src [src ...]

positional arguments:
  src                   source file(s) or directory

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         run with verbose output
  -q, --quiet           run without output
  --no-multiline        convert only single line expressions
  -ll LINE_LENGTH, --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.
  -tc, --transform-concats
                        Replace string concatenations (defined as + operations involving string literals) with f-strings. Available only if flynt is installed with 3.8+
                        interpreter.
  -f, --fail-on-change  Fail when changing files (for linting purposes)
  -a, --aggressive      Include conversions with potentially changed behavior.
  -e EXCLUDE [EXCLUDE ...], --exclude EXCLUDE [EXCLUDE ...]
                        ignore files with given strings in it's absolute path.

Sample output of a successful run:

38f9d3a65222:~ ikkamens$ git clone https://github.com/pallets/flask.git
Cloning into 'flask'...
...
Resolving deltas: 100% (12203/12203), done.

38f9d3a65222:open_source ikkamens$ flynt flask
Running flynt v.0.40

Flynt run has finished. Stats:

Execution time:                            0.789s
Files modified:                            21
Character count reduction:                 299 (0.06%)

Per expression type:
Old style (`%`) expressions attempted:     40/42 (95.2%)
`.format(...)` calls attempted:            26/33 (78.8%)
F-string expressions created:              48
Out of all attempted transforms, 7 resulted in errors.
To find out specific error messages, use --verbose flag.

_-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_._-_.
Please run your tests before commiting. Did flynt get a perfect conversion? give it a star at:
~ https://github.com/ikamensh/flynt ~
Thank you for using flynt. Upgrade more projects and recommend it to your colleagues!

38f9d3a65222:~ ikkamens$

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: local
     hooks:
         - id: flynt
           name: flynt
           entry: flynt
           args: [--fail-on-change]
           types: [python]
           language: python
           additional_dependencies:
               - flynt

This will run flynt on all modified files before commiting.

You can skip conversion of certain lines by adding # noqa [: anything else] flynt [anything else]

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

  • astor 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.

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-0.48.1.tar.gz (25.6 kB view details)

Uploaded Source

Built Distribution

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

flynt-0.48.1-py3-none-any.whl (30.2 kB view details)

Uploaded Python 3

File details

Details for the file flynt-0.48.1.tar.gz.

File metadata

  • Download URL: flynt-0.48.1.tar.gz
  • Upload date:
  • Size: 25.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.8.2

File hashes

Hashes for flynt-0.48.1.tar.gz
Algorithm Hash digest
SHA256 be3b1bff310983e121ecc5f1608b25ed5891b78a0ad2071499a003b2b6a12cae
MD5 4d2136fc3536255f695c39d9c75a54c8
BLAKE2b-256 64805bc2adfdf84bbf80bd2e06e49dc206a7a45a6aaaf8cacd983abeb755bbb1

See more details on using hashes here.

File details

Details for the file flynt-0.48.1-py3-none-any.whl.

File metadata

  • Download URL: flynt-0.48.1-py3-none-any.whl
  • Upload date:
  • Size: 30.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.8.2

File hashes

Hashes for flynt-0.48.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fecc26be43f3bc405d19cbfefcefc37b65a6f4ec8f9a8b0ec5c47387762fe3c6
MD5 22bbc7bc63abf0bafdadbcae06e6301e
BLAKE2b-256 90e481db9a999d2c6630fa2f03d907aabfbdd079e4767174e2e81776662f950c

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