astral-sh / ruff

An extremely fast Python linter and code formatter, written in Rust.
https://docs.astral.sh/ruff
MIT License
30.14k stars 982 forks source link

format: different behavior with black for `hug_parens_with_braces_and_square_brackets` and generators #11375

Open trim21 opened 3 months ago

trim21 commented 3 months ago

I'm using ruff format with --preview enable, and it generate different output in this case.

ruff:

import shutil
import asyncio

async def main():
    by_path = {}
    loop = asyncio.get_event_loop()

    if loop:
        value = await asyncio.gather(
            *(
                loop.run_in_executor(None, lambda pp: (pp, shutil.disk_usage(pp).free), p)
                for p in by_path
            )
        )
        return value

    return None

black:

import shutil
import asyncio

async def main():
    by_path = {}
    loop = asyncio.get_event_loop()

    if loop:
        value = await asyncio.gather(*(
            loop.run_in_executor(None, lambda pp: (pp, shutil.disk_usage(pp).free), p)
            for p in by_path
        ))
        return value

    return None

This is not listed in "Known Deviations from Black", is this unexpected behavoir?

pyproject.toml

[tool.black]
line-length = 100
target-version = ['py311']
#future = true

unstable = true
preview = true

[tool.ruff]
cache-dir = ".venv/.cache/ruff"
line-length = 100
target-version = 'py311'

exclude = ['dist', '.venv']

[tool.ruff.format]
preview = true
153957 commented 3 months ago

I think this is related; https://github.com/psf/black/pull/3964#issuecomment-1783318353 And this in black is the part which may be missing in ruff: https://github.com/psf/black/pull/3992

trim21 commented 3 months ago

title of this issue is not very accurate and I don't know how black call this feature...

153957 commented 3 months ago

I think it is called hug_parens_with_braces_and_square_brackets: https://github.com/astral-sh/ruff/discussions/9945#discussioncomment-8439722

trim21 commented 3 months ago

I think it is called hug_parens_with_braces_and_square_brackets: #9945 (comment)

thanks

dhruvmanila commented 3 months ago

It seems like we don't consider generator to be huggable:

https://github.com/astral-sh/ruff/blob/5bde6a08a0b59b00ee3911be4508c72cf31a2cc5/crates/ruff_python_formatter/src/expression/mod.rs#L1126-L1126

I'm not sure if it's intentional or not but Micha might be able to provide more context on this once he's back from his PTO.

Although it does seem that a tuple expression is huggable, so I'd say that the generator should probably be as well.

MichaReiser commented 2 months ago

This is not listed in "Known Deviations from Black", is this unexpected behavior?

We don't track differences for preview styles because both Black's and Ruff's preview styles are in flux, making it difficult to track the differences over time.

I'm not sure if it's intentional or not but Micha might be able to provide more context on this once he's back from his PTO.

I don't think this is intentional. The only thing we need to be mindful of is that generator parentheses in call expressions are optional. Meaning, we should only hug if the generator already has parentheses (the logic must be in sync with the parentheses logic in FormatExprGenerator)