Skip to content

Commit 798700f

Browse files
committed
rewrite bytes(b'foo') to b'foo'
1 parent 54356ff commit 798700f

File tree

3 files changed

+25
-4
lines changed

3 files changed

+25
-4
lines changed

pyupgrade/_plugins/native_literals.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import ast
4+
import functools
45
from typing import Iterable
56

67
from tokenize_rt import Offset
@@ -19,15 +20,15 @@
1920
SIX_NATIVE_STR = frozenset(('ensure_str', 'ensure_text', 'text_type'))
2021

2122

22-
def _fix_native_str(i: int, tokens: list[Token]) -> None:
23+
def _fix_literal(i: int, tokens: list[Token], *, empty: str) -> None:
2324
j = find_open_paren(tokens, i)
2425
func_args, end = parse_call_args(tokens, j)
2526
if any(tok.name == 'NL' for tok in tokens[i:end]):
2627
return
2728
if func_args:
2829
replace_call(tokens, i, end, func_args, '{args[0]}')
2930
else:
30-
tokens[i:end] = [tokens[i]._replace(name='STRING', src="''")]
31+
tokens[i:end] = [tokens[i]._replace(name='STRING', src=empty)]
3132

3233

3334
def is_a_native_literal_call(
@@ -58,4 +59,16 @@ def visit_Call(
5859
state.settings.min_version >= (3,) and
5960
is_a_native_literal_call(node, state.from_imports)
6061
):
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

pyupgrade/_token_helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ def replace_call(
420420

421421
# there are a few edge cases which cause syntax errors when the first
422422
# argument contains newlines (especially when moved outside of a natural
423-
# contiunuation context)
423+
# continuation context)
424424
if _arg_contains_newline(tokens, *args[0]) and 0 not in parens:
425425
# this attempts to preserve more of the whitespace by using the
426426
# original non-stripped argument string

tests/features/native_literals_test.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
'str(*a)', 'str("foo", *a)',
1515
'str(**k)', 'str("foo", **k)',
1616
'str("foo", encoding="UTF-8")',
17+
'bytes("foo", encoding="UTF-8")',
18+
'bytes(b"foo"\nb"bar")',
19+
'bytes("foo"\n"bar")',
20+
'bytes(*a)', 'bytes("foo", *a)',
21+
'bytes("foo", **a)',
1722
),
1823
)
1924
def test_fix_native_literals_noop(s):
@@ -38,6 +43,9 @@ def test_fix_native_literals_noop(s):
3843
3944
id='from import of rewritten name',
4045
),
46+
('bytes()', "b''"),
47+
('bytes(b"foo")', 'b"foo"'),
48+
('bytes(b"""\nfoo""")', 'b"""\nfoo"""'),
4149
),
4250
)
4351
def test_fix_native_literals(s, expected):

0 commit comments

Comments
 (0)