Skip to content

Commit

Permalink
messages: clarify bytes repr errors (#9243)
Browse files Browse the repository at this point in the history
Resolves #9236 

Co-authored-by: hauntsaninja <>
  • Loading branch information
hauntsaninja authored Aug 2, 2020
1 parent e6615c9 commit a9c9a41
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 15 deletions.
14 changes: 8 additions & 6 deletions mypy/checkstrformat.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,9 +384,10 @@ def perform_special_format_checks(self, spec: ConversionSpecifier, call: CallExp
if self.chk.options.python_version >= (3, 0):
if (has_type_component(actual_type, 'builtins.bytes') and
not custom_special_method(actual_type, '__str__')):
self.msg.fail("On Python 3 '{}'.format(b'abc') produces \"b'abc'\";"
" use !r if this is a desired behavior", call,
code=codes.STR_BYTES_PY3)
self.msg.fail(
"On Python 3 '{}'.format(b'abc') produces \"b'abc'\", not 'abc'; "
"use '{!r}'.format(b'abc') if this is desired behavior",
call, code=codes.STR_BYTES_PY3)
if spec.flags:
numeric_types = UnionType([self.named_type('builtins.int'),
self.named_type('builtins.float')])
Expand Down Expand Up @@ -843,9 +844,10 @@ def check_s_special_cases(self, expr: FormatStringExpr, typ: Type, context: Cont
# Couple special cases for string formatting.
if self.chk.options.python_version >= (3, 0):
if has_type_component(typ, 'builtins.bytes'):
self.msg.fail("On Python 3 '%s' % b'abc' produces \"b'abc'\";"
" use %r if this is a desired behavior", context,
code=codes.STR_BYTES_PY3)
self.msg.fail(
"On Python 3 '%s' % b'abc' produces \"b'abc'\", not 'abc'; "
"use '%r' % b'abc' if this is desired behavior",
context, code=codes.STR_BYTES_PY3)
if self.chk.options.python_version < (3, 0):
if has_type_component(typ, 'builtins.unicode'):
self.unicode_upcast = True
Expand Down
4 changes: 2 additions & 2 deletions test-data/unit/check-errorcodes.test
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,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 '{}'.format(b'abc') produces "b'abc'"; use !r if this is a desired behavior [str-bytes-safe]
'%s' % b'abc' # E: On Python 3 '%s' % b'abc' produces "b'abc'"; use %r if this is a desired behavior [str-bytes-safe]
'{}'.format(b'abc') # E: On Python 3 '{}'.format(b'abc') produces "b'abc'", not 'abc'; use '{!r}'.format(b'abc') if this is desired behavior [str-bytes-safe]
'%s' % b'abc' # E: On Python 3 '%s' % b'abc' produces "b'abc'", not 'abc'; use '%r' % b'abc' if this is desired behavior [str-bytes-safe]
[builtins fixtures/primitives.pyi]
[typing fixtures/typing-medium.pyi]

Expand Down
14 changes: 7 additions & 7 deletions test-data/unit/check-expressions.test
Original file line number Diff line number Diff line change
Expand Up @@ -1183,8 +1183,8 @@ xb: bytes
xs: str

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

[case testStringInterpolationSBytesVsStrResultsPy2]
Expand Down Expand Up @@ -1576,17 +1576,17 @@ N = NewType('N', bytes)
n: N

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

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

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

'{!r}'.format(b)
Expand Down

0 comments on commit a9c9a41

Please sign in to comment.