#black-formatter

1 messages · Page 8 of 1

azure plank
dense jungle
azure plank
#

Should I make it as a standalone PR, or include it with the rest of the changes I'm making to the contributing basics page?

dense jungle
flat krakenBOT
#

Description

This PR contains some small improvements to the basics about contributing that I would have liked when making my first PR.
There are also a few small changes to make formatting more consistent/add clarity/make it flow better.
This also implements a workaround for a bug in MyST-Parser causing the Next PR Number query params to be rejected.

I'm not sure why in one part of the documentation it has (.venv)$ pip install -e ".[d]" while in another `(.venv)$ pip ins...

azure plank
#

It looks like whenever a new commit is merged to the main repo I get a diff-shades-comment workflow run failed for main branch notification, should I keep my PR branches synced to main even if the merged changes don't effect them, or just leave them be?

azure plank
#

While writing a comment on #4494 that I found while trying to fix #4495, I came across a question I couldn't find the answer to. Does black give any guarentees about formatting invalid code? If this was said somewhere in the docs, I didn't see it. If it isn't, it would probably be a good thing to add. The thing in question is that black still formats code with invalid f-strings in them pre-3.11, even though they are invalid when run, ie f"{'"'}". This is also an issue for any future f-string formatting things since for normalizing quote styles, what's possible is different between pre-3.12 and 3.12+.

dense jungle
#

If you look closely you'll find we still format some Python 2-only syntax 🙂

#

For the f-string situation, one thing to be careful about is to make it so that if the user's code still supports 3.11 or earlier, we don't format to a state that is valid only in 3.12+

azure plank
#

While trying to be exhaustive when re-writing the visible equals detection, I have found that f-strings are so much more cursed than I could have ever imagined. For example, this: "" f'{1:{""=}}'. And given stuff like this is also possible 3.12+ f'{1:{'{''=}'=}}' I'm not seeing how a single non-recursive regex could handle this. From how it looks to me it basically has to be a full f-string parser.

dense jungle
#

we produce a full parse tree, we just don't format it right now

drowsy jolt
#

strange thing with pre-commit-uv. in the CPython repo with macOS, first update Black to 24.10.0:

pre-commit autoupdate --repo https://github.com/psf/black-pre-commit-mirror

then install pre-commit-uv (with Python 3.13.0) and run:

pre-commit run --all-files black

and it shows:

Python 3.12.5 has a memory safety issue that can cause Black's AST safety checks to fail. Please upgrade to Python 3.12.6 or downgrade to Python 3.12.4

if I uninstall pre-commit-uv, it works okay. we do have language_version: python3.12 in the config, but I don't know where 3.12.5 is coming from. uv python list --only-installed tells me I have 3.12.7, which corresponds to my python3.12...

azure plank
# dense jungle we do have that already, right?

I think so, the business about list[Leaf], right? Are f-strings actually parsed different from strings at wherever trans.py takes place? Since most of the code I've been looking at in trans.py only interacts with the Leaf.value and manipulates it as a string, or does a Leaf.type == token.STRING.

dense jungle
late dewBOT
#

src/black/__init__.py line 547

