ruff/crates
Shaygan Hooshyari 6591775cd9
[flake8-type-checking] Skip quoting annotation if it becomes invalid syntax (TCH001) (#14285)
Fix: #13934 

## Summary

Current implementation has a bug when the current annotation contains a
string with single and double quotes.

TL;DR: I think these cases happen less than other use cases of Literal.
So instead of fixing them we skip the fix in those cases.

One of the problematic cases:

```
from typing import Literal
from third_party import Type

def error(self, type1: Type[Literal["'"]]):
    pass
```

The outcome is:

```
- def error(self, type1: Type[Literal["'"]]):
+ def error(self, type1: "Type[Literal[''']]"):
```

While it should be:

```
"Type[Literal['\'']"
```

The solution in this case is that we check if there’s any quotes same as
the quote style we want to use for this Literal parameter then escape
that same quote used in the string.

Also this case is not uncommon to have:
<https://grep.app/search?current=2&q=Literal["'>

But this can get more complicated for example in case of:

```
- def error(self, type1: Type[Literal["\'"]]):
+ def error(self, type1: "Type[Literal[''']]"):
```

Here we escaped the inner quote but in the generated annotation it gets
removed. Then we flip the quote style of the Literal paramter and the
formatting is wrong.

In this case the solution is more complicated.
1. When generating the string of the source code preserve the backslash.
2. After we have the annotation check if there isn’t any escaped quote
of the same type we want to use for the Literal parameter. In this case
check if we have any `’` without `\` before them. This can get more
complicated since there can be multiple backslashes so checking for only
`\’` won’t be enough.

Another problem is when the string contains `\n`. In case of
`Type[Literal["\n"]]` we generate `'Type[Literal["\n"]]'` and both
pyright and mypy reject this annotation.

https://pyright-play.net/?code=GYJw9gtgBALgngBwJYDsDmUkQWEMoAySMApiAIYA2AUAMaXkDOjUAKoiQNqsC6AXFAB0w6tQAmJYLBKMYAfQCOAVzCk5tMChjlUjOQCNytANaMGjABYAKRiUrAANLA4BGAQHJ2CLkVIVKnABEADoogTw87gCUfNRQ8VAITIyiElKksooqahpaOih6hiZmTNa29k7w3m5sHJy%2BZFRBoeE8MXEJScxAA

## Test Plan

I added test cases for the original code in the reported issue and two
more cases for backslash and new line.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2024-11-15 11:11:46 +00:00
..
red_knot Introduce Diagnostic trait (#14130) 2024-11-07 13:26:21 +01:00
red_knot_python_semantic [red-knot] Display raw characters for string literal (#14351) 2024-11-15 13:44:04 +05:30
red_knot_server Introduce Diagnostic trait (#14130) 2024-11-07 13:26:21 +01:00
red_knot_test [red-knot] Improve mdtest output (#14213) 2024-11-11 11:03:41 +00:00
red_knot_vendored Sync vendored typeshed stubs (#14350) 2024-11-14 22:29:29 -08:00
red_knot_wasm Introduce Diagnostic trait (#14130) 2024-11-07 13:26:21 +01:00
red_knot_workspace [red-knot] Avoid panics for ipython magic commands (#14326) 2024-11-13 20:58:08 +01:00
ruff [flake8-markupsafe] Adds Implementation for MS001 via RUF035 (#14224) 2024-11-11 18:30:03 +00:00
ruff_benchmark [red-knot] function signature representation (#14304) 2024-11-14 23:34:24 +00:00
ruff_cache Fix cache key collisions for paths with separators (#12159) 2024-07-03 07:36:46 -05:00
ruff_db Introduce Diagnostic trait (#14130) 2024-11-07 13:26:21 +01:00
ruff_dev Alternate quotes for strings inside f-strings in preview (#13860) 2024-10-23 07:57:53 +02:00
ruff_diagnostics Document comment policy around fix safety (#14300) 2024-11-13 08:03:58 -05:00
ruff_formatter Join implicit concatenated strings when they fit on a line (#13663) 2024-10-24 11:52:22 +02:00
ruff_graph Bump MSRV to Rust 1.80 (#13826) 2024-10-20 10:55:36 +02:00
ruff_index [red-knot] small efficiency improvements and bugfixes to use-def map building (#12373) 2024-07-18 09:24:58 -07:00
ruff_linter [flake8-type-checking] Skip quoting annotation if it becomes invalid syntax (TCH001) (#14285) 2024-11-15 11:11:46 +00:00
ruff_macros Derive message formats macro support to string (#14093) 2024-11-04 18:06:25 +01:00
ruff_notebook Bump MSRV to Rust 1.80 (#13826) 2024-10-20 10:55:36 +02:00
ruff_python_ast [flake8-simplify] Infer "unknown" truthiness for literal iterables whose items are all unpacks (SIM222) (#14263) 2024-11-11 15:23:34 -05:00
ruff_python_ast_integration_tests [internal] ComparableExpr (f)strings and bytes made invariant under concatenation (#13301) 2024-09-25 16:58:57 +02:00
ruff_python_codegen Extract LineIndex independent methods from Locator (#13938) 2024-10-28 07:53:41 +00:00
ruff_python_formatter Disallow single-line implicit concatenated strings (#13928) 2024-11-03 11:49:26 +00:00
ruff_python_index Extract LineIndex independent methods from Locator (#13938) 2024-10-28 07:53:41 +00:00
ruff_python_literal Use bitshift consistently for bitflag definitions (#14265) 2024-11-11 10:20:17 +00:00
ruff_python_parser Short circuit lex_identifier if the name is longer or shorter than any known keyword (#13815) 2024-10-19 11:07:15 +00:00
ruff_python_resolver
ruff_python_semantic [ruff] Also report problems for attrs dataclasses in preview mode (RUF008, RUF009) (#14327) 2024-11-14 15:13:49 +00:00
ruff_python_stdlib Use bitshift consistently for bitflag definitions (#14265) 2024-11-11 10:20:17 +00:00
ruff_python_trivia Extract LineIndex independent methods from Locator (#13938) 2024-10-28 07:53:41 +00:00
ruff_python_trivia_integration_tests Extract LineIndex independent methods from Locator (#13938) 2024-10-28 07:53:41 +00:00
ruff_server Use CWD to resolve settings from ruff.configuration (#14352) 2024-11-15 13:45:00 +05:30
ruff_source_file Extract LineIndex independent methods from Locator (#13938) 2024-10-28 07:53:41 +00:00
ruff_text_size Extract LineIndex independent methods from Locator (#13938) 2024-10-28 07:53:41 +00:00
ruff_wasm Bump version to 0.7.3 (#14197) 2024-11-08 16:39:37 +05:30
ruff_workspace [flake8-markupsafe] Adds Implementation for MS001 via RUF035 (#14224) 2024-11-11 18:30:03 +00:00