0
# Message Types
1
2
Comprehensive set of structured warning and error classes representing different types of issues that can be detected in Python code. Each message type provides specific information about the problem and its location, enabling precise error reporting and programmatic handling of analysis results.
3
4
Pyflakes defines 48 message classes that inherit from the base `Message` class, each representing a specific type of code issue.
5
6
## Capabilities
7
8
### Base Message Class
9
10
Foundation class for all Pyflakes messages, providing common functionality for error reporting and formatting.
11
12
```python { .api }
13
class Message:
14
"""Base class for all pyflakes messages."""
15
16
message: str = '' # Format string for the message
17
message_args: tuple = () # Arguments for format string
18
19
def __init__(self, filename: str, loc):
20
"""
21
Initialize message with location information.
22
23
Parameters:
24
- filename (str): Name of file where issue was found
25
- loc: AST node with location information (lineno, col_offset)
26
"""
27
28
filename: str # File where issue occurs
29
lineno: int # Line number (1-based)
30
col: int # Column offset (0-based)
31
32
def __str__(self) -> str:
33
"""Format message as 'filename:line:col: description'."""
34
```
35
36
**Usage:**
37
38
```python
39
import pyflakes.api
40
from pyflakes.messages import UnusedImport, UndefinedName
41
42
# Get messages from analysis
43
code = "import os\nprint(x)"
44
checker_result = pyflakes.api.check(code, 'test.py')
45
46
# Messages are typically accessed through checker.messages
47
# Each message provides structured information:
48
# - message.filename: 'test.py'
49
# - message.lineno: line number
50
# - message.col: column position
51
# - str(message): formatted error string
52
```
53
54
### Import-Related Messages
55
56
Messages for issues related to import statements and module usage.
57
58
```python { .api }
59
class UnusedImport(Message):
60
"""Import statement that is never used."""
61
message = '%r imported but unused'
62
63
def __init__(self, filename: str, loc, name: str): ...
64
65
class RedefinedWhileUnused(Message):
66
"""Name redefined before being used."""
67
message = 'redefinition of unused %r from line %r'
68
69
def __init__(self, filename: str, loc, name: str, orig_loc): ...
70
71
class ImportShadowedByLoopVar(Message):
72
"""Import name shadowed by loop variable."""
73
message = 'import %r from line %r shadowed by loop variable'
74
75
def __init__(self, filename: str, loc, name: str, orig_loc): ...
76
77
class ImportStarNotPermitted(Message):
78
"""Star import used outside module level."""
79
message = "'from %s import *' only allowed at module level"
80
81
def __init__(self, filename: str, loc, modname: str): ...
82
83
class ImportStarUsed(Message):
84
"""Star import used, limiting name detection."""
85
message = "'from %s import *' used; unable to detect undefined names"
86
87
def __init__(self, filename: str, loc, modname: str): ...
88
89
class ImportStarUsage(Message):
90
"""Name may be from star import."""
91
message = "%r may be undefined, or defined from star imports: %s"
92
93
def __init__(self, filename: str, loc, name: str, from_list: str): ...
94
```
95
96
### Name Resolution Messages
97
98
Messages for undefined names and variable usage issues.
99
100
```python { .api }
101
class UndefinedName(Message):
102
"""Reference to undefined name."""
103
message = 'undefined name %r'
104
105
def __init__(self, filename: str, loc, name: str): ...
106
107
class UndefinedLocal(Message):
108
"""Local variable referenced before assignment."""
109
message = 'local variable %r {0} referenced before assignment'
110
default = 'defined in enclosing scope on line %r'
111
builtin = 'defined as a builtin'
112
113
def __init__(self, filename: str, loc, name: str, orig_loc): ...
114
115
class UndefinedExport(Message):
116
"""Name in __all__ is not defined."""
117
message = 'undefined name %r in __all__'
118
119
def __init__(self, filename: str, loc, name: str): ...
120
```
121
122
### Variable Usage Messages
123
124
Messages for unused variables and assignments.
125
126
```python { .api }
127
class UnusedVariable(Message):
128
"""Variable assigned but never used."""
129
message = 'local variable %r is assigned to but never used'
130
131
def __init__(self, filename: str, loc, names: str): ...
132
133
class UnusedAnnotation(Message):
134
"""Type annotation without assignment or usage."""
135
message = 'local variable %r is annotated but never used'
136
137
def __init__(self, filename: str, loc, names: str): ...
138
139
class UnusedIndirectAssignment(Message):
140
"""Global or nonlocal statement where name is never reassigned."""
141
message = '`%s %s` is unused: name is never assigned in scope'
142
143
def __init__(self, filename: str, loc, name: str): ...
144
```
145
146
### Syntax and Structure Messages
147
148
Messages for syntax errors and structural issues.
149
150
```python { .api }
151
class DoctestSyntaxError(Message):
152
"""Syntax error in doctest code."""
153
message = 'syntax error in doctest'
154
155
def __init__(self, filename: str, loc, position=None): ...
156
157
class DuplicateArgument(Message):
158
"""Duplicate argument in function definition."""
159
message = 'duplicate argument %r in function definition'
160
161
def __init__(self, filename: str, loc, name: str): ...
162
163
class MultiValueRepeatedKeyLiteral(Message):
164
"""Dictionary key repeated with different values."""
165
message = 'dictionary key %r repeated with different values'
166
167
def __init__(self, filename: str, loc, key): ...
168
169
class MultiValueRepeatedKeyVariable(Message):
170
"""Dictionary key variable repeated with different values."""
171
message = 'dictionary key variable %s repeated with different values'
172
173
def __init__(self, filename: str, loc, key): ...
174
```
175
176
### Future Import Messages
177
178
Messages for __future__ import issues.
179
180
```python { .api }
181
class LateFutureImport(Message):
182
"""__future__ import not at beginning of file."""
183
message = 'from __future__ imports must occur at the beginning of the file'
184
185
class FutureFeatureNotDefined(Message):
186
"""Unknown __future__ feature."""
187
message = 'future feature %s is not defined'
188
189
def __init__(self, filename: str, loc, name: str): ...
190
```
191
192
### Control Flow Messages
193
194
Messages for control flow statement issues.
195
196
```python { .api }
197
class ReturnOutsideFunction(Message):
198
"""Return statement outside function."""
199
message = "'return' outside function"
200
201
class YieldOutsideFunction(Message):
202
"""Yield statement outside function."""
203
message = "'yield' outside function"
204
205
class ContinueOutsideLoop(Message):
206
"""Continue statement outside loop."""
207
message = "'continue' not properly in loop"
208
209
class BreakOutsideLoop(Message):
210
"""Break statement outside loop."""
211
message = "'break' outside loop"
212
```
213
214
### Exception Handling Messages
215
216
Messages for exception handling issues.
217
218
```python { .api }
219
class DefaultExceptNotLast(Message):
220
"""Default except clause not last."""
221
message = 'default \'except:\' must be last'
222
```
223
224
### Assignment Expression Messages
225
226
Messages for assignment expression and unpacking issues.
227
228
```python { .api }
229
class TwoStarredExpressions(Message):
230
"""Multiple starred expressions in assignment."""
231
message = 'two starred expressions in assignment'
232
233
class TooManyExpressionsInStarredAssignment(Message):
234
"""Too many expressions in starred assignment."""
235
message = 'too many expressions in star-unpacking assignment'
236
```
237
238
### Comparison and Literal Messages
239
240
Messages for comparison and literal usage issues.
241
242
```python { .api }
243
class IfTuple(Message):
244
"""If statement with tuple condition (always true)."""
245
message = '\'if tuple literal\' is always true, perhaps remove accidental comma?'
246
247
class AssertTuple(Message):
248
"""Assert statement with tuple (always true)."""
249
message = 'assertion is always true, perhaps remove parentheses?'
250
251
class IsLiteral(Message):
252
"""Identity comparison with literal."""
253
message = 'use ==/!= to compare constant literals (str, bytes, int, float, tuple)'
254
```
255
256
### Forward Annotation Messages
257
258
Messages for type annotation issues.
259
260
```python { .api }
261
class ForwardAnnotationSyntaxError(Message):
262
"""Syntax error in forward annotation."""
263
message = 'syntax error in forward annotation %r'
264
265
def __init__(self, filename: str, loc, annotation: str): ...
266
```
267
268
### Python Version Compatibility Messages
269
270
Messages for Python version compatibility issues.
271
272
```python { .api }
273
class RaiseNotImplemented(Message):
274
"""Raise NotImplemented instead of NotImplementedError."""
275
message = "'raise NotImplemented' should be 'raise NotImplementedError'"
276
277
class InvalidPrintSyntax(Message):
278
"""Invalid print syntax (Python 2 style)."""
279
message = 'use of >> is invalid with print function'
280
```
281
282
### String Formatting Messages
283
284
Messages for string formatting issues (f-strings, .format(), % formatting).
285
286
```python { .api }
287
class FStringMissingPlaceholders(Message):
288
"""F-string without placeholders."""
289
message = 'f-string is missing placeholders'
290
291
class TStringMissingPlaceholders(Message):
292
"""T-string without placeholders."""
293
message = 't-string is missing placeholders'
294
295
class StringDotFormatExtraPositionalArguments(Message):
296
"""Extra positional arguments in .format() call."""
297
message = "'...'.format(...) has unused arguments at position(s): %s"
298
299
def __init__(self, filename: str, loc, extra_positions): ...
300
301
class StringDotFormatExtraNamedArguments(Message):
302
"""Extra named arguments in .format() call."""
303
message = "'...'.format(...) has unused named argument(s): %s"
304
305
def __init__(self, filename: str, loc, extra_keywords): ...
306
307
class StringDotFormatMissingArgument(Message):
308
"""Missing argument in .format() call."""
309
message = "'...'.format(...) is missing argument(s) for placeholder(s): %s"
310
311
def __init__(self, filename: str, loc, missing_arguments): ...
312
313
class StringDotFormatMixingAutomatic(Message):
314
"""Mixing automatic and manual field numbering."""
315
message = "'...'.format(...) mixes automatic and manual numbering"
316
317
class StringDotFormatInvalidFormat(Message):
318
"""Invalid format specifier."""
319
message = "'...'.format(...) has invalid format string: %s"
320
321
def __init__(self, filename: str, loc, error): ...
322
```
323
324
### Percent Formatting Messages
325
326
Messages for percent-style string formatting issues.
327
328
```python { .api }
329
class PercentFormatInvalidFormat(Message):
330
"""Invalid percent format string."""
331
message = "'...' %% ... has invalid format string: %s"
332
333
def __init__(self, filename: str, loc, error): ...
334
335
class PercentFormatMixedPositionalAndNamed(Message):
336
"""Mixed positional and named formatting."""
337
message = "'...' %% ... has mixed positional and named placeholders"
338
339
class PercentFormatUnsupportedFormatCharacter(Message):
340
"""Unsupported format character."""
341
message = "'...' %% ... has unsupported format character %r"
342
343
def __init__(self, filename: str, loc, c): ...
344
345
class PercentFormatPositionalCountMismatch(Message):
346
"""Wrong number of positional arguments."""
347
message = "'...' %% ... has %d placeholder(s) but %d substitution(s)"
348
349
def __init__(self, filename: str, loc, n_placeholders: int, n_substitutions: int): ...
350
351
class PercentFormatExtraNamedArguments(Message):
352
"""Extra named arguments in percent formatting."""
353
message = "'...' %% ... has unused named argument(s): %s"
354
355
def __init__(self, filename: str, loc, extra_keywords): ...
356
357
class PercentFormatMissingArgument(Message):
358
"""Missing argument in percent formatting."""
359
message = "'...' %% ... is missing argument(s) for placeholder(s): %s"
360
361
def __init__(self, filename: str, loc, missing_arguments): ...
362
363
class PercentFormatExpectedMapping(Message):
364
"""Expected mapping for named formatting."""
365
message = "'...' %% ... expected mapping but got sequence"
366
367
class PercentFormatExpectedSequence(Message):
368
"""Expected sequence for positional formatting."""
369
message = "'...' %% ... expected sequence but got mapping"
370
371
class PercentFormatStarRequiresSequence(Message):
372
"""Star format requires sequence."""
373
message = "'...' %% ... `*` specifier requires sequence"
374
```
375
376
## Complete Message Class List
377
378
All 48 message classes available in pyflakes.messages:
379
380
1. `Message` - Base class
381
2. `UnusedImport` - Unused import statement
382
3. `RedefinedWhileUnused` - Name redefined before use
383
4. `ImportShadowedByLoopVar` - Import shadowed by loop variable
384
5. `ImportStarNotPermitted` - Star import outside module level
385
6. `ImportStarUsed` - Star import used
386
7. `ImportStarUsage` - Name may be from star import
387
8. `UndefinedName` - Undefined name reference
388
9. `DoctestSyntaxError` - Doctest syntax error
389
10. `UndefinedExport` - Undefined name in __all__
390
11. `UndefinedLocal` - Local variable referenced before assignment
391
12. `DuplicateArgument` - Duplicate function argument
392
13. `MultiValueRepeatedKeyLiteral` - Repeated dictionary key literal
393
14. `MultiValueRepeatedKeyVariable` - Repeated dictionary key variable
394
15. `LateFutureImport` - Late __future__ import
395
16. `FutureFeatureNotDefined` - Undefined __future__ feature
396
17. `UnusedVariable` - Unused variable assignment
397
18. `UnusedAnnotation` - Unused type annotation
398
19. `UnusedIndirectAssignment` - Unused global/nonlocal statement
399
20. `ReturnOutsideFunction` - Return outside function
400
21. `YieldOutsideFunction` - Yield outside function
401
22. `ContinueOutsideLoop` - Continue outside loop
402
23. `BreakOutsideLoop` - Break outside loop
403
24. `DefaultExceptNotLast` - Default except not last
404
25. `TwoStarredExpressions` - Multiple starred expressions
405
26. `TooManyExpressionsInStarredAssignment` - Too many expressions in starred assignment
406
27. `IfTuple` - If with tuple literal
407
28. `AssertTuple` - Assert with tuple
408
29. `ForwardAnnotationSyntaxError` - Forward annotation syntax error
409
30. `RaiseNotImplemented` - Raise NotImplemented
410
31. `InvalidPrintSyntax` - Invalid print syntax
411
32. `IsLiteral` - Identity comparison with literal
412
33. `FStringMissingPlaceholders` - F-string without placeholders
413
34. `TStringMissingPlaceholders` - T-string without placeholders
414
35. `StringDotFormatExtraPositionalArguments` - Extra positional args in .format()
415
36. `StringDotFormatExtraNamedArguments` - Extra named args in .format()
416
37. `StringDotFormatMissingArgument` - Missing argument in .format()
417
38. `StringDotFormatMixingAutomatic` - Mixed numbering in .format()
418
39. `StringDotFormatInvalidFormat` - Invalid format in .format()
419
40. `PercentFormatInvalidFormat` - Invalid percent format
420
41. `PercentFormatMixedPositionalAndNamed` - Mixed percent format types
421
42. `PercentFormatUnsupportedFormatCharacter` - Unsupported percent format char
422
43. `PercentFormatPositionalCountMismatch` - Percent format count mismatch
423
44. `PercentFormatExtraNamedArguments` - Extra named args in percent format
424
45. `PercentFormatMissingArgument` - Missing argument in percent format
425
46. `PercentFormatExpectedMapping` - Expected mapping in percent format
426
47. `PercentFormatExpectedSequence` - Expected sequence in percent format
427
48. `PercentFormatStarRequiresSequence` - Star requires sequence in percent format
428
429
## Usage Examples
430
431
### Message Type Filtering
432
433
```python
434
import pyflakes.api
435
from pyflakes.messages import UnusedImport, UnusedVariable, UndefinedName
436
437
def categorize_issues(code: str, filename: str):
438
"""Categorize issues by type."""
439
import ast
440
import pyflakes.checker
441
442
tree = ast.parse(code, filename=filename)
443
checker = pyflakes.checker.Checker(tree, filename=filename)
444
445
categories = {
446
'unused_imports': [],
447
'unused_variables': [],
448
'undefined_names': [],
449
'other': []
450
}
451
452
for message in checker.messages:
453
if isinstance(message, UnusedImport):
454
categories['unused_imports'].append(message)
455
elif isinstance(message, UnusedVariable):
456
categories['unused_variables'].append(message)
457
elif isinstance(message, UndefinedName):
458
categories['undefined_names'].append(message)
459
else:
460
categories['other'].append(message)
461
462
return categories
463
464
# Usage
465
code = """
466
import os
467
import sys
468
unused_var = 42
469
print(undefined_name)
470
"""
471
472
issues = categorize_issues(code, 'test.py')
473
print(f"Unused imports: {len(issues['unused_imports'])}")
474
print(f"Undefined names: {len(issues['undefined_names'])}")
475
```
476
477
### Custom Message Handling
478
479
```python
480
import pyflakes.api
481
from pyflakes.messages import Message
482
483
class CustomMessageHandler:
484
"""Custom handler for pyflakes messages."""
485
486
def __init__(self):
487
self.errors = []
488
self.warnings = []
489
self.info = []
490
491
def process_message(self, message: Message):
492
"""Process a single message."""
493
error_types = {
494
'UndefinedName', 'UndefinedLocal', 'UndefinedExport',
495
'DoctestSyntaxError', 'ForwardAnnotationSyntaxError'
496
}
497
498
warning_types = {
499
'UnusedImport', 'UnusedVariable', 'RedefinedWhileUnused',
500
'ImportStarUsed', 'IsLiteral'
501
}
502
503
message_type = type(message).__name__
504
505
if message_type in error_types:
506
self.errors.append(message)
507
elif message_type in warning_types:
508
self.warnings.append(message)
509
else:
510
self.info.append(message)
511
512
def get_summary(self):
513
"""Get summary of processed messages."""
514
return {
515
'errors': len(self.errors),
516
'warnings': len(self.warnings),
517
'info': len(self.info),
518
'total': len(self.errors) + len(self.warnings) + len(self.info)
519
}
520
521
# Usage with checker
522
import ast
523
import pyflakes.checker
524
525
code = """
526
import os
527
x = 1
528
print(y)
529
"""
530
531
tree = ast.parse(code, 'test.py')
532
checker = pyflakes.checker.Checker(tree, 'test.py')
533
534
handler = CustomMessageHandler()
535
for message in checker.messages:
536
handler.process_message(message)
537
538
summary = handler.get_summary()
539
print(f"Summary: {summary}")
540
```