if sys.version_info[:3] == (3, 12, 5):```
drowsy jolt
#

yep, Black is fine. it's because uv is picking 3.12.5:

$ rm -rf .venv && uv venv -p python3.12 -v
DEBUG uv 0.4.27 (36b729e92 2024-10-25)
DEBUG Searching for Python 3.12 in managed installations or system path
DEBUG Searching for managed installations at `/Users/hugo/.local/share/uv/python`
DEBUG Found managed installation `cpython-3.12.5-macos-aarch64-none`
DEBUG Found `cpython-3.12.5-macos-aarch64-none` at `/Users/hugo/.local/share/uv/python/cpython-3.12.5-macos-aarch64-none/bin/python3` (managed installations)
Using CPython 3.12.5
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate

uv python list --only-installed does in fact list both 3.12.5 and 3.12.7. I'm guessing I used uv to install a 3.12 in September when I was playing the new thing and it's been sitting dormant ready to strike: seems uv venv will prefer its own "managed installations", even if it's an older version than the one on my PATH

flat krakenBOT
#

Describe the bug

When running the test suite on a machine with high nproc (i.e. large number of CPUs/cores — we have 80 on arm64 and 256 on sparc), the test suite suddenly runs out of fds in middle of testing tests/test_blackd.py. The remaining blackd tests fail, then pytest hangs when it's supposed to exit.

To Reproduce

  1. Errr, get a system with high nproc… (perhaps some mocking will work?)
  2. tox -e py312-ci (xdist in non-CI jobs works around the problem)

**Expec...

solemn mantle
#

just want to say i fucking love using the black formatter. keep up the good work

flat krakenBOT
#

Hello,

I'd like your opinion on black's handling of the following case and what I think would be preferable

# Original
A = func([fooooooooooooooooooooooooooooooooooooooo for bar in baaaaaaaaaaaaaaaaaaaaaaaaaaaaaz])

# Current black
A = func(
    [
        fooooooooooooooooooooooooooooooooooooooo
        for bar in baaaaaaaaaaaaaaaaaaaaaaaaaaaaaz
    ]
)

# Preferred
A = func([
    fooooooooooooooooooooooooooooooooooooooo
    for bar in baaaaaaaaaaaaaaaaaaaaaaaaa...
azure plank
#

@dense jungle I've done the changes for the reviews you left on my PR, but I'm stuck on getting the code to format. The contributing docs say

# Format Black itself
(.venv) $tox -e run_self

But that just gives me the

Oh no! 💥 💔 💥
1 file would be reformatted, 63 files would be left unchanged.
message.
Is there some way to get it to actually do the formatting, instead of just saying it would reformat?

dense jungle
#

or temporarily edit the tox command so it doesn't --check

azure plank
#

@dense jungle New commits are up.
Also question: If I want to open an issue about the tests in the repo, what category should I do it under? Since it's more of a meta issue on the repo itself, it doesn't quite fit any of the existing issue categories.
/ should I open an issue at all? The main thing I want is with the test organization, since currently it is very painful to parse the output from a single test, or edit a test, and that is something I think I could tackle if it's wanted.

dense jungle
#

I think there's some "internals" label I can apply

flat krakenBOT
#

Part of #2238
While working on my first PR to the repo, I've noticed that interacting with the test cases is not easy.
This is because of how much is in each file, with the longest being ~1200 lines long. Because it's a test that uses # output, the input and output for a specific case are ~600 lines apart. This is made worse by the fact that formatting changes line counts, so getting back to the source isn't as easy as dividing the line number by 2. Running the test case also doesn't help...

azure plank
#

This is not the right channel/server. This server is for python related things, not PHP. Additionally, this channel is for discussing the Black formatter for python. If you want to give help on PHP, I would suggest finding PHP specific servers, instead of this one.

flat krakenBOT
#

Generally i've come to really love the black formatter, so first off thanks for that!

There is really only one thing I dont like about it which is that if the length of a line is reduced such that it could be put simply on one line, the nested format remains and leaves sometimes goofy looking artifacts.

I believe the black formatter would be better off it attempted to (perhaps via option) to first eliminate any line nesting or extra space then performed a format.

Example - a list com...

flat krakenBOT
flat krakenBOT
#

import random
import re
import time
import string
import sys
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from PyQt5.QtCore import QThread, pyqtSignal, QTimer
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QSpinBox, QLabel
from selenium.webdriver.support import expected_conditions as EC
import re
import sys
import...

silent knoll
flat krakenBOT
#

Describe the bug

There is a clash between the process of reflowing multi-line strings and the rule that prevents formatting lines with # type: ignore pragma at the end. Here is what happens:

  1. A multi-line string gets first merged into a single-line string which can be arbitrarily long.
  2. Because of the pragma comment at the end of the line, the line is considered unsafe to split. Hence the final result is a single huge line.

To Reproduce

Here is a simple exam...

civic remnant
#

I am using VsCode on windows but black formatter is not working correctly

#

also having trouble with jinja template.
They are formatting incorrectly when I save the code.

#

How to do that?

#

Can anybody help me with this?

civic remnant
#

I tried to follow the guide of black formatter

tame yew
#

It would be helpful if you can be specific about what you mean by “is not working correctly”. What are you expecting to happen, and what is happening instead that you don’t expect?

flat krakenBOT
#

Describe the bug

If there is a f-string (single-line or multi-line) following a # fmt: off (with or without a pairing # fmt: on) and both the f-string and # fmt: off are inside a pair of brackets ((), [], {}), the code cannot be formatted.

The error reported is something like:

error: cannot format ???.py: {' ', 'r', 'f', 'o', ':', 'm', 't', '#', '\n'} is NOT a subset of {'U', 'r', 'f', 'u', 'F', 'R', 'b', 'B'}.

To Reproduce

Sample:

flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
nimble hearth
#

<@&831776746206265384> spam account

glacial gate
#

!cban 696770552593121440 Ad spam

late dewBOT
#

:incoming_envelope: :ok_hand: applied ban to @worthy mica permanently.

chilly gazelle
#

Perfect

flat krakenBOT
flat krakenBOT
#

Describe the bug

Using # fmt: skip at the end of a line or # fmt: on/off for that matter does not change the output of black errors.

To Reproduce
python=3.11
pip install black=24.10.0

conf.py

try:
    import {{cookiecutter.repo_name}} # fmt: skip
except:
    raise ImportError("The package, {{cookiecutter.repo_name}}, has not been installed.") # fmt: skip

And run it with these arguments:

$ black --line-length=120 conf.py

The re...

flat krakenBOT
#

The problem

I'm always frustrated when formatting for a long if statement that involved in. So the if statement shall break with the "and", "or" keyword normally. However, if it is like a "key" in [array_item1, array_item2... ], it will break from the list and create a inconsistent layout with other if.

please think of every variable is with very long name
if a=b and c=d:
normally change to
if (
a=b
and c=d
):

but
if a=b and c in [d, e, f]:
it will change t...

flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Describe the bug
black hangs (or takes an extremely long time?) to process a file with a multiline f-string containing a bunch of escaped quotation marks.

To Reproduce
Run black against this file:

def testing():
    somevar = "some value"
    return f"""
        {somevar} the following line causes the issue:
         \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \" \...
azure plank
# flat kraken

I used pdb to find the cause of this, very cool to have a debugger built in. Might have been faster to open black in pycharm and use it's debugger, but my computer may have also exploded

flat krakenBOT
thick perch
#

hi,
should i be able to install black with pipenv install git+https://github.com/psf/black#egg=black?

i ask because when i try to use it, i get TypeError: unhashable type: 'list'
(full log in pastebin: https://paste.pythondiscord.com/UETA)

a repo that shows what i've tried: https://github.com/keepitsimpledev/python-exploration/tree/add-pipenv-then-black

update: the above issue occurs in windows/gitbash. i tried it again in WSL/ubuntu and no issues ¯_(ツ)_/¯
i suppose that solves it enough for me, but i'll leave this up for anyone interested in the future

tropic finch
#

I tried to add black to a CI job on GitLab. The problem is that when I run it locally, it says that 11 files would need to be modified, but on the CI job it says there are 88 such files. Why do two instances of black behave so different? If I cannot easily fix the files on my local computer to match the expectations on the CI machine, than the CI job becomes useless.

#

I checked and both versions are 24.10.0. The version of Python is slightly different (3.10 vs. 3.11), and OS is different as well.

dense jungle
dense jungle
tropic finch
#

How do I verify what configuration I'm using? I did not configure black in any way.

dense jungle
#

Run black -v

tropic finch
#

That does not work:

$ black -v
Usage: black [OPTIONS] SRC ...

One of 'SRC' or 'code' is required.
#

But black --version on CI says

$ black --version
black, 24.10.0 (compiled: yes)
Python (CPython) 3.10.15
tropic finch
#

I think the mystery was solved: black and isort were changing each other's result inside CI.

#

I found a configuration option to fix that.

flat krakenBOT
#

Refer to #4042 for 2024, #3407 for 2023, #4501 for some previous discussion

It's almost 2025, time to decide what Black's stable style will look like for next year. Any comments are welcome to help decide whether we should stabilize these changes.

My expectation is that we'll stabilize all of the features currently in the preview style, but not those in the unstable style. Here are the current preview rules, sorted in my estimate of most to least controversial:

hex_codes_in_unicod...

azure plank
# flat kraken

Was comfily reading this in bed, but had to get out of bed to test, and now open an issue in both black and ruff about the hex code case replacement

flat krakenBOT
brisk pawn
#

yo

#

what do you mean

flat krakenBOT
flat krakenBOT
radiant ravine
nova idol
#

hey guyss
im new here and would love to work with u all
can someone brief about it to me once..?

azure plank
# radiant ravine https://gist.github.com/hemanthkumar669/ca95c5fdadbd78803aa89a1677fa0398

This is the wrong channel for general python help, you should either ask in #python-discussion or open a post in #1035199133436354600
I would also recommend not asking people to write/improve your code for you. You'll get better results if you ask for help on specific problems you are having, and with the mindset of learning, not getting your issues magically solved. Also see the guide to asking good questions

azure plank
azure plank
# nova idol hey guyss im new here and would love to work with u all can someone brief about ...

I just noticed you opened a few PRs in the past. I have a few suggestions for you:

  1. Spell check/grammar check your posts. Posts that are easier to read will get more responses, and a better reception. This doesn't mean they have to be perfect, but PRs/issues that have a lot of spelling/grammar errors generally indicate the post is low quality.
  2. Ensure your change is a meaningful improvement. This means fixing something quantifiable, ie an open issue, documentation errors, etc.
  3. Give as much context as possible. Include things like the rationale behind your changes, the history of the issue, alternate considerations, etc.
flat krakenBOT
azure plank
#

@dense jungle I've been going back through old issues and have found a few that have been fixed, but I can't do anything besides say "this was fixed at some point". Would you like me to give a list of the issues I've found so far and/or ping you in the "this was fixed at some point" message?

dense jungle
#

And thanks for doing this!

azure plank
# dense jungle It's fine to just post on the issue, I will close them when I see the GitHub not...

Do you have a recommended way to go about that? I have two concerns:

  1. Test organization improvements #4506 hasn't reached a conclusion yet, so any new tests I add now will be more work in the future for whoever splits out the tests, and adding the tests in the first place is a big pain
  2. Since these are unlinked issues, I don't know what PR fixed them, so I can't easily minimize them. I don't think I ever mentioned it on 4506, but I'd also like to minimize the tests, since currently a lot of them are very verbose, which makes changing them in the event of intentional breakage more difficult. If I am going to go through all the tests, I figure I might as well minimize them while I'm there to make future things easier.
dense jungle
azure plank
# dense jungle I'd just stick with the current system of the tests. I'm not convinced the tests...

Ok, sounds reasonable. Then I guess the next question would be do I make a new file in cases for them, or put them into whichever case I feel they most match?
Also with #970 specifically, is there anything special I should do with it? My main concerns is that a solo \r usually doesn't play well with most editors, vscode turns it into a \n or \r\n, and I know git messes around with \n depending on the local user settings, so if it was set up like the normal cases it would be very easy to get accidentally messed up.

dense jungle
#

The \r case might be better with a test in test_black.py that passes that string to the parser directly, instead of a test case file handled by test_format

flat krakenBOT
azure plank
dense jungle
#

Separate

#

They won't need changelog entries, I'll add skip news when you make the PR

flat krakenBOT
flat krakenBOT
azure plank
#

:<test>

#

Huh, I wonder why the bot formats git log -L :<function_name>:<file_path> into git log -L ::

waxen wigeon
#

Hello, is there a way to configure the SRC from black's usage in my pyproject.toml rather than specifying it in the command ?

azure plank
waxen wigeon
azure plank
waxen wigeon
#

Actually that's for tox integration + git hook. But I'm finding specifying such arguments through configuration more elegant imho. But I've simply added SRC in the tox commands in the end.

flat krakenBOT
#

Describe the style change

We had a SEV happening inside of Meta because somebody forgot a , in a list declaration. So what happened is that python considered the two strings next to each other a string concatenation instead of raising an exception.

Examples in the current Black style

x = [
    "SuperLongStringSuperLongStringSuperLongString",
    "SuperLongStringSuperLongStringSuperLongString"   # missing ,
    "SuperLongStringSuperLongStringSuperLongStri...
flat krakenBOT
flat krakenBOT
#

Description

Added some additional clarification and example to the "Global" configuration file documentation.

I had some trouble when I was trying to do this myself because I misunderstood what was being said in this section. (Had thought you needed to make a .toml file inside a directory called black...)

Checklist - did you ...

  • [x] Add an entry in CHANGES.md if necessary?
  • [x] Add / update tests if necessary?
  • [x] Add new / update outdated documentation?
flat krakenBOT
#

Is your feature request related to a problem? Please describe.

I have noticed that when writing functions with generics, black splits the generics into more space. This is frustrating, as it makes it harder to read. Also, I feel it goes against black's philosophy, as black always tries to minimise space whenever possible.

For example, instead of writing a function like:

def foo[TypeA](
    input_a: TypeA,
    input_b: TypeA,
    input_c,
    input_d,
    input_e,
...
flat krakenBOT
flat krakenBOT
#

Describe the bug

Hi, # fmt: skip doesn't skip the formatting in this code:

def foo(): return "mock"  # fmt: skip
$ black foo.py; cat foo.py

Output:

def foo():
    return "mock"  # fmt: skip

Similar case in the [playground](https://black.vercel.app/?version=stable&state=_Td6WFoAAATm1rRGAgAhARYAAAB0L-Wj4AEpAJNdAD2IimZxl1N_WlXnON2nzN36C8EDS2OdozrF3A8N-yRxMzveJgvGD0d8QKTaox5vY_DvNkC0MxTYAIJP6wYvhPX_6e8_eA8axqa4Y00iUpSPgGJNJ0BXC0...

flat krakenBOT
silent knoll
#

is it just me or is diff-shades broken

#

src/blib2to3/pgen2/pgen.py:360: error: Argument 2 to "SyntaxError" has incompatible type "tuple[str | PathLike[str], int, int, str]"; expected "tuple[str | None, int | None, int | None, str | None]" [arg-type]

#

same error on the build workflow

flat krakenBOT
#

Description

Fixes a type error introduced in https://github.com/python/typeshed/pull/13141
As mentioned in that PR, it is a legitimate bug, however self.filename is never not a string at runtime
Regardless, the type error is currently causing CI to fail and needs to be resolved

Checklist - did you ...

  • [N/A] Add an entry in CHANGES.md if necessary?
  • [N/A] Add / update tests if necessary?
  • [N/A] Add new / update outdated documentation?
flat krakenBOT
#

Description

This fixes #3678. The fix is done by adding two new functions to node.py, is_tuple_containing_star and is_generator, which are then added to the checks in maybe_make_parens_invisible_in_atom inside linegen.py, which is used by the function remove_with_parens that Jelle suggested modifying in a comment on #3678

Both functions are based on the existing is_tuple_containing_walrus. That makes me fairly confident in is_tuple_containing_star, since it d...

flat krakenBOT
#

Description

This fixes #4232. This issue happening is different from what was stated. At least with the given bash script, black does correctly find and apply the settings from the pyproject.toml, the force exclude just doesn't get applied. This happens because the check for if formatting should be skipped when using stdin is constructed via

            root_relative_path = best_effort_relative_path(path, root).as_posix()
            root_relative_path = "/" + root_r...
azure plank
#

Huh, I wonder why 3678 got closed twice in a row

slow ibex
#

commit with message fix #XXXX auto-closes the issue XXXX
i guess jelle made two such commits somehow, which closed the issue twice

dense jungle
#

That's what you see in @slow ibex's screenshot above

bright glacier
#

Although IIRC y'all adjusted diff-shades' parallelisation so it may not benefit as the arm macOS runners seem to have 3 cores.

drowsy jolt
#

Good tip! Although many projects are on the Free plan so get max 20 concurrent jobs for Ubuntu+Windows, but only 5 for macOS, so the speed difference might not matter too much for projects with large macOS matrices.

https://docs.github.com/en/actions/administering-github-actions/usage-limits-billing-and-administration#usage-limits

GitHub has upgraded the pypa org to Enterprise, with 500 and 50 max concurrent, respectively. But worth looking into!

bright glacier
#

It's actually 1000 concurrent jobs / 50 concurrent macOS jobs

flat krakenBOT
#

Describe the bug

is_fstring_start using builtin.any for prefix matching is too slow and slows down fstring tokenization.

def is_fstring_start(token: str) -> bool:
    return builtins.any(token.startswith(prefix) for prefix in fstring_prefix) # using `any` with `` is too slow

To Reproduce

Run this minimal reproducing script:

import cProfile, pstats, io
from blib2to3.pgen2 import tokenize

profiler = cProfile.Profile()
example = io.StringIO(','...
flat krakenBOT
flat krakenBOT
#

Description: This PR addresses an issue with the handling of type comments in Black. Previously, type comments with multiple spaces after # were not recognized correctly, and formatting could lead to unnecessary whitespace.

Changes:
Fixed the handling of type comments by normalizing whitespace after # and : (e.g., converting # type: str to # type: str).
The function now trims extra spaces and ensures consistent formatting for type comments.
Added a check for comments starting with type:...

flat krakenBOT
#

Description:

This PR refactors the code to align with the feedback provided by @cobaltt7. Below are the key changes made:

Ensured Function Purity:

Refactored the function to ensure it remains pure by separating the modification logic into a different function.
The function now focuses solely on extracting the type annotation and avoids directly modifying any external state (e.g., leaf.value).
Integrated with Preview Style:

The modification logic has been moved to align with th...

silent knoll
#

..ok

buoyant anvil
#

Is there a way to stop block for multilining type vars


def toasycn[**P, R](fn: Callable[P, Generator[None, None, R]]) -> Callable[P, Coroutine[None, None, R]]:
    ...

it outputs

def toasycn[
    **P, R
](fn: Callable[P, Generator[None, None, R]]) -> Callable[
    P, Coroutine[None, None, R]
]: ...

I want it to output


def toasycn[**P, R](
    fn: Callable[P, Generator[None, None, R]]
) -> Callable[P, Coroutine[None, None, R]:
    ...
#

and yes, I added a trailing comma to the arguments and this was the mess it generated

def toasycn[
    **P, R
](
    fn: Callable[P, Generator[None, None, R]],
) -> Callable[
    P, Coroutine[None, None, R]
]: ...
young sand
flat krakenBOT
flat krakenBOT
azure plank
#

While working on a different issue, I of course stumbled across a rabbit-hole: ```ps
(.venv) PS C:...\black>py -c "'''rar''';print(repr(doc))"
'\na\n'
(.venv) PS C:...\black>black -c "'''rar''';print(repr(doc))" | py -
'a'

This comes from `is_multiline_string` in `nodes.py`, which does `return has_triple_quotes(leaf.value) and "\n" in leaf.value`. I'm not sure if this is an actual issue, since black's support for files that use just `\r` seems... tenuous at best. There are also a bunch more places that make this same assumption of a lone `\r` not existing.
flat krakenBOT
#

Description

I noticed these two things while looking through the coverage reports.

For the first change to fix_docstring, the only use I could find of it is behind a call to is_multiline_string. Since is_multiline_string is false if the string is empty, fix_docstring could never receive an empty string as an argument. I didn't closely analyze what fix_docstring does to see if it breaks if passed a single line string, but given how it is used I decided the easier fi...

azure plank
cyan quiver
#

black 24.10.0 formats this:

type AttachmentTuple = tuple[str, str | bytes] | tuple[str | None, str | bytes, str] | tuple[str, str | bytes, None]

Into this: (playground)

type AttachmentTuple = tuple[str, str | bytes] | tuple[
    str | None, str | bytes, str
] | tuple[str, str | bytes, None]

I think this is much more readable, which I can get by adding the parenthesis manually:

type AttachmentTuple = (
    tuple[str, str | bytes]
    | tuple[str | None, str | bytes, str]
    | tuple[str, str | bytes, None]
)

Is this the same issue as #4071, or should I open a new issue? In that issue, black is also eager to split the contents of [] across multiple lines instead of breaking the line at a point higher up in the AST.

