|
1 | 1 | from __future__ import annotations
|
2 | 2 |
|
3 | 3 | import ast
|
| 4 | +import functools |
4 | 5 | from typing import Iterable
|
5 | 6 |
|
6 | 7 | from tokenize_rt import Offset
|
|
19 | 20 | SIX_NATIVE_STR = frozenset(('ensure_str', 'ensure_text', 'text_type'))
|
20 | 21 |
|
21 | 22 |
|
22 |
| -def _fix_native_str(i: int, tokens: list[Token]) -> None: |
| 23 | +def _fix_literal(i: int, tokens: list[Token], *, empty: str) -> None: |
23 | 24 | j = find_open_paren(tokens, i)
|
24 | 25 | func_args, end = parse_call_args(tokens, j)
|
25 | 26 | if any(tok.name == 'NL' for tok in tokens[i:end]):
|
26 | 27 | return
|
27 | 28 | if func_args:
|
28 | 29 | replace_call(tokens, i, end, func_args, '{args[0]}')
|
29 | 30 | else:
|
30 |
| - tokens[i:end] = [tokens[i]._replace(name='STRING', src="''")] |
| 31 | + tokens[i:end] = [tokens[i]._replace(name='STRING', src=empty)] |
31 | 32 |
|
32 | 33 |
|
33 | 34 | def is_a_native_literal_call(
|
@@ -58,4 +59,16 @@ def visit_Call(
|
58 | 59 | state.settings.min_version >= (3,) and
|
59 | 60 | is_a_native_literal_call(node, state.from_imports)
|
60 | 61 | ):
|
61 |
| - yield ast_to_offset(node), _fix_native_str |
| 62 | + func = functools.partial(_fix_literal, empty="''") |
| 63 | + yield ast_to_offset(node), func |
| 64 | + elif ( |
| 65 | + state.settings.min_version >= (3,) and |
| 66 | + isinstance(node.func, ast.Name) and node.func.id == 'bytes' and |
| 67 | + not node.keywords and not has_starargs(node) and |
| 68 | + ( |
| 69 | + len(node.args) == 0 or |
| 70 | + (len(node.args) == 1 and isinstance(node.args[0], ast.Bytes)) |
| 71 | + ) |
| 72 | + ): |
| 73 | + func = functools.partial(_fix_literal, empty="b''") |
| 74 | + yield ast_to_offset(node), func |
0 commit comments