@@ -786,7 +786,7 @@ def build_replacement_checkers(self, specifiers: List[ConversionSpecifier],
786
786
def replacement_checkers (self , specifier : ConversionSpecifier , context : Context ,
787
787
expr : FormatStringExpr ) -> Optional [List [Checkers ]]:
788
788
"""Returns a list of tuples of two functions that check whether a replacement is
789
- of the right type for the specifier. The first functions take a node and checks
789
+ of the right type for the specifier. The first function takes a node and checks
790
790
its type in the right type context. The second function just checks a type.
791
791
"""
792
792
checkers : List [Checkers ] = []
@@ -874,11 +874,11 @@ def check_s_special_cases(self, expr: FormatStringExpr, typ: Type, context: Cont
874
874
875
875
def checkers_for_c_type (self , type : str ,
876
876
context : Context ,
877
- expr : FormatStringExpr ) -> Optional [Checkers ]:
877
+ format_expr : FormatStringExpr ) -> Optional [Checkers ]:
878
878
"""Returns a tuple of check functions that check whether, respectively,
879
879
a node or a type is compatible with 'type' that is a character type.
880
880
"""
881
- expected_type = self .conversion_type (type , context , expr )
881
+ expected_type = self .conversion_type (type , context , format_expr )
882
882
if expected_type is None :
883
883
return None
884
884
@@ -889,8 +889,12 @@ def check_type(type: Type) -> None:
889
889
def check_expr (expr : Expression ) -> None :
890
890
"""int, or str with length 1"""
891
891
type = self .accept (expr , expected_type )
892
- if isinstance (expr , (StrExpr , BytesExpr )) and len (cast (StrExpr , expr ).value ) != 1 :
893
- self .msg .requires_int_or_char (context )
892
+ # TODO: Use the same the error message when incompatible types match %c
893
+ # Python 3 doesn't support b'%c' % str
894
+ if not (self .chk .options .python_version >= (3 , 0 )
895
+ and isinstance (format_expr , BytesExpr )):
896
+ if isinstance (expr , (StrExpr , BytesExpr )) and len (expr .value ) != 1 :
897
+ self .msg .requires_int_or_char (context )
894
898
check_type (type )
895
899
896
900
return check_expr , check_type
@@ -939,9 +943,12 @@ def conversion_type(self, p: str, context: Context, expr: FormatStringExpr,
939
943
numeric_types .append (self .named_type ('typing.SupportsInt' ))
940
944
return UnionType .make_union (numeric_types )
941
945
elif p in ['c' ]:
942
- return UnionType ([self .named_type ('builtins.int' ),
943
- self .named_type ('builtins.float' ),
944
- self .named_type ('builtins.str' )])
946
+ if isinstance (expr , BytesExpr ):
947
+ return UnionType ([self .named_type ('builtins.int' ),
948
+ self .named_type ('builtins.bytes' )])
949
+ else :
950
+ return UnionType ([self .named_type ('builtins.int' ),
951
+ self .named_type ('builtins.str' )])
945
952
else :
946
953
self .msg .unsupported_placeholder (p , context )
947
954
return None
0 commit comments