azure plank
flat krakenBOT
flat krakenBOT
#

Hello! Thanks for submitting a PR. To help make things go a bit more
smoothly we would appreciate it if you could go through this template.

Description

Good things to put here include: reasoning for the change (please link
any relevant issues!), any noteworthy (or hacky) choices to be aware of,
or what the problem resolved here looked like ... we won't mind a ranty
story :)

Checklist - did you ...

  • [ ] Add an entry in CHANGES.md if necessa...
azure plank
#

I don't know how anyone manages to run a big OSS project, even just reading all these PRs is driving me insane.

azure plank
#

I'm specifically talking about #4542 #4543 #4545 and #4549. Like... do people not read anymore? Especially #4549, they commented on #4545, but seem to have not bothered reading the several paragraphs of advice I gave to the other person. >:(

neon loom
neon loom
#

FWIW … people don’t read for their job where they are paid to be a “professional” 🤪

bright glacier
#

IMO, I'd just close the PR saying that this looks AI generated and we can't accept it as it wholly misses the mark. I doubt they put much effort into the PR, you can simply return that lack of effort in your response /shrug.

#

You can be nice, but keep it concise and terse.

azure plank
#

I probably would do that, but I'm not a collaborator/maintainer so I'm limited to polite but sternly worded comments :)

floral palm
#

Somehow remembers me of north korean Cyberspies, but i'm not saying that it is

flat krakenBOT
flat krakenBOT
#

Describe the bug

I just installed into my PC (Ubuntu 24.01). It fails to load in the VsCode extension. When I run manually it is working.

To Reproduce

The resulting error is:

