Skip to content

crash while formatting a delete statement with given line length #4625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
15r10nk opened this issue Mar 17, 2025 · 6 comments · Fixed by #4628
Closed

crash while formatting a delete statement with given line length #4625

15r10nk opened this issue Mar 17, 2025 · 6 comments · Fixed by #4628
Assignees
Labels
T: bug Something isn't working

Comments

@15r10nk
Copy link

15r10nk commented Mar 17, 2025

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: /tmp/blk_qtuwnx6z.log

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

but it can be parsed by cpython:

from ast import parse
parse('''
del ([], name_2), [(), [], name_4, name_3], name_1[[name_2 for name_1 in name_0]]
''')

result:


returncode: 0

black transforms the code with --fast into

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

This has technical the same meaning but a different ast representation (tuple vs targets) https://docs.python.org/3/library/ast.html#ast.Delete.

❯ echo 'del (a,b); del a,b' | python -m ast
Module(
   body=[
      Delete(
         targets=[
            Tuple(
               elts=[
                  Name(id='a', ctx=Del()),
                  Name(id='b', ctx=Del())],
               ctx=Del())]),
      Delete(
         targets=[
            Name(id='a', ctx=Del()),
            Name(id='b', ctx=Del())])],
   type_ignores=[])

Environment

  • Black's version: current main (5342d2e
    )
  • OS and Python version: Linux/Python 3.12.6 (main, Sep 9 2024, 22:11:19) [Clang 18.1.8 ]

Additional context

The bug was found by pysource-codegen (see #3908)

@15r10nk 15r10nk added the T: bug Something isn't working label Mar 17, 2025
@JelleZijlstra
Copy link
Collaborator

Interesting, we have code in the AST safety check specifically allowing this:

. Perhaps it's buggy.

@15r10nk
Copy link
Author

15r10nk commented Mar 17, 2025

I think the problem is that there is a tuple inside the tuple in the formatted code.

@tusharsadhwani tusharsadhwani self-assigned this Mar 19, 2025
@tusharsadhwani
Copy link
Collaborator

@15r10nk great seeing your work being used to catch bugs in black. I'll pick up fixing this over the week, assuming you aren't working on a fix already.

@15r10nk
Copy link
Author

15r10nk commented Mar 19, 2025

@tusharsadhwani Thank you, you can fix it if you want. I wanted to fix it, but I haven't found the time yet.

@tusharsadhwani
Copy link
Collaborator

tusharsadhwani commented Mar 19, 2025

Minimized the case to:

del (),
$ black -l1 -v x.py 
[...]
Traceback (most recent call last):
  File "/Users/tusharsadhwani/code/black/src/black/__init__.py", line 911, in reformat_one
    if changed is not Changed.CACHED and format_file_in_place(
                                         ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tusharsadhwani/code/black/src/black/__init__.py", line 953, in format_file_in_place
    dst_contents = format_file_contents(
                   ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tusharsadhwani/code/black/src/black/__init__.py", line 1085, in format_file_contents
    check_stability_and_equivalence(
  File "/Users/tusharsadhwani/code/black/src/black/__init__.py", line 1059, in check_stability_and_equivalence
    assert_equivalent(src_contents, dst_contents)
  File "/Users/tusharsadhwani/code/black/src/black/__init__.py", line 1540, in assert_equivalent
    raise ASTSafetyError(
black.parsing.ASTSafetyError: INTERNAL ERROR: Black 22.1.1.dev715+g97a730d.d20250219 on Python (CPython) 3.12.3 produced code that is not equivalent to the source.  Please report a bug on https://github.com/psf/black/issues.

@tusharsadhwani
Copy link
Collaborator

It was indeed because we end up with a tuple inside a tuple after formatting.

The AST check code was only unwrapping a top level tuple if present, causing the inner tuple after formatting to not get unwrapped before the AST comparison.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T: bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants