@@ -183,6 +183,16 @@ def warn(self, msg: str, context: Context, file: Optional[str] = None,
183
183
"""Report a warning message (unless disabled)."""
184
184
self .report (msg , context , 'warning' , file = file , origin = origin )
185
185
186
+ def quote_type_string (self , type_string : str ) -> str :
187
+ """Quotes a type representation for use in messages."""
188
+ no_quote_regex = r'^<(tuple|union): \d+ items>$'
189
+ if (type_string in ['Module' , 'overloaded function' , '<nothing>' , '<deleted>' ]
190
+ or re .match (no_quote_regex , type_string ) is not None ):
191
+ # Messages are easier to read if these aren't quoted. We use a
192
+ # regex to match strings with variable contents.
193
+ return type_string
194
+ return '"{}"' .format (type_string )
195
+
186
196
def format (self , typ : Type , verbosity : int = 0 ) -> str :
187
197
"""
188
198
Convert a type to a relatively short string suitable for error messages.
@@ -192,22 +202,16 @@ def format(self, typ: Type, verbosity: int = 0) -> str:
192
202
modification of the formatted string is required, callers should use
193
203
.format_bare.
194
204
"""
195
- ret = self .format_bare (typ , verbosity )
196
- no_quote_regex = r'^tuple\(length \d+\)$'
197
- if (ret in ['Module' , 'overloaded function' , '<nothing>' , '<deleted>' ]
198
- or re .match (no_quote_regex , ret ) is not None ):
199
- # Messages are easier to read if these aren't quoted. We use a
200
- # regex to match strings with variable contents.
201
- return ret
202
- return '"{}"' .format (ret )
205
+ return self .quote_type_string (self .format_bare (typ , verbosity ))
203
206
204
207
def format_bare (self , typ : Type , verbosity : int = 0 ) -> str :
205
208
"""
206
209
Convert a type to a relatively short string suitable for error messages.
207
210
208
211
This method will return an unquoted string. If a caller doesn't need to
209
212
perform post-processing on the string output, .format should be used
210
- instead.
213
+ instead. (The caller may want to use .quote_type_string after
214
+ processing has happened, to maintain consistent quoting in messages.)
211
215
"""
212
216
if isinstance (typ , Instance ):
213
217
itype = typ
@@ -256,7 +260,7 @@ def format_bare(self, typ: Type, verbosity: int = 0) -> str:
256
260
if len (s ) < 400 :
257
261
return s
258
262
else :
259
- return 'tuple(length {}) ' .format (len (items ))
263
+ return '< tuple: {} items> ' .format (len (items ))
260
264
elif isinstance (typ , TypedDictType ):
261
265
# If the TypedDictType is named, return the name
262
266
if not typ .is_anonymous ():
@@ -284,7 +288,7 @@ def format_bare(self, typ: Type, verbosity: int = 0) -> str:
284
288
if len (s ) < 400 :
285
289
return s
286
290
else :
287
- return 'union type ( {} items) ' .format (len (items ))
291
+ return '< union: {} items> ' .format (len (items ))
288
292
elif isinstance (typ , NoneTyp ):
289
293
return 'None'
290
294
elif isinstance (typ , AnyType ):
@@ -614,8 +618,9 @@ def incompatible_argument(self, n: int, m: int, callee: CallableType, arg_type:
614
618
arg_type_str = '*' + arg_type_str
615
619
elif arg_kind == ARG_STAR2 :
616
620
arg_type_str = '**' + arg_type_str
617
- msg = 'Argument {} {}has incompatible type "{}"; expected "{}"' .format (
618
- n , target , arg_type_str , expected_type_str )
621
+ msg = 'Argument {} {}has incompatible type {}; expected {}' .format (
622
+ n , target , self .quote_type_string (arg_type_str ),
623
+ self .quote_type_string (expected_type_str ))
619
624
if isinstance (arg_type , Instance ) and isinstance (expected_type , Instance ):
620
625
notes = append_invariance_notes (notes , arg_type , expected_type )
621
626
self .fail (msg , context )
0 commit comments