Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve bytes formatting error #14959

Merged
merged 3 commits into from
Mar 29, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Improve bytes formatting error
Fixes #11806

This error message was last changed in #11139 to make it more applicable
to f-strings. Since users are still getting confused, it makes sense to
be more explicit about what the recommended fix is. There was also an
extra set of quotes and a mention of Python 3 that didn't help.
  • Loading branch information
hauntsaninja committed Mar 26, 2023

Verified

This commit was signed with the committer’s verified signature.
mp911de Mark Paluch
commit c1762c00ede77895e6d4d396403cf2281515769e
10 changes: 4 additions & 6 deletions mypy/checkstrformat.py
Original file line number Diff line number Diff line change
@@ -435,9 +435,8 @@ def perform_special_format_checks(
actual_type, "__str__"
):
self.msg.fail(
'On Python 3 formatting "b\'abc\'" with "{}" '
'produces "b\'abc\'", not "abc"; '
'use "{!r}" if this is desired behavior',
'If "x = b\'abc\'" then f"{x}" or "{}".format(x) produces "b\'abc\'", '
'not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x)',
call,
code=codes.STR_BYTES_PY3,
)
@@ -946,9 +945,8 @@ def check_s_special_cases(self, expr: FormatStringExpr, typ: Type, context: Cont
# Couple special cases for string formatting.
if has_type_component(typ, "builtins.bytes"):
self.msg.fail(
'On Python 3 formatting "b\'abc\'" with "%s" '
'produces "b\'abc\'", not "abc"; '
'use "%r" if this is desired behavior',
'If "x = b\'abc\'" then "%s" % x produces "b\'abc\'", not "abc"; '
'if this is desired behavior use "%r" % x',
context,
code=codes.STR_BYTES_PY3,
)
3 changes: 1 addition & 2 deletions mypyc/test-data/run-strings.test
Original file line number Diff line number Diff line change
@@ -232,8 +232,7 @@ def test_fstring_basics() -> None:

x = bytes([1, 2, 3, 4])
# assert f'bytes: {x}' == "bytes: b'\\x01\\x02\\x03\\x04'"
# error: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc";
# use "{!r}" if this is desired behavior behavior
# error: If "x = b'abc'" then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x)

float_num = 123.4
assert f'{float_num}' == '123.4'
4 changes: 2 additions & 2 deletions test-data/unit/check-errorcodes.test
Original file line number Diff line number Diff line change
@@ -638,8 +638,8 @@ def g() -> int:
'%d' % 'no' # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsInt]") [str-format]
'%d + %d' % (1, 2, 3) # E: Not all arguments converted during string formatting [str-format]

'{}'.format(b'abc') # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior [str-bytes-safe]
'%s' % b'abc' # E: On Python 3 formatting "b'abc'" with "%s" produces "b'abc'", not "abc"; use "%r" if this is desired behavior [str-bytes-safe]
'{}'.format(b'abc') # E: If "x = b'abc'" then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x) [str-bytes-safe]
'%s' % b'abc' # E: If "x = b'abc'" then "%s" % x produces "b'abc'", not "abc"; if this is desired behavior use "%r" % x [str-bytes-safe]
[builtins fixtures/primitives.pyi]
[typing fixtures/typing-medium.pyi]

20 changes: 10 additions & 10 deletions test-data/unit/check-formatting.test
Original file line number Diff line number Diff line change
@@ -30,8 +30,8 @@ xb: bytes
xs: str

'%s' % xs # OK
'%s' % xb # E: On Python 3 formatting "b'abc'" with "%s" produces "b'abc'", not "abc"; use "%r" if this is desired behavior
'%(name)s' % {'name': b'value'} # E: On Python 3 formatting "b'abc'" with "%s" produces "b'abc'", not "abc"; use "%r" if this is desired behavior
'%s' % xb # E: If "x = b'abc'" then "%s" % x produces "b'abc'", not "abc"; if this is desired behavior use "%r" % x
'%(name)s' % {'name': b'value'} # E: If "x = b'abc'" then "%s" % x produces "b'abc'", not "abc"; if this is desired behavior use "%r" % x
[builtins fixtures/primitives.pyi]

[case testStringInterpolationCount]
@@ -435,21 +435,21 @@ N = NewType('N', bytes)
n: N

'{}'.format(a)
'{}'.format(b) # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior
'{}'.format(x) # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior
'{}'.format(n) # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior
'{}'.format(b) # E: If "x = b'abc'" then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x)
'{}'.format(x) # E: If "x = b'abc'" then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x)
'{}'.format(n) # E: If "x = b'abc'" then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x)

f'{b}' # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior
f'{x}' # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior
f'{n}' # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior
f'{b}' # E: If "x = b'abc'" then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x)
f'{x}' # E: If "x = b'abc'" then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x)
f'{n}' # E: If "x = b'abc'" then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x)

class C(Generic[B]):
x: B
def meth(self) -> None:
'{}'.format(self.x) # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior
'{}'.format(self.x) # E: If "x = b'abc'" then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x)

def func(x: A) -> A:
'{}'.format(x) # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior
'{}'.format(x) # E: If "x = b'abc'" then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x)
return x

'{!r}'.format(a)