astral-sh / astral-sh/ruff

Format Should Preserve Type Ignore Sub Expression

Open
#8,286 16 comments 8 reactions 0 assignees View on GitHub
formatter
Dominant language
Rust
Stars
49.7k
Forks
2.4k
Avg merge
2d 1h
Merged PRs (30d)
458

Description

It seems that the ruff formatter will collapse a multi line expression with a `# type: ignore` to one line, unlike black.

I would like to keep the existing line split, if possible, since this limits the type ignore to one piece of the statement, instead of all of it. That way, if there is a type error in one of the other parts of the statement they are still caught by the type checker.

This is similar to https://github.com/astral-sh/ruff/issues/7730 but the issue here is not that the line ends up being too long, but that it changes the semantics of the type checker.

Example:

```diff
$ ruff format . --diff
--- python/egglog/egraph.py
+++ python/egglog/egraph.py
@@ -536,9 +536,7 @@

# If this is the class for this method and we have a paramaterized class, recurse
if (
- cls_type_and_name
- and isinstance(tp, _GenericAlias)
- and tp.__origin__ == cls_type_and_name[0] # type: ignore
+ cls_type_and_name and isinstance(tp, _GenericAlias) and tp.__origin__ == cls_type_and_name[0] # type: ignore
):
return TypeRefWithVars(
cls_type_and_name[1],

1 file would be reformatted, 25 files left unchanged
$ ruff --version
ruff 0.1.3
```

Settings:

```toml
[tool.ruff]
# Allow lines to be as long as 120.
line-length = 120
ignore = [
# allow star imports
"F405",
"F403",
# Dont care if cls isnt typed explicitly in classmethod
"ANN102",
# Same for self
"ANN101",
# Allow single line docstrings on multiple lines
"D200",
"D212",
# Inconsistant formatting
"D203",
"COM812",
"COM819",
"E501",
"ISC001",
"Q001",
"Q002",
"Q003",
"W191",
"Q000",
"D206",
# TODO: Remove the rest of these eventually
# Allow public methods to not have docstrings
"D102",
# Allow longer messages for custom errors
"TRY003",
# Allow f-string in exceptions
"EM102",
]
src = ["python"]
select = ["ALL"]
extend-exclude = ["python/tests"]
```

Contributor guide

Open the contributing guide

Research direction

Reproduce the formatter change using the example in python/egglog/egraph.py and `ruff format . --diff`, then compare the result with Black. Trace Ruff's formatter handling of multiline expressions and `# type: ignore`; done means preserving the split so the ignore applies only to the intended expression, with a regression test for the behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.