Black - The Uncompromising Formatter

Main point

Black’s goal is to make Python code look as good as written by a programmer who is rigorously following a style guide. It proved to be much better than any of its alternatives.

Make it your favorite formatter right now.

  • Black reformats entire files in place. It is not configurable! Thanks to that:

    • Blackened code will look the same regardless of the project you’re reading. Formatting becomes transparent after a while and you can focus on the content instead.
    • Black makes code review much, much faster! 🚀 It’s been proven empirically on every single project it was applied.
    • All in all, you will save time and mental energy for more important matters than formatting, while keeping your code straight, beautiful and readable.
  • It is recommended to include Black in your linting Invoke task and also to run it during pre-commit Git Hook. Example of both can be found in Big-Bang-py, see project.py and CI checks called by Git Hook.

  • To manage edge cases, disable Black per block:

    # fmt: off
    
    all_domains_dict_1 = {
        'valid-safe-foo-1.bar': {'impression': 1},
        'valid-safe-foo-2.bar': {'impression': 2},
    }
    
    all_domains_dict_2 = {
        'valid-safe-spam-3.eggs': {'impression': 3},
        'valid-safe-spam-4.eggs': {'impression': 4},
    }
    unsafe_domains_dict_2 = {
        'valid-unsafe-spam-1.eggs': {'impression': 5},
        'valid-unsafe-spam-2.eggs': {'impression': 6},
    }
    
    # fmt: on
    

YAPF - Google’s Alternative

  • The formatting style used by YAPF is configurable, where specific configuration can be pointed in a couple of ways.

    • It is recommended to store the configuration in a properly formatted .style.yapf file at the root of your project.
    • You may find pre-configured .style.yapf in Big-Bang-py.
  • It is recommended to include YAPF in your linting Invoke task and also to run it during pre-commit Git Hook. Example of both can be found in Big-Bang-py, see project.py and pre-commit.

  • To manage edge cases, disable YAPF:

    • per line:
    INTERVALS = (
        ('weeks',   60 * 60 * 24 * 7),
        ('days',    60 * 60 * 24),
        ('hours',   60 * 60),
        ('minutes', 60),
        ('seconds', 1),
    )  # yapf: disable
    
    • per block:
    # yapf: disable
    
    all_domains_dict_1 = {
        'valid-safe-foo-1.bar': {'impression': 1},
        'valid-safe-foo-2.bar': {'impression': 2},
    }
    
    all_domains_dict_2 = {
        'valid-safe-spam-3.eggs': {'impression': 3},
        'valid-safe-spam-4.eggs': {'impression': 4},
    }
    unsafe_domains_dict_2 = {
        'valid-unsafe-spam-1.eggs': {'impression': 5},
        'valid-unsafe-spam-2.eggs': {'impression': 6},
    }
    
    # yapf: enable
    
  • Survival tips:

    • If you leave trailing comma in a collection (be it a list, function parameters, etc.), YAPF will force it to break, giving one element per line.

    • YAPF is not perfect - from time to time you WILL see weirdly formatted code. There are at least two major occurrences:

      • Deeply Nested Dicts - this is quite understandable as decisions that improve readability are usually arbitrary and should be solved on a case-by-case basis.
      • Complex Comprehensions - comprehensions are split over multiple lines only when they exceed the column limit… This issue is brought to the attention of both YAPF authors (see issue on Github) and other programmers (see posts on Reddit) and Stack Overflow).