2025-01-10 11:39:29.096 [info] Global settings (client side): {
    "cwd": "/home/nerve",
    "workspace": "/home/nerve",
    "args": [
        "--line-length=240"
    ],
    "path": [
        "/usr/local/bin/black"
    ],
    "interpreter": [],
    "importStrategy": "useBundled"...
dense jungle
#

I just closed a couple of the worst ones

azure plank
#

I was very tired that night so I couldn’t stop myself from going on a mini rant

cyan quiver
silent knoll
red eagle
#

I probably would do that, but I'm not a collaborator/maintainer so I'm limited to polite but sternly worded comments 🙂

#

انا زهقت والله خلااااص حد ادمن يوثقني

#

اقصد يعني يعطيني رتبة اعرف اتكلم صوتي

#

عشان تعبتخ

#

تعبتتت

fallen trench
red eagle
#

i speak english fifty fifty

#

i am from egybt

#

i need tell in voice

flat krakenBOT
flat krakenBOT
azure plank
#

Going through old issues again, I came across https://github.com/psf/black/issues/236, the second oldest still open issue. The main complaint looks to have been fixed at some point, so I'd like to be able to say "it was fixed here, tests are here, closable". The issue I'm having is that I can't seem to do that. I looked through a good number of tests, but couldn't find one that had the exact structure from this issue. I tried to git bisect, but I couldn't get the first bisection commit from 2021 working. This also applies to a lot of other issues, where I'd like to bisect them to see when they got solved, but I either can't get black working from that far back, or running py src\black\__init__.py -c "code" never reproduces the issue. Does anyone else know of a way to run these older versions of black for bisection?

dense jungle
#

But if it's too much trouble, it's fine to just say that it works now, it doesn't matter that much exactly when it got fixed

azure plank
dense jungle
#

one principled way to do this could be to use the uv invocation that only installs dependencies older than some date, that should get you the right version of click

#

(don't remember the exact command)

azure plank
#

I'm still very not good with anything CI, so no clue, I would need a lot of handholding. I did have a different idea though, which is I should be able to at least bisect using the release binaries to narrow the search scope

young sand
azure plank
azure plank
#

Make that 4

#

Actually I'm not sure what to do with this. https://github.com/psf/black/issues/1187 The opening issue was fixed by 4010, but then as people commented it got turned from an issue with f(x=1 if y else 2) into running into issues with fluent-interface styles? to issues with what black does with inline comments. There still should be a test added for that original issue, but should the entire issue be closed?

flat krakenBOT
#

Description

Fixes the handling of # fmt: skip in one-liner functions. (#4535).

The fix involves modifying the algorithm that determines which nodes to ignore in the _generate_ignored_nodes_from_fmt_skip function. Specifically, the adjustment applies to cases where the # fmt: skip comment is not on the colon line of an if, while, def, class, etc.

Previous Algorithm

The previous algorithm for selecting ignored nodes worked as follows:

  1. Add the *previo...
silent knoll
#

What's the progress on v25.1? Is there anything I could help with getting an alpha released soon?

dense jungle
zenith ferry
#

Hello I am new member here trying to contribute my first open source, need the guidance.

#

Need the information about what this PROJECT is all about ? and how can I involve in there to contribute anything in my capacity ?
Can somebody explain or provide me document to review and study please.

azure plank
flat krakenBOT
#

Description

This PR addresses #4071 by improving how Black wraps function definitions that include generic type declarations.

Current Behavior

When a function with generic type declarations is formatted, Black prioritizes wrapping the generic type definitions, even in cases where splitting the arguments would result in a cleaner layout. For example:

Input:

def func[T](a: T, b: T,) -> T:
    return a

Cur...

flat krakenBOT
#

Describe the style change

When a "dot-chain" extends over the line length, black does different line breaks depending on a number of parameters that I don't fully understand, but I think include e.g.

  • Whether elements of the chain have brackets (i.e. We are choosing an element from a list or a map)
  • Whether the chain is standalone, or a function argument.
  • Possibly the target python version

Simply breaking before or after the dot seems very sensible, but black sometimes does this, so...

flat krakenBOT
#

Description

Docs CLI is now failing thanks to

The sphinx.configuration key is missing. This key is now required, see our blog post for more information.

It looks like black does the same thing as the .readthedocs.yaml example from that post, so I just copied it.

Checklist - did you ...

  • [x] Add an entry in CHANGES.md if necessary?
  • [x] Add / update...
flat krakenBOT
#

I have a .py file which runs as notebook

# Databricks notebook source
!pip install -U dspy python-dotenv
!pip install torchmetrics
dbutils.library.restartPython() 
# COMMAND ----------
from tqdm.notebook import tqdm
tqdm.pandas()
import logging
# COMMAND ----------
!pip install matplotlib seaborn

The above is python file which runs as notebook where each cell is defined by # COMMAND in databricks. When applying black formatting I want to skip the pip install related lines. I tried ...

flat krakenBOT
#

Describe the style change

When creating class or function definitions within an if-else statement, Black currently enforces empty newlines above and below the definition so that things look more readable. This generally works perfectly, but in certain circumstances, it can create a very odd looking if-else clause. In my experience, this specifically happens when the definition appears in the last block, while no definitions appear in the preceding block or blocks.

**Examples in the cu...

flat krakenBOT
azure plank
#

And make that 5 issues I've found that 4010 fixed

flat krakenBOT
drowsy jolt
late dewBOT
#

pyproject.toml lines 41 to 49

keywords = [
  "automation",
  "autopep8",
  "formatter",
  "gofmt",
  "pyfmt",
  "rustfmt",
  "yapf",
]```
flat krakenBOT
flat krakenBOT
flat krakenBOT
dense jungle
#

fun #21 1954.6 gcc: internal compiler error: Segmentation fault signal terminated program cc1 #21 1954.6 Please submit a full bug report, with preprocessed source (by using -freport-bug). #21 1954.6 See <file:///usr/share/doc/gcc-12/README.Bugs> for instructions. #21 1954.6 error: command '/usr/bin/gcc' failed with exit code 4

#

from our docker build

dense jungle
#

ok passed on retry

flat krakenBOT
dense jungle
#

urp all the macosx wheels failed ERROR InvalidDistribution: Invalid distribution metadata: license-expression introduced in metadata version 2.4, not 2.1

#

ah we have hardcoded hatchling==1.20.0 somewhere?

dense jungle
#

^ wheels are created only on pushes to main

dense jungle
#

ok I manually uploaded the macos wheels now

flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Describe the bug

There is a formatting difference depending on whether you have Python 3.10.15 installed but with the same version of Black (currently 25.1.0).

Under 3.10.15 this gets reformatted:

match args:
    case _ if ("test" in "testing" and True is True):
        print("YAY")

to this:

match args:
    case _ if "test" in "testing" and True is True:
        print("YAY")

Under 3.10.16 this reformatting doesn't occur and the parentheses remain in pla...

dense jungle
#

^ oh no what did we do

azure plank
#

I was going to try and repro this, but 3.10.15/16 don't have installers and thus I am too small brain to do anything

dense jungle
azure plank
#

(both locally with 3.13 and on the playground it removes the parens)

dense jungle
#

Building CPython from source is not entirely trivial but shouldn't be too hard, https://devguide.python.org/ is the best resource on how to do it

flat krakenBOT
#

Describe the style change

Strings should remain on separate lines if they end with “\n”. The newline has already the meaning of a line-break in a string. I think it would improve the readability if black uses this information to format strings.

Examples in the current Black style

a = "a=1\n" "b=2\n" "c=3\n"

Desired style

a = (
    "a=1\n"
    "b=2\n"
    "c=3\n"
)

Additional context

I'm the author of [inline-snapshot](https://github.com...

flat krakenBOT
#

This file:

class ModelError(Exception):
    "Models can raise this error, which will be displayed to the user"
    pass

When run through the latest Black is reformatted to look like this:

class ModelError(Exception):
    "Models can raise this error, which will be displayed to the user"

    pass

Here's a way to see that happen using uvx. With the previous Black version:

echo 'class ModelError(Exception):
    "Models can raise this error, which will be ...
flat krakenBOT
#

Description

This PR fixes the is_type_comment() function to correctly handle type comments with excessive whitespace. It normalizes spacing after # and :, ensuring that type comments are properly detected, even if they have extra spaces. This improves comment detection and prevents issues with misformatted type annotations.

Checklist - did you ...

  • [ ] Add an entry in CHANGES.md if necessary?
  • [ ] Add / update tests if necessary?
  • [ ] Add new / update outdated ...
flat krakenBOT
#

Hello, thank you for your contribution to Black! I have a few things that need addressed before this is ready to be merged.

  • Make sure you should read https://black.readthedocs.io/en/latest/contributing/the_basics.html . The next couple items of feedback all come from there, and it goes much more in-depth on exactly how and why to do things.
    • Since this is a user-facing change, you need to add a changelog entry
    • I'll admit I'm not familiar with this element of Black's formatting, so...
flat krakenBOT
flat krakenBOT
flat krakenBOT
mint barn
#

im good thank

meager pewter
#

Hey, i have a question.
Black recently got introduced to our workplace and i find the formatting a bit odd in some places and can't find an explanation as to why it is formatted the way it is, so i am hoping to get more infos here.

         or 'very long text ' not in element.get_attribute('aria-label'):
     return workday_handle_custom_fields_hook(element, dict, category, _)``` 

gets formatted to

``` if not element.get_attribute(
     'aria-label'
 ) or 'very long text' not in element.get_attribute('aria-label'):
     return False```

when i expected it to be


``` if (
 not element.get_attribute('aria-label') 
 or 'very long text' not in element.get_attribute('aria-label')
):
   return False``` 

Why is it going for the second option and not the third?
Is there a way to get the third option as a result by disabling a rule?
azure plank
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

From click 8.2.0 changelog:

Keep stdout and stderr streams independent in CliRunner. Always collect stderr output and never raise an exception. Add a new output stream to simulate what the user sees in its terminal. Removes the mix_stderr parameter in CliRunner. [:issue:`2522`](https://github.com/pallets/click/blob/main/CHANGES.rst#id27) [:pr:`2523`](https://github.com/pallets/click/blob/main/CHANGES.rst#id29)

so mix_stderr=False throws an error and is redundant.

flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Description

Issue #3623 appears to be resolved, added regression tests to monitor this formatting issue and track any potential recurrence.

Regression tests were created based on Black's current stable version (25.1.0) formatting results, see [Black Playground](https://black.vercel.app/?version=stable&state=_Td6WFoAAATm1rRGAgAhARYAAAB0L-Wj4AQTANldAD2IimZxl1N_Wg0-A00Q7AStP7a3q0sqVQPWdY1xadXvajUNDqf4hsar9JsSEjvUIkO86voFmeTFwICDsImuEkAIHQ_jOFRyFZO2d_RDtELcNHSgMoIla6f1d7fosYp-0UUDHqBX...

flat krakenBOT
#

Describe the style change

Current black format the slice notation just after a multiline string literal over multiple lines, but that's unnecessary when the line containing closing triple quote is short.

Examples in the current Black style

s = """
lorem ipsum dolor sit amet
consectetur adipiscing elit
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua
ut enim ad minim veniam
quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo
conse...
flat krakenBOT
#

Describe the bug

When running the test suite on PyPy3.11 7.3.18, I'm seeing two test failures:

========================================================= test session starts =========================================================
platform linux -- Python 3.11.11[pypy-7.3.18-final], pytest-8.3.4, pluggy-1.5.0
cachedir: .tox/pypy311/.pytest_cache
rootdir: /tmp/black
configfile: pyproject.toml
plugins: cov-6.0.0, xdist-3.6.1
12 workers [386 items]   ipped                          ...
flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Beterbiev vs Bivol 2 live stream: How to watch boxing online today – start time, TV channel, full fight card. Artur Beterbiev vs Dmitry Bivol 2 – aka The Last Crescendo – for the undisputed world light heavyweight title isn't only one of the best pound-for-pound fights of 2025, it's got arguably the highest-quality card this century. Beterbiev won a razor-thin decision when these two met in October, as Bivol seeks revenge

The epic rematch in the light heavyweight division is ready to get und...

#

Beterbiev vs Bivol 2 live stream: How to watch boxing online today – start time, TV channel, full fight card. Artur Beterbiev vs Dmitry Bivol 2 – aka The Last Crescendo – for the undisputed world light heavyweight title isn't only one of the best pound-for-pound fights of 2025, it's got arguably the highest-quality card this century. Beterbiev won a razor-thin decision when these two met in October, as Bivol seeks revenge

The epic rematch in the light heavyweight division is ready to get und...

late dewBOT
#

:incoming_envelope: :ok_hand: applied timeout to @jade lintel until <t:1740316112:f> (10 minutes) (reason: duplicates spam - sent 4 duplicate messages).

The <@&831776746206265384> have been alerted for review.

flat krakenBOT
#

Describe the bug

Black errs on format string while Python runs the code without error.

To Reproduce

x = "test"

if f"{x}:\\":y = f'{x}'; print(y)

And run it with these arguments:

$ black test.py --target-version py310

The resulting error is:

error: cannot format test.py: Cannot parse for target version Python 3.10: 3:22: EOF in multi-line string

Expected behavior

The same code but formatted. Python does accept this input and will print y.

**...

flat krakenBOT
#

any reason you didn't migrate to Trusted Publishing? It can produce digital attestations out of the box now: https://blog.pypi.org/posts/2024-11-14-pypi-now-supports-digital-attestations/.

_Originally posted by @webknjaz in https://github.com/psf/black/issues/4512#issuecomment-2483427381_

          We should move to Trusted Publishing at some point, but that's a bit more work, so we'll do it when we do it I suppose. I'd probably accept a PR that does it f...
flat krakenBOT
#

Describe the style change

black version: 25.1.0

Currently this example could not be formatted at all if line length is set to 80.

Examples in the current Black style

class Foobar:
    def method(self, foobar_long_dictionary: dict):
        return [
            (foobar_long_key, foobar_long_value)
            for foobar_long_key, foobar_long_value in foobar_long_dictionary.items()
        ]

Desired style

class Foobar:
    def method(self, fooba...
flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

The wildcard at the beginning used to match tags with arbitrary prefixes otherwise. This patch corrects that, making it more accurate.

It's a follow-up to #4592. The docs provide a very generic example of the .git_archival.txt template file, suggesting that it's tailored per project needs later [1]:

Feel free to alter the match field in describe-name to match your project's tagging style.

flat krakenBOT
#

Describe the bug

In some cases the current black version (25.1.0) reformats a string that is too long. Also the behaviour differs between not specifying a line length and specifying the default length of 88 chars.

To Reproduce

class A:
    def foo(self):
        return (
            "This is a very loooooooooooooooooooooooooooooooooooooooooooooong string"
        )

Note: The long line is exactly 86 chars wide. The bug does not occur when I add one character.

$...
flat krakenBOT
#

Describe the bug

Using pre-commit in Django and want to exclude the migrations directory and all files of it from formatting because these are auto-generated files by Django. Tried with exclude, extend-exclude, and force-exclude but none of them seems to be working as expected
To Reproduce

repos:
  - repo: https://github.com/psf/black
    rev: 25.1.0  # Use the latest stable version
    hooks:
      - id: black
        language_version: python3
        exclude: |
...
flat krakenBOT
dense jungle
#

oh it's because the stable branch didn't get updated because of wheel shenanigans. just updated it manually

flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Describe the bug

The following code can not be parsed/formatted by black:

class name_5[name_4: lambda: something]:
     pass
❯ black -t py312 bug.py
error: cannot format bug.py: Cannot parse for target version Python 3.12: 1:21: class name_5[name_4: lambda: something]:

Oh no! 💥 💔 💥
1 file failed to reformat.

but it can be parsed by cpython.

python3.12 scripts/min_code.py

Environment

  • Black's version: current main (00c0d6d91ae3dc31894fadd37968e...
flat krakenBOT
#

Describe the bug

The following code can not be parsed/formatted by black:

{name_4: name_1 for name_2 in something if f'\\' if {}}
❯ .venv/bin/black -t py312 scripts/min_code.py
error: cannot format scripts/min_code.py: Cannot parse for target version Python 3.12: 1:53: {name_4: name_1 for name_2 in something if f'\\' if {}}

Oh no! 💥 💔 💥
1 file failed to reformat.

but it can be parsed by cpython.

❯ python3.12 scripts/min_code.py
Traceback (most recent call ...
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Describe the bug

Black unexpectedly changes binary content as per the example below.

└➜ cat main.py
invalid_binary_char = b"\xFEFEF"
└➜ black --check --verbose --diff ./main.py
Identified `/` as project root containing a file system root.
Found input source: "main.py"
--- main.py     2025-03-04 04:21:22.184368+00:00
+++ main.py     2025-03-04 04:22:25.247730+00:00
@@ -1 +1 @@
-invalid_binary_char = b"\xFEFEF"
+invalid_binary_char = b"\xfeFEF"
would reformat main.py

Oh no! 💥 💔 💥
1 f...
tough gazelle
#

Hello

grave compass
#

Hello

flat krakenBOT
#

Description

"dependency-groups" is the mechanism for storing package requirements in pyproject.toml, recommended for formatting tools (see https://packaging.python.org/en/latest/specifications/dependency-groups/ )

this change allow the black action to look also in those locations when determining the version of black to install

Checklist - did you ...

  • [ ] Add an entry in CHANGES.md if necessary?
  • [ ] Add / update tests if necessary?
  • [ ] Add new / u...
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

When working in a project where some paths are not blacked yet, you may configure file discovery and run something like:

black .

Once you have this, you may need to integrate black in your editor, and some plugins end up piping from stdin:

stdin | black - --stdin-filename "$FILEPATH"

The problem is the integration will fail when trying to format a file being excluded by force-exclude directive.

You can check other tools like ruff output unformatted stdin in this case:

https://github...

#

Description

This change tries to fix https://github.com/psf/black/issues/4609, so you can use black piping stdin and expect the new content in the output, formatted or not. This is the way other formatters such as ruff or clang-format works too.

I'm not really sure if this is the best place to output the content, feel free to modify or make any suggestion.

Checklist - did you ...

  • [ ] Add an entry in CHANGES.md if necessary?
  • [ ] Add / update tests if nece...
flat krakenBOT
#

Fixes #4589

This PR upgrades the PyPI publishing workflow to use Trusted Publishing instead of token-based authentication. This change:

  • Improves security by using OpenID Connect (OIDC) instead of long-lived tokens
  • Removes the need for maintaining PyPI tokens in GitHub secrets
  • Uses the official PyPA publishing action

Changes made:

  • Added id-token: write permission for OIDC authentication
  • Changed environment name to 'release'
  • Switched to pypa/gh-action-pypi-publish ac...
flat krakenBOT
dark orbit
#

so me and my friends tried to calculate the truck/bus factor of this project using the git repository and the resulting answer was "1" with the author being "Łukasz Langa" dropping the coverage to below 50%.
Would the developers agree with this result, given no new developer joins the team, removing them would pose significant setbacks to the further development of this project?

flat krakenBOT
dense jungle
#

ugh may need psf folks to ban that person

glacial drum
#

that looks fun

#

Guess they really want to "debloat" black

flat krakenBOT
glacial drum
#

lol

azure plank
#

:(

azure plank
flat krakenBOT
#

Describe the bug

The following code can not be parsed/formatted by black:

del ([], name_2), [(), [], name_4, name_3], name_1[[name_2 for name_1 in name_0]]

black reported the following error:

> black -l 80 -C bug.py
error: cannot format bug.py: INTERNAL ERROR: Black 25.1.1.dev21+g254e829.d20250317 on Python (CPython) 3
.12.6 produced code that is not equivalent to the source.  Please report a bug on https://github.com/psf
/black/issues.  This diff might be helpful: /...
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Describe the bug

The following code can not be parsed/formatted by black:

with {} as name_3, (name_2 := name_4):

    def name_3[**name_1]():
        pass

black reported the following error:

> black -l 100 -C bug.py
error: cannot format bug.py: Cannot parse: 1:26: with {} as name_3, name_2 := name_4:

Oh no! 💥 💔 💥
1 file failed to reformat.

but it can be parsed by cpython:

from ast import parse
parse(
    'with {} as name_3, (name_2 := name_4):\n'
 ...
flat krakenBOT
flat krakenBOT
#

Describe the bug
Internal Error when reformatting file with comments at the end, where the first line has # fmt: skip added to it. All additional comment lines are removed.

To Reproduce

For example, take this code:

def foo():
    pass


# comment1  # fmt: skip
# comment2

And run it with these arguments:

$ black file.py

The resulting error is:

cannot format file.py: INTERNAL ERROR: Black 25.1.1.dev21+gdbb14ea on Python (CPython) 3.12.8 produced diff...

flat krakenBOT
#

Describe the bug

The following code can not be parsed/formatted by black:

with (name_2, name_2) as name_2:
    pass

black reported the following error:

> black -l 100 -t py312 bug.py
error: cannot format bug.py: INTERNAL ERROR: Black 25.1.1.dev21+g944a38e.d20250317 on Python (CPython) 3
.12.6 produced code that is not equivalent to the source.  Please report a bug on https://github.com/psf
/black/issues.  This diff might be helpful: /tmp/blk_umh51eiz.log

Oh no! 💥 💔 ...
azure plank
#

@dapper rapids Thanks for the amazing tool/work for the issues, but since the descriptions say it I have a couple of things that are mostly just nitpicks/out of laziness, feel free to ignore if they are too much work for not enough value.
nitpicks:
The "black reported the following error" code block has an extra newline, I think it should be strippable
Same thing with the "result:" code block
Laziness:
With issues that are inequivalent to source, often the output with --fast/"Skip temporary sanity checks" can quickly show where it went wrong (ie with (a, b) as c: pass vs with a, b as c: pass) more easilly than reading the diff (for me, might be skill issue)
It would be nice to have a link to the playground in the message somewhere with the broken code, these should be generatable without actually going to the playground since the compression/decompression code is very simple and so is the stored json link:
{'sc': 'source code here', 'll': 88, 'ssfl': False, 'ssn': False, 'smtc': False, 'pyi': False, 'fast': False, 'prv': False, 'usb': False, 'tv': []}

late dewBOT
#

api/app.py lines 38 to 45

def compress_state(data):
    compressed = lzma.compress(json.dumps(data).encode("utf-8"))
    return base64.urlsafe_b64encode(compressed).decode("utf-8")


def decompress_state(state):
    compressed = base64.urlsafe_b64decode(state)
    return json.loads(lzma.decompress(compressed))```
flat krakenBOT
dapper rapids
flat krakenBOT
flat krakenBOT
grave compass
flat krakenBOT
#

This PR fixes the inconsistent formatting of 'with' statements when using tuples.

Previously, Black formatted 'with' conditions inconsistently when they contained bracketes.

Now, the formatting is consistent across different cases.

##Changes:

  • Fixed inconsistent formatting of with statements when they contain brackets (tuples, lists, function calls).
  • Ensured that Black formats with statements consistently, avoiding unnecessary line breaks or misalignment when using brackets. ...
flat krakenBOT
#

Describe the style change

Black reformat defs and classes with 3 dots ("...") inside to one line. May be it should leave it as is, like with the "pass"

Examples in the current Black style

from this

def f():
    pass

Black leaves as is

def f():
    pass

from this

def f():
    ...

Black do

def f():  ...

It raise an flake8 error E704 (multiple statements on one line (def))

flat krakenBOT
flat krakenBOT
elder tusk
dark orbit
elder tusk
#

bus factor often reflected in contributions that aren’t commits too

dark orbit
elder tusk
#

reviews / merges is the big one

dark orbit
#

oh, that's useful. will definitely try to include them

elder tusk
#

(involvement in issues is a pulse check. releases is another kind of bus factor you might be interested in)

azure plank
# flat kraken

The perils of reading code on your phone, I somehow didn’t even notice the test case was js xD

dense jungle
livid dagger
#

hi does anyone know how i can format python
in discord

hallow solar
#

Hey! To format Python code in Discord, use triple backticks around your code. Add ‘python’ right after the opening backticks for syntax highlighting. Like this:

def say_hello():
    print("Hello, Discord!")
slow bison
#

You can put "python" after the first 3x inverted commas to get synyax highlighting
#```python

print("hello")
flat krakenBOT
#

Describe the bug

Given the following code snippet:

help(lambda x=(
    # comment
    "bar",
): False)

black crashes within the reformatting code with the error message:

error: cannot format : Opening paren not found in `leaves`

I reproduced this using the current head of black (black, 25.1.1.dev24+g2c135ed (compiled: no)) and on the online formatter. I can see this on both Linux and macOS and multiple versions of Python (3.12 and 3.13).

I bisected the repro, and...

slow ibex
#
    @t.overload
    def get_components(self) -> t_abc.Iterable[tuple[ID, tuple[()]]]: ...

    @t.overload
    def get_components[
        C1: Component,
    ](self, c1: type[C1],) -> t_abc.Iterable[tuple[ID, tuple[C1,]]]: ...

    @t.overload
    def get_components[
        C1: Component,
        C2: Component,
    ](self, c1: type[C1], c2: type[C2],) -> t_abc.Iterable[
        tuple[
            ID,
            tuple[
                C1,
                C2,
            ],
        ]
    ]: ...

    @t.overload
    def get_components[
        C1: Component,
        C2: Component,
        C3: Component,
    ](self, c1: type[C1], c2: type[C2], c3: type[C3],) -> t_abc.Iterable[
        tuple[
            ID,
            tuple[
                C1,
                C2,
                C3,
            ],
        ]
    ]: ...

    @t.overload
    def get_components[
        C1: Component,
        C2: Component,
        C3: Component,
        C4: Component,
    ](self, c1: type[C1], c2: type[C2], c3: type[C3], c4: type[C4],) -> t_abc.Iterable[
        tuple[
            ID,
            tuple[
                C1,
                C2,
                C3,
                C4,
            ],
        ]
    ]: ...

i am doing nasty stuff with 3.12 generics
i noticed weird formatting of func args in these cases: even if there is a trailing comma, func args are not split into several lines

#
    @t.overload
    def get_components[
        C1: Component,
        C2: Component,
        C3: Component,
        C4: Component,
-    ](self, c1: type[C1], c2: type[C2], c3: type[C3], c4: type[C4], /,) -> t_abc.Iterable[
+    ](
+        self, 
+        c1: type[C1], 
+        c2: type[C2], 
+        c3: type[C3], 
+        c4: type[C4], 
+        /,
+    ) -> t_abc.Iterable[
        tuple[
            ID,
            tuple[
                C1,
                C2,
                C3,
                C4,
            ],
        ]
    ]: ...
#

^ this is what i would like to see

azure plank
slow ibex
flat krakenBOT
#

The formatting applied by black on imports is not compatible with isort.

That prevents using both black --check and isort --check in CI testing.

Example:

Original code:

from .common_options import help_option, config_option, parm_options, \
    target_options

After formatting by isort:

from .common_options import (help_option, config_option, parm_options,
                             target_options)

After formatting by black:

from .common_options import (
    help...
flat krakenBOT
flat krakenBOT
#

Describe the bug

When saving the file, black does a great job with formatting. But today it caused the an issue in the code by changing the below - it removed the parenthesis:

list_filter = ("region")

to:

list_filter = "region"

This created an issue as list_filter has to be a tuple.

Unless this is an expected behavior and I missed something in the usage of the black, I don't think it should change a defined type.

To Reproduce

just run

list...
flat krakenBOT
#

Description

Fixes: #2095 – is_type_comment() is wrong

Summary of Changes:

  • Modified function signatures across several modules to pass the mode parameter to is_type_comment and make_comment.
  • Incorporated parts of PR #4467 by @Pedro-Muller29, particularly the fix in mode.py addressing the unhashable type: mode issue.

Acknowledgment:
Credit to @Pedro-Muller29 for the initial work in PR #4467.

Che...

flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Describe the style change

The current Black style for tuple assignment, as shown in the example below, is concise but lacks readability, especially when dealing with tuples that contain multiple elements. This can make it harder for readers to quickly understand the intent of the code.

Examples in the current Black style

(a,) = ("a",)

This style places the tuple elements on a single line, which might require the reader to spend extra time parsing the structure, espe...

flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Describe the style change

If inline comments have been aligned, that has most likely been done for a reason and breaking the alignment is likely to make the code worse. As an example, we have this code in our project:

TypeHint = Union[
    type,                     # Actual type.
    str,                      # Type name or alias.
    UnionType,                # Union syntax (e.g. `int | float`).
    'tuple[TypeHint, ...]'    # Tuple of type hints. Behaves like a union.
]

...

flat krakenBOT
#

Fixes #2097

Description

Currently, Black fails to recognize # type: and # type: ignore comments if there's extra whitespace after the # (e.g., # type:), as described in issue #2097. This can lead to these comments being treated as regular comments, potentially causing incorrect formatting or instability.

This PR updates the comment recognition logic (is_type_comment, is_type_ignore_comment, and helper functions like is_type_comment_string / `is_type_ignore_commen...

flat krakenBOT
#

Black is exploding the if guard in case patterns which have trailing commas in them, even if the guard expression fits in one line. The trailing comma logic should apply only to the case pattern, not the if guard.

Black https://github.com/psf/black/commit/d0ff3b

[Playground link](https://black.vercel.app/?version=main&state=_Td6WFoAAATm1rRGAgAhARYAAAB0L-Wj4AHyAKFdAD2IimZxl1N_WlbvK5V9HwFY_XA6IUcMIo1tyYCCoFcD4ulUXLciN-oOsLyTg3jeQOCSB4n_hjtP0pinvPpG8c3P-YF68pR7Qz8LQZlIYqo1mz-CYSOrK...

flat krakenBOT
#

Description:
While testing Black’s output, I observed that deeply nested f-strings (e.g., f"outer {f'inner {x}'}") sometimes lose indentation alignment or break unpredictably. This reduces code clarity, especially in templating or SQL query generation.

Evidence:

Input (before formatting)

query = f"SELECT {f"COUNT(*) FROM {f"users WHERE id = {user_id}"}"}"
Current output may misalign the nested f-strings.

flat krakenBOT
flat krakenBOT
#

Hello, thank you for the contribution!
I've looked at your changes, but there are a few things that need fixing before it's good to go.
First and foremost, the contributing basics docs page is your best friend. It guides you though how to set up everything for developing and how to run the pre-commit hooks/tests. It also guides you through how to make a changelog entry, which will be required.
I ran your change through ...

flat krakenBOT
#

I have multiple configurations in my pyproject.toml. Black and flake8 seem to be conflicting. Here is the configuration I have for the two linters.

[tool.black]
line-length = 120
include = '\.pyi?$'
check = true

[tool.flake8]
filename = folder1,folder2,folder3

When running black it gives the following error:

black  .
Error: Could not open file '/example/gitfolder/pyproject.toml': Error reading configuration file: Invalid value (at line 15, column 12)

To reproduce:
Add the ...

flat krakenBOT
#

Description

Resolves #4159

As I summarized there, most of the issues described can not be fixed easily. This PR resolves the two problems with obvious fixes: dictionary values with multiline strings should stay parenthesized, and ternaries with multiline strings in the value should stay parenthesized. Again, I don't believe we can do anything for the other pain points mentioned, so this PR resolves the issue as ...

flat krakenBOT
#

Description

Fixes #4640

This PR fixes a bug where Black would crash when formatting code with standalone comments within parentheses in lambda default arguments.

The issue occurs in the has_magic_trailing_comma method in src/black/lines.py. When a standalone comment is present within parentheses in a lambda default argument, the method tries to find the opening bracket in the line's leaves, but it wouldn't be there, causing a LookupError.

The fix adds a try-except blo...

flat krakenBOT
#

Describe the style change

Having a comment after an import to disable a pylint issue results in Black formatting it by putting both the imported Object and the comment in ( ) and stopping the comments purpose.

Examples in the current Black style

from django.contrib.auth.models import User  # We use default User model, pylint:disable=E5142

Results in

from django.contrib.auth.models import (
    User,  # We use default User model, pylint:disable=E5142
)
``...
safe gate
flat krakenBOT
#

Description

Updated the Prettier configuration and re-ran Prettier.
The pre-commit hook we were using has been archived, so I switched to an active and decently popular (600+ repo) fork. We were previously on an alpha version, and the fork doesn't support alpha versions, so I did have to downgrade the version. However, no changes in v4 affected us, and v3 is more freuently updated.
I also modified the file type list to include Markdown and remove language this project does not use.

...

azure plank
#

Starting to investigate why CI hypothesis is failing, at least on the surface it looks legit, though I don't know why this wasn't caught before. Maybe a hypothesis update? ```pycon

black.format_str('try:\\r# type: ignore\n pass\nfinally:\n pass\n', mode=black.FileMode())
'try:\n pass\nfinally:\n pass\n'

#

That is also valid code even if it looks very weird ```ps
PS> py -c "try:`r# type: ignoren passnfinally:n passnprint(1)"
1

#
PS D:\python_projects\black> uv run black -c "try:\`r# type: ignore`n pass`nfinally:`n pass`n"
# type: ignore
 pass
finally:
 pass
error: cannot format <string>: INTERNAL ERROR: Black 25.1.1.dev27+gd0ff3bd on Python (CPython) 3.13.0 produced code that is not equivalent to the source.  Please report a bug on https://github.com/psf/black/issues.
#

Like usual \r certainly is something to deal with

azure plank
#

Doing some bisection, it looks like at least the failing behavior changed with the new tokenizer.
Before new tokenizer: ```ps
PS D:\python_projects\jam-game> uvx --from git+https://github.com/psf/black@9f38928 black -c "try:`r# type: ignoren passnfinally:n passn"
Built black @ git+https://github.com/psf/black@9f38928414e6a39044f9b148692e90f3e1fd3433
Installed 7 packages in 45ms

type: ignore

pass
finally:
pass
error: cannot format <string>: Cannot parse for target version Python 3.13: 1:4: try:\

After new tokenizer: ```ps
PS D:\python_projects\jam-game> uvx --from git+https://github.com/psf/black@5342d2e black -c "try:\`r# type: ignore`n pass`nfinally:`n pass`n"
      Built black @ git+https://github.com/psf/black@5342d2eeda6935a96d2bd0c74072b3c441d76bde
Installed 8 packages in 55ms
# type: ignore
 pass
finally:
 pass
error: cannot format <string>: INTERNAL ERROR: Black 25.1.1.dev20+g5342d2e on Python (CPython) 3.13.0 produced code that is not equivalent to the source.  Please report a bug on https://github.com/psf/black/issues.  This diff might be helpful: C:\Users\gigagon\AppData\Local\Temp\blk_56kx39se.log
azure plank
#

After a bit of editing to the NL repr code so it shows the prefixes and a good amount of stepping through the line generator, my basic understanding is that for some reason the comment is never being generated ```
PS D:\python_projects\black> uv run black -c "try:`r# type: ignoren passnfinally:n passn"

d:\python_projects\black\src\black_init_.py(1222)format_str_once()
-> breakpoint()
(Pdb) n
d:\python_projects\black\src\black_init
.py(1223)format_str_once()
-> src_node = lib2to3_parse(src_contents.lstrip(), mode.target_versions)
(Pdb) n
d:\python_projects\black\src\black_init
.py(1224)_format_str_once()
-> dst_blocks: list[LinesBlock] = []
(Pdb) src_node
Node(file_input, '' [Node(try_stmt, '' [Leaf(NAME, '' 'try'), Leaf(COLON, '' ':'), Node(suite, '\\r# type: ignore' [Leaf(NEWLINE, '\\r# type: ignore' '\n'), Leaf(INDENT, '' ''), Node(simple_stmt, ' ' [Leaf(NAME, ' ' 'pass'), Leaf(NEWLINE, '' '\n')]), Leaf(DEDENT, '' '')]), Leaf(NAME, '' 'finally'), Leaf(COLON, '' ':'), Node(suite, '' [Leaf(NEWLINE, '' '\n'), Leaf(INDENT, '' ''), Node(simple_stmt, ' ' [Leaf(NAME, ' ' 'pass'), Leaf(NEWLINE, '' '\n')]), Leaf(DEDENT, '' '')])]), Leaf(ENDMARKER, '' '')])

#

After a lot more stepping, it looks like the issue starts in generate_comments because it can't deal with the starting \

#

I finally got to the bottom of it, making PR now

flat krakenBOT
#

Description

Fixes a \ followed by a \r followed by a comment causing the comment to be deleted. This also fixes Hypothesis failing the CI. This originally went under the radar since the old tokenizer largely didn't support carriage returns, so this example would crash with error: cannot format : Cannot parse for target version Python 3.13: 1:4: try:\ before getting to linegen. The new tokenizer supports carriage returns much better, and so this issue was revealed. I'm not...

azure plank
#

(Also even though I have merge rights now I am very tired currently and would appreciate another set of eyes to make sure I didn't explode everything on accident)

#

:/ I ran the 3.13 fuzz and it came out fine, but I guess this didn't fix the 3.11 fuzz, so the investigation continues

azure plank
#

So the issue is with the code \n#\r0. I think this might be a tokenizer issue, since comparing it with how \n#\n0 behaves:
\n#\r0 lib2to3 tokens: ```py
(54, '\n', (1, 0), (1, 1), '\n')
(53, '#\r0', (2, 0), (2, 3), '#\r0')
(54, '', (2, 3), (2, 3), '#\r0')
(0, '', (3, 0), (3, 0), '')

`\n#\n0` lib2to3 tokens: ```py
(54, '\n', (1, 0), (1, 1), '\n')
(53, '#', (2, 0), (2, 1), '#\n')
(54, '\n', (2, 1), (2, 2), '#\n')
(2, '0', (3, 0), (3, 1), '0')
(0, '', (4, 0), (4, 0), '')

So it looks like something is broken with #\r, starting from lib2to3.

\n#\r0 black tokens: ```py
TokenInfo(type=63 (NL), string='\n', start=(1, 0), end=(1, 1), line='\n')
TokenInfo(type=62 (COMMENT), string='#', start=(2, 0), end=(2, 1), line='#\r0')
TokenInfo(type=2 (NUMBER), string='\r0', start=(2, 1), end=(2, 3), line='#\r0')
TokenInfo(type=63 (NL), string='', start=(2, 3), end=(2, 4), line='#\r0')
TokenInfo(type=0 (ENDMARKER), string='', start=(3, 0), end=(3, 0), line='')

`\n#\n0` black tokens: ```py
TokenInfo(type=63 (NL), string='\n', start=(1, 0), end=(1, 1), line='\n')
TokenInfo(type=62 (COMMENT), string='#', start=(2, 0), end=(2, 1), line='#\n')
TokenInfo(type=63 (NL), string='\n', start=(2, 1), end=(2, 2), line='#\n')
TokenInfo(type=2 (NUMBER), string='0', start=(3, 0), end=(3, 1), line='0')
TokenInfo(type=4 (NEWLINE), string='', start=(3, 1), end=(3, 2), line='0')
TokenInfo(type=0 (ENDMARKER), string='', start=(4, 0), end=(4, 0), line='')

The black tokens also have similar behavior, where the \r version doesn't separate from the 0 correctly.

@lavish scroll since you did the new tokenizer, thoughts? I'm unsure how to fix this

I also have no clue why this seems to be only found on 3.11.

dense jungle
#

Personally on open-source projects I usually merge without review only for obvious quick fixes (e.g. fixing CI)

#

And sometimes when I'm impatient 🙂

dense jungle
#

As for why 3.11 only, it's random, so I think that sort of thing might just happen

azure plank
# dense jungle What does Python itself produce? I get ```$ echo '\n#\r0' | ./python.exe -m toke...

It works "fine" for me in PS. ```ps
PS D:\python_projects\black> echo "n#r0" | py -m tokenize
1,0-1,1: NL '\n'
2,0-2,1: COMMENT '#'
2,1-2,2: NL '\n'
3,0-3,1: NUMBER '0'
3,1-3,2: NEWLINE '\n'
4,0-4,0: ENDMARKER ''
PS D:\python_projects\black> py
Python 3.13.0 (tags/v3.13.0:60403a5, Oct 7 2024, 09:38:07) [MSC v.1941 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.

import tokenize
from io import StringIO;print(*tokenize.generate_tokens(StringIO("\n#\r0").readline), sep="\n")
TokenInfo(type=63 (NL), string='\n', start=(1, 0), end=(1, 1), line='\n')
TokenInfo(type=62 (COMMENT), string='#', start=(2, 0), end=(2, 1), line='#\r0')
TokenInfo(type=2 (NUMBER), string='\r0', start=(2, 1), end=(2, 3), line='#\r0')
TokenInfo(type=63 (NL), string='', start=(2, 3), end=(2, 4), line='#\r0')
TokenInfo(type=0 (ENDMARKER), string='', start=(3, 0), end=(3, 0), line='')

Of course I get inconsistent results depending on if I run it inside or outside of python, but I'd think that's probably either python or windows normalizing to NL at some point.

Trying it out in Git Bash, it looks like `echo` gives back the input literally, so python ends up with the equivalent of `"\\n#\\r0"`, which is why it's saying unexpected line continuation character. Using `printf` seems to work, and it gives the same result as on PS. ```bash
$  echo "\n#\r0"
\n#\r0
$  printf "\n#\r0"

0
$ printf "\n#\r0"  | py -m tokenize
1,0-1,1:            NL             '\n'
2,0-2,1:            COMMENT        '#'
2,1-2,2:            NL             '\n'
3,0-3,1:            NUMBER         '0'
3,1-3,2:            NEWLINE        ''
4,0-4,0:            ENDMARKER      ''
#

Well almost the same, but close enough

dense jungle
#

Interesting I get something else on 3.14 ```$ printf "\n#\r0" | ./python.exe -m tokenize
1,0-1,1: NL '\n'
2,0-2,1: COMMENT '#'
2,1-2,3: NUMBER '\r0'
2,3-2,4: NL ''
3,0-3,0: ENDMARKER ''

#

Seems like tokenize was buggy in 3.11 and earlier, checking with -m ast shows it always compiled to the same code

azure plank
#

Hm, it may just be windows things but trying both on Git Bash and PS I never get the \r0 from running from -m tokenize, and I always get it if I run from -c with generate_tokens.

dense jungle
#

Yeah I'm on a Mac, it's possible these things get interpreted differently somewhere along the way

azure plank
# azure plank So the issue is with the code `\n#\r0`. I think this might be a tokenizer issue,...

I dug into pytokens, and it looks like the tokenization is because a lone \r is not considered a newline, only \r\n and \n are considered newlines, while \r is just white space. This causes the comment to over-expand and include the following line(s) until a NL is encountered or EOF. It should be a fairly simple fix (around line 764 in __init__.py), but wow are CRs such a pain to work with. Part of me wonders if we should even keep bothering with special casing CRs and instead just normalize everything before running, since the output already normalizes and \r isn’t even a valid normalization option.

#

Also I’ve got no clue how to handle the cross-project/cross-repo update to fix this

azure plank
#

I do think pytokens should diverge from CPython here, since in the lexical analysis docs section it says all line ending forms including CR can be used equally regardless of platform, and we can see that’s the case by ```ps
PS>py -c "#rprint(1)r#nprint(2)n#rnprint(3)"
1
2
3

Python documentation

A Python program is read by a parser. Input to the parser is a stream of tokens, generated by the lexical analyzer(also known as the tokenizer). This chapter describes how the lexical analyzer brea...

#

I think CPython itself normalizes before running, which is why I can only observe this when running directly though generate_tokens, since this gives 10 instead of 13 ```PS
PS> py -c "print(ord('''`r'''))"
10

flat krakenBOT
#

Describe the bug

formatting the following string takes ~35s on my machine:

f"""
{{"xxxxx": "xxx xxxx xx xx xxxxxxxxxx xxx xx xxxxxxxx xxxx xxxxxxxx xx xxxxxxxx xxxxxx xxxxxxxx xx xxx xxx xxxxxx xx xxxxxxxxxxx.", "xxxxxxx": ["xxxxxx xxxx xx xxxxx xxxx xxx xxxxxxxxx xxxxxx: xxxx xx xx xxxxxxx xx x xxxxx (xxxx xxxxx) xxxxxx xxxxx xxxx xxxxx xxxxxxxxxx x xxxx xxxx x xx x, xxxx x xxxxxxxxxxxxx xxxxxxxxxxx xxxxx:. xxxx xxx xxx xxxxx xx xxxxxxxx xxxxxxx xxxxxxxxx xxxxxx xxxx xx xxxxx ...
flat krakenBOT
flat krakenBOT
silent knoll
#

oh tests failing, maybe they weren't so unneeded :p

dense jungle
#

the test failure is not obviously related but I didn't look deeply

silent knoll
#

oh it's on main too

dense jungle
#

might also be due to the click release

silent knoll
#

looks like it

#

ohhhh, no it's working fine, mypy's just confused

#

i'll look further probably on tuesday

flat krakenBOT
ornate hollow
#

what seems to be wrong with this code? it compiles on 3.9 and 3.12

lavish scroll
#

@silent knoll thanks for looking into the \r thing! I was unavailable for a bit. The fix should most likely go into pytokens.

silent knoll
#

(that was @azure plank)

lavish scroll
#

misclick :P

#

we pass a flag to pytokens in black for handling the carriage return edge cases (i think it's called handle_issue_128233 or something). this is another edge case that should be handled within that. If you want to give that a shot go ahead, I'll probably try to fix it Sunday.

#

fixing it there also has the added benefit of having a fully cpython compliant python tokenizer written in pure python.

silent knoll
flat krakenBOT
azure plank
# lavish scroll we pass a flag to pytokens in black for handling the carriage return edge cases ...

I looked at the pytokens code, and I'm confused why a lone \r isn't considered a newline link to code

def is_whitespace(self) -> bool:
    if self.is_newline():
        return False

    char = self.source[self.current_index]
    return (
        char == " "
        or char == "\r"
        or char == "\t"
        or char == "\x0b"
        or char == "\x0c"
    )

def is_newline(self) -> bool:
    if self.source[self.current_index] == "\n":
        return True
    if (
        self.source[self.current_index] == "\r"
        and self.current_index + 1 < len(self.source)
        and self.source[self.current_index + 1] == "\n"
    ):
        return True

    return False

Why is \r considered whitespace instead of a newline? I'm probably missing something, but the python docs say it's a valid newline in 2.1.2 Physical lines

A physical line is a sequence of characters terminated by an end-of-line sequence. In source files and strings, any of the standard platform line termination sequences can be used - the Unix form using ASCII LF (linefeed), the Windows form using the ASCII sequence CR LF (return followed by linefeed), or the old Macintosh form using the ASCII CR (return) character. All of these forms can be used equally, regardless of platform.
Is it just for matching the behavior of the old blib2to3 tokenizer?

lavish scroll
azure plank
#

Huh, I thought you could always use any return type on any platform

lavish scroll
#

the docs may not be in line with the tokenize module

#

try piping some code to tokenize and pytokens

#

on python 3.13 and up, and if you see any divergence that's a bug

azure plank
# lavish scroll the docs may not be in line with the tokenize module

Hm, (jumping around a bit in thought), so then wouldn’t the simplest way to handle the 128233 issue be to consider \r as always a newline? Since the current workaround works, at least in that a strange op token isn’t produced, but the next line of code gets eaten by the comment since the \r is considered white space

azure plank
#

And with this new knowledge, it's very easy to cook up some \r crashes, ie a=b\rc=d crashes since black sees a=b c=d, and a=b\r=d crashes with a saftey error since black sees a=b =d

silent knoll
#

is there a reason why we run pre-commit both in the action and through pre-commit.ci? it seems like pre-commit uses different versions of Click (and therefore its types) depending on if it's run in the action vs on pre-commit.ci

#

i think the website runner is caching the old version and i don't know that there's a way to clear it

dense jungle
#

forgot the syntax but isn't there something like additional deps

silent knoll
#

yeah we can

#

the only reason i didn't is right now it's the same as the pyproject, and i didn't really want to bring them out of sync

#

or we could just bump it to 3.2.0 throught the whole project and remove the things we added to support both versions

dense jungle
#

that might be annoying for some users

#

if they install other apps in the same env that want older click

silent knoll
#

ah right

#

i'm a bit unfamiliar with how packaging/deps works with python

cinder musk
flat krakenBOT
flat krakenBOT
pearl spruce
#

For anyone running black via pre-commit often and wishing it was snappier, I just released this pre-commit wrapper which uses JumpTheGun to make it start near-instantly:
https://pypi.org/project/jumpthegun-precommit-wrapper/

(Works for most other formatters/linters as well.)

flat krakenBOT
#

Describe the bug

Originally I realized that in VSCode the black formatter does not format my code anymore, i.e. the --line-ranges is broken and raises a parser error.

Observation: Difference between black file.py and black --line-range #-# file.py

If there is a def foo(self): ... with ... on the same line black fails to format anything after when used with --line-range.

To Reproduce

For example, take this code:

class Foo:
    
    @overload
    def ...
flat krakenBOT
#

Description

Fixes #4669

The issue happens because on a single line decorated item, due to the special handling of decorators there is a missing newline between the decorator(s) and decorated item. Like usual with my fixes, I approach it in the most blunt way possible: Add back in the missing newline. This should always be the correct thing to do, since multiline decorated items would have taken a different code path in _convert_unchanged_line_by_line that doesn't have this...

azure plank
# flat kraken

Currently getting bullied by the ci, one of the failures I could fix, but not sure how. The node.type == syms.decorated also implies that node is a node, not a leaf, since there shouldn’t be a leaf of type decorated, but I’m not sure how to tell mypy that. The diff-shades is failing because mypyc is failing inside the parser, but I don’t know why that’s just started now.

lavish scroll
#

you can always add an assert isinstance(node, Node)

azure plank
#

That’s a good idea

azure plank
#

It looks like both the mypyc tests and diff-shades are now using the new mypy 1.16, so probably some improvement to mypyc is causing the failures

flat krakenBOT
#

Description

This should fix the new failure happening with mypyc 1.16. I don't understand what was changed, and I also don't understand why the original code is so complex, so this reverts it to hopefully equivalent more normal code, which hopefully won't trip up mypyc.

I did not test this locally since I have no clue how.

Checklist - did you ...

  • [x] Add an entry in CHANGES.md if necessary?
    • N/A, fixing CI failure, should not result in any changes at ru...
azure plank
#

@lavish scroll Hypothesis found an error and I tracked down the cause, but I don't know how we should fix it.
await ... crashes the parser, since a ... op token (52 is op) (52, '...', (1, 6), (1, 9), 'await ...') slips through. tokenize.tokenize is supposed to fix that by turning a ... back into 3 .s, but in the case of await ..., the special handling for await takes precedence, and the token after the await gets to skip the later ... handling. I'm not sure how to cleanly deal with this since the ... handling has to happen on both paths, and I'm not comfortable enough with yields to pull it out into a function on my own, and you might have an ever better idea than that.

flat krakenBOT
lavish scroll
#

@azure plank is it a pytokens bug?

azure plank
#

It's in the translation layer between pytoken's output and the tokens black expects

#

But pytokens itself is fine

lavish scroll
#

i see, can you make a bug report? i can take it up

azure plank
#

sure

flat krakenBOT
flat krakenBOT
#

Description

This fixes another one of the hypothesis errors. It took me a long time to track down, but it was again in this translation layer:

Since transform_whitespace only checked for \\\n, any \\\r\n whitespace token would break everything. This is because since the offset adjustments never happened, on the token after the \\\r\n there would be a position mismatch, triggering the code to add a \n to the prefix of that token. This is fine for the first pass, but after ...

flat krakenBOT
#

Description

This is my attempt at fixing the carriage return problems. In combination with https://github.com/tusharsadhwani/pytokens/pull/1 , this should fix the hypothesis errors around \r.

I'm making both PRs drafts since my changes were made with the consideration of a sledgehammer, and were just focused on getting the issue to go away, so I'm uncertain if I've accidentally broken other things. All the black tests pass, as well as a local hypothesis run gave no problems, but I...

flat krakenBOT
#

Description

This fixes #2547 for the (default) case when g:black_use_virtualenv = 1.
The fix for g:black_use_virtualenv = 0 is a superset of these changes but is more invasive so I'll create a separate branch for it.

To trigger the bug on Linux:

  • make sure you don't have black installed as a system package: apt purge black
  • launch vim built with Python 3.X
  • run :BlackVersion, let it finish creating the virtualenv, close vim
  • launch vim built with Python 3.Y
    -...
flat krakenBOT
#

Description

Fixes #4672

This resolves the await ... bug from hypothesis. By removing support for async/await as soft keywords, it allows for making the pytokens->black's expected tokens much simpler, and in doing so removes the issue causing a ... op token to slip through.

I'd like to clean up both the remaining async/await and ... transforms, but those require much more sweeping changes, so for now this just fixes the one error from hypothesis.

This removes ...

flat krakenBOT
#

Describe the bug

When a long f-string is wrapped / split due to exceeding the line limit, Black will never put a substitution at the end of a f-string, resulting in unexpected wrapping behaviour.

To Reproduce

Input:

print(
    f"short {1} loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"
)

Output with --unstable:

print(
    "short"
    f" {1} loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"
)
``...
flat krakenBOT
flat krakenBOT
#

Black is a cool code formatter but as many other projects that I like it is quite hard to contribute as the project is big and feels intimidating at the begining. That is why I want to improve this on-boarding (get-to-know) process for all people who want to help the OSS community.

This PR adds auto-generated high-level diagrams and component-level documentation using CodeBoarding, aimed at improving developer onboarding by making it easier to get to know the codebase and lowering the barr...

flat krakenBOT
#

Description

Fixes #4677

My assumption on how the issue started is from a documentation issue on iter_fexpr_spans - the docs said "Spans are half-open ranges (left inclusive, right exclusive)", but it actually returns closed ranges. I assume the author of _get_illegal_split_indices then saw that, and added one to the range, making the ranges include the char after the f-string expr.

To fix this, I just removed that +1 to fix the ranges.

I looked at the other usages ...

azure plank
#

^ I decided to look through some of the other PRs from that account, and there is a very funny and true statement on a similar matplotlib pr:

I am impressed with AI in topics I do not know much about, but in topics I know about, it is flawed

flat krakenBOT
#

Olá, colegas espectadores do jogo Alemanha x Portugal. Semifinal da Liga das Nações da UEFA 2025. Sou fã do jogo Alemanha x Portugal. Semifinal da Liga das Nações da UEFA 2025 e, sem a TV Alemanha x Portugal.

🔴GO Live==►► CLICK HERE TO WATCH Live

🔴GO Live==►► CLICK HERE TO WATCH Live

Semifinal da Liga das Nações da UEFA 2025 disponível, estou procurando uma boa opção para assistir ao Weeks aqui na Austrália. Veja como posso encontrar a...

flat krakenBOT
#

Describe the bug

After running pre-commit, the black hook removed an exception alias - it must've though it was redundant given a prior still-in-scope iterable of the same name e. Regardless that renaming e is a fix, this is still incorrect behavior, since the except block is of course referring to the alias.

for e in emails:
    pass

...
-    except Exception as e:
+    except Exception:
         logger.error(f"err: {str(e)}")

To Reproduce

test.py:

flat krakenBOT
#

Description

Fixes #4647

As best I can tell, the error happens because in line gen, optional parenthesis get added:

def name_3[name_0: ([] if name_2 else name_3)](): pass

Then when left_hand_split runs, it mistakes the parenthesis inside the type params for the function arguments, and since it needs splitting adds a comma, which turns it into a tuple, and causes the equivalence error.

There's probably a better way to fix this, but since I don't understand t...

flat krakenBOT
#

Description

I got annoyed with dealing with percent formatting, so I decided to convert them to f-strings.

I'm not 100% sure about the pytree change since it's a reduction in quality, but I did it anyways because consistency.

There are still a couple instances of percent formatting in places, but they deal with external things like logging or tests so I didn't touch them.

There's a few more things I'd like to modernize since older python runtimes have stopped support...

flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Description

This has the changes mentioned in #4685 for not having the driver always use debug True, since while running black normally there is no way to change the log level to make those debug log calls useful.

This also has a small improvement to the release.py file since while I was reading the docs I noticed a part of the docs that said pr welcome for this. I updated the comment detection logic using https://www.rexegg.com/regex-quantifiers.php#lazy_solution as fut...

flat krakenBOT
#

Is your feature request related to a problem? Please describe.

It would be kinda helpful if black detecs comments used for pylint e.g. and move them to the correct line / trys to do that.

example the following inline statement:

query_plan = utils.__get_original_query_plan(file_content)  # pylint: disable=protected-access # pyright: ignore[reportPrivateUsage]

gets formatted into this:

query_plan = utils.__get_original_query_plan(
    file_content
)  # pylint: disable=prot...
flat krakenBOT
#

Description

MacOS CI started failing because it updated to 3.13.4 before the rest of the OSs. With the fixing of https://github.com/python/cpython/issues/129958 , some of the code in the pep_701 test is now invalid, so this makes that code valid by converting it to a multiline f-string. Since this was a change to the lexer in cpython, a corresponding change should be made in pytokens to fix this, so I'll open an issue there after I open this PR.

Checklist - did you ...

...

flat krakenBOT
flat krakenBOT
#

Description

This has the changes mentioned in #4685 for not having the driver always use debug True, since while running black normally there is no way to change the log level to make those debug log calls useful, and should give a very small speedup.

Checklist - did you ...

  • [x] Add an entry in CHANGES.md if necessary?
    • N/A, no user facing changes made
  • [x] Add / update tests if necessary?
    • N/A, no tests affected
  • [x] Add new / update outdated do...
#

Description

While reading the docs I noticed that there was a typo in the line ranges note, so this fixes that typo, and also makes it more clear what the potential issue might be with duplicate lines.

Checklist - did you ...

  • [x] Add an entry in CHANGES.md if necessary?
    • N/A small docs change
  • [x] Add / update tests if necessary?
    • N/A no tests affected
  • [x] Add new / update outdated documentation?
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Description

I was bored so I decided to run all the ruff lints against src/black, and only fix the ones I liked, so here's the results. I tried my best to only pick ones that I thought made a clear improvement to the code without causing too much churn. All the reasoning is in the commit messages, but I also copied it here because github cuts it off.

SIM201 negate-equal-op seems reasonable

RUF010 explicit-f-string-type-conversion seems reasonable

RUF003 ambiguou...
flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Describe the bug

When upgrading our system Python to 3.13.5 test_simple_format test starts to fail:

[  126s] =================================== FAILURES ===================================
[  126s] _________________________ test_simple_format[pep_701] __________________________
[  126s] 
[  126s] src = 'x = f"foo"\nx = f\'foo\'\nx = f"""foo"""\nx = f\'\'\'foo\'\'\'\nx = f"foo {{ bar {{ baz"\nx = f"foo {{ {2 + 2}bar {{ ...\'\'\'\n\'\'\'}"""\n\nf"{\'\\\'\'}"\nf"{f\'\\\'\'}"\n\nf\'{...
flat krakenBOT
brazen basin
#

should i be able tow rite here?

flat krakenBOT
flat krakenBOT
silent knoll
#

@azure plank what's the status on black#4674/pytokens#1? it's a bit difficult to create/review prs when tox is failing and I can't immediately tell if it's the same issue or not

#

from what i can tell, it looks like the prs are "ready" and you're just unsure if this is the best solution?

azure plank
azure plank
#

I’m also a lot more confident on the black side of things than the pytokens, since I’m making a much larger change on that side than on blacks.

silent knoll
#

interesting, i see

#

imo they probably shouldn't be drafts then, because for me a draft says "this isn't ready for review yet, please ignore it, just know i'm working on it", and in this case you do want feedback

azure plank
#

I make the black side PR a draft since even though it’s simple, it’s useless until the pytokens side is complete, and the pytokens side PR is a draft since my changes are very rough, and I think there’s a good chance tursharsadhwani will do something completely different. (They also said they were going to look at it a while ago, but I guess they never got the chance)

silent knoll
#

fair enough

flat krakenBOT
solemn mantle
#

Would like to ask, does black formatter work with marimo notebooks?

little parrot
#

yes cause the files are just normal scripts i dont know if theres a plugin for it directly though to run

flat krakenBOT
#

Describe the bug

No spacing between argument assignment operator when calling functions.

To Reproduce

For example, take this code:

apple(aapple=10,banana=20,charlie=30, delta=40, echo = 60, udvchuhbdichbasduhbfwdh=40, your_mums_nice_lady=69)

And run it with these arguments:

$ black file.py --target-version py39

The resulting error is:

apple(
aapple=10,
banana=20,
charlie=30,
delta=40,
echo=60,
udvchuhbdichbasduhbfwdh=40,
yo...

flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Input code:

# chain of 2 methods
foo = (
    bar.do_something(longish, listof, arguments)
    .do_something_else(also, a, long, listof, arguments)
)

# chain of 3 methods
other_foo = (
    bar.do_something(longish, listof, arguments)
    .do_something_else(also, a, long, listof, arguments)
    .do_a_third_thing(the, final, long, listof, arguments)
)

Output code:

# chain of 2 methods, formatted by black
foo = bar.do_something(longish, listof, arguments).do_something_else(
    al...
flat krakenBOT
#

Description

This is another way to fix the issues with \r, and should permanently get rid of them - currently \r isn't included in the normalization due to limitations with io.BytesIO and probably other things. This PR makes it so that they are included in the normalization to \n, and are a valid target for all newlines to normalize to. This should permanently fix all \r-related issues, since now there will be none given to the tokenizer / parser / formatter internals...

flat krakenBOT
#

CrackStreams provides live streams for all major MMA and UFC events, including Fight Nights, main events, and title matches. Enjoy uninterrupted ...When is UFC 318? How to watch Max Holloway vs. Dustin Poirier 3: TV, odds, predictions.[Here's How To Watch] UFC 318 Live Fight Streams On TV's ReddiT.[Here's How To Watch] UFC 318 Fight Live Stream On TV's ReddiT

[▶️Click Here 'Watch Now' UFC 318 Streams

[▶️Click Here 'Watch Now' [UFC 318 Streams](https://tinyurl...

#

CrackStreams provides live streams for all major MMA and UFC events, including Fight Nights, main events, and title matches. Enjoy uninterrupted ...When is UFC 318? How to watch Max Holloway vs. Dustin Poirier 3: TV, odds, predictions.[Here's How To Watch] UFC 318 Live Fight Streams On TV's ReddiT.[Here's How To Watch] UFC 318 Fight Live Stream On TV's ReddiT

[▶️Click Here 'Watch Now' UFC 318 Streams

[▶️Click Here 'Watch Now' [UFC 318 Streams](https://tinyurl...

flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Description

Minor changes to the PR template. Mainly small grammar and formatting tweaks, but I also added information about the stability policy and a checkbox ensuring any code style changes were added to preview.

Checklist - did you ...

  • [-] Add an entry in CHANGES.md if necessary?
  • [-] Add / update tests if necessary?
  • [-] Add new / update outdated documentation?
flat krakenBOT
flat krakenBOT
#

Describe the bug

Use of asyncio.get_event_loop_policy(), which is deprecated as of Python 3.14, triggers DeprecationWarnings during test runs.

To Reproduce

  1. Install Python 3.14.
    sudo apt install python3.14-dev python3.14-venv
    

The dev variant is needed because aiohttp doesn’t have wheels for Python 3.14 yet. Without it, pip tries to build from source but fails due to missing Python headers.

  1. Clone the Black repository:
    git clone https:/...
flat krakenBOT
#

Description

Python 3.14 deprecates asyncio.get_event_loop_policy(), which causes multiple unit tests to emit warnings or fail. This PR replaces usage of the deprecated function with a modern alternative to ensure compatibility with Python 3.14+.

Checklist - did you ...

  • [ ] Implement any code style changes under the --preview style, following the
    stability policy?
  • [ ] Add an entry in CHANGES.md if necessary?
  • [ ] Add / update tests if neces...
flat krakenBOT
#

Description

Closes: #4678

Previously, catching multiple exception types required writing:

try:
    …
except (A, B, C):
    …

With PEP 758 you can now omit the parentheses when you’re not using an as clause:

try:
    …
except A, B, C:
    …

This change streamlines the syntax, reduces visual clutter when catching several exceptions, and brings except closer in style to other comma‑separated constructs in the language.

This P...

flat krakenBOT
#

Describe the bug

In unit tests, specifying the --target-version flag raises AttributeError: 'tuple' object has no attribute 'append'.

To Reproduce

Just add # flags: --target-version=py310 on top of any unit test and then run with tox -e py.

The resulting error is:

AttributeError: 'tuple' object has no attribute 'append'.

Expected behavior

The unit test should be run with target_versions set to exactly what was specified.

Environment

  • Black's ver...
flat krakenBOT
silent knoll
#

The problem is that when mode.target_versions is empty, supports_feature ends up evaluating to all([]), which returns True. That means supports_feature(empty_set, some_feature) incorrectly returns True, and Black removes parentheses from except types even on older Python versions. Modifying support_feature causes multiple tests to fail which seem to be relying this quirk so i just check before calling it.
that doesn't sound good

flat krakenBOT
#

Describe the bug

I expect the wrapping to look nicer

To Reproduce

For example, take this code:

class Example:
    @overload
    @classmethod
    def create_from[TBool: (Literal[True], Literal[False])](
        cls: type[SearchConfig[Any]],
        search_config: SearchConfig[Any],
        *,
        allow_boolean: TBool,
        **overrides: Any,
    ) -> SearchConfig[TBool]: ...

And run it with these arguments:

$ black t.py --target-version py313 --line-...
flat krakenBOT
flat krakenBOT
steady oriole
# silent knoll > The problem is that when mode.target_versions is empty, supports_feature ends ...

Apologies for the confusion earlier — I didn’t realize that some unit tests ( test_black) also check formatting of some source files. I was using another editor that didn’t auto-format on save, so the failures were due to formatting issues, not behavior changes (my mistake 😞). I’ve verified that tests pass on the main branch and will update the GitHub comment right away.

Also, should I add a patch to supports_feature to align current behavior with the expected one?

And once again sorry about that

flat krakenBOT
#

Description

def supports_feature(target_versions: set[TargetVersion], feature: Feature) -> bool:
    return all(feature in VERSION_TO_FEATURES[version] for version in target_versions)

Here when target_versions is empty, expression gets reduced to all([]) which evaluates to False which is not the correct behaviour.

Checklist - did you ...

  • [ ] Implement any code style changes under the --preview style, following the
    stability p...
flat krakenBOT
#

In my pyproject.toml: `black = { version = ">=25.1.0, Warning: The locked version 8.2.2 for click is a yanked version. Reason for being yanked: Unintended change in behavior of boolean options and None

Because no versions of black match >=25.0.0,25.1.0, So, because no versions of click match >=8.0.0
and {{project-name}} depends on black[d] (>=25.0.0,<26.0.0), version solving failed.

bronze raft
#

New to Black - is there an option to insert/validate line 1 of a file has the project path and name of the file as a comment - e.g. # srv/directory/myfile.py

azure plank
flat krakenBOT
#

Describe the bug

#fmt: skip is ignored in the specific case demonstrated below.

To Reproduce

Let black format this piece of code:

class ClassWithALongName:
    Constant1 = 1
    Constant2 = 2
    Constant3 = 3


def test():
    if (
        "cond1" == "cond1"
        and "cond2" == "cond2"
        and 1 in (  # fmt: skip
            ClassWithALongName.Constant1,
            ClassWithALongName.Constant2,
            ClassWithALongName.Constant3,
        )
    ):
       ...
supple vapor
#

Python ka vs course chahie

flat krakenBOT
#

Describe the bug

Black crashes on the following valid python code:

class ClassWithALongName:
    Constant1 = 1
    Constant2 = 2
    Constant3 = 3


def test():
    if (
        "cond1" == "cond1"
        and "cond2" == "cond2"
        and 1 in (
            ClassWithALongName.Constant1,
            ClassWithALongName.Constant2,
            ClassWithALongName.Constant3, # fmt: skip
        )
    ): # fmt: skip
        return True
    return False

To Reproduce

Jus...

flat krakenBOT
#

Description

This PR improves the performance of the is_chained_assignment method by replacing a list comprehension followed by .count() with a generator expression passed to sum(). This change avoids building an intermediate list, which improves both memory efficiency and runtime.

The original implementation constructs an intermediate list of leaf.type values before calling .count(token.EQUAL). The updated version uses a generator expression to directly count match...

flat krakenBOT
#

Describe the bug

error: cannot format foo.py: INTERNAL ERROR: Black 25.1.1.dev56+gb3ae57b on Python (CPython) 3.13.5 produced different code on the second pass of the formatter.  Please report a bug on https://github.com/psf/black/issues.  This diff might be helpful: /tmp/blk_kir8cfms.log

To Reproduce
Minimal repro:

def foo():
    possibly_redundant_lowlevel_checkpoints: list[  # pyright: ignore[reportUnknownVariableType]
        cst.BaseExpression
    ] = field( ...
flat krakenBOT
flat krakenBOT
flat krakenBOT
#

Description

This PR introduces an optimization for the Line.__str__ method, improving runtime efficiency when rendering lines.

The original implementation repeatedly concatenates strings using +=, which is inefficient in Python due to the creation of intermediate string objects.
The refactored version significantly speeds up string creation by replacing repeated concatenation (res += ...) with the much more efficient "".join() method.
This approach avoids creating a n...

coarse quiver
#

Hello everyone, i'm new here
I'm a software developer and also a computer science student in uni

digital river
#

Hi @coarse quiver

flat krakenBOT
flat krakenBOT
#

Description

This PR changes diff-shades to run on the stable and unstable styles as opposed to the stable and preview styles.

I opted to replace the preview job with the unstable job instead of adding a new job because all preview changes also exist in unstable so running both feels redundant, and it takes a long time to run so it wouldn't be worth it to have both jobs.

I wasn't sure if the "preview-changes" mode was meant to be interpreted as "Changes in the preview style" or "Previ...

flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
flat krakenBOT
pliant tundra
#

ANYONE GERE

#

please someone

silent knoll
#

Hi

narrow vigil
#

racist

plain atlas
#

Does black ever plan to stop developing now that a replacement tool (ruff format) exists?

silent knoll
#

No

covert sand
#

Hi

plain atlas