0
# Error Processing
1
2
Error representation, deduplication, and formatting capabilities for managing linting results across multiple tools and output formats. Pylama provides comprehensive error handling with intelligent deduplication and flexible formatting options.
3
4
## Type Imports
5
6
```python
7
from typing import Any, Dict, Generator, List, Optional, Set, Tuple
8
from argparse import Namespace
9
```
10
11
## Capabilities
12
13
### Error Representation
14
15
Core error class that represents individual linting issues with comprehensive metadata.
16
17
```python { .api }
18
class Error:
19
"""
20
Represents a single linting error with source information.
21
22
Attributes:
23
filename: str - File path where error occurred
24
lnum: int - Line number (1-based)
25
col: int - Column number (1-based)
26
message: str - Error message text
27
etype: str - Error type (E=error, W=warning, etc.)
28
source: str - Linter that generated the error
29
number: str - Error code (extracted from text)
30
"""
31
32
def __init__(
33
self,
34
source: str = "pylama",
35
col: int = 1,
36
lnum: int = 1,
37
type: Optional[str] = None,
38
text: str = "unknown error",
39
filename: str = "",
40
number: str = "",
41
**_
42
):
43
"""
44
Initialize error with position and message information.
45
46
Args:
47
source: Name of linter that found the error
48
col: Column number (1-based)
49
lnum: Line number (1-based)
50
type: Error type/severity (stored as etype attribute)
51
text: Error message text (stored as message attribute)
52
filename: File path where error occurred
53
number: Error code number
54
**_: Additional unused parameters
55
"""
56
57
def to_dict(self) -> Dict[str, Any]:
58
"""
59
Convert error to dictionary representation.
60
61
Returns:
62
Dict[str, Any]: Error data as dictionary with keys:
63
- filename, lnum, col, message, etype, source, number
64
"""
65
66
def format(self, template: str) -> str:
67
"""
68
Format error using template string.
69
70
Args:
71
template: Format string with placeholders like {filename}, {lnum}, etc.
72
73
Returns:
74
str: Formatted error message
75
76
Available template variables:
77
- {filename}: File path
78
- {lnum}: Line number
79
- {col}: Column number
80
- {message}: Error message text
81
- {etype}: Error type
82
- {source}: Linter name
83
- {number}: Error code
84
"""
85
```
86
87
### Error Deduplication
88
89
Remove duplicate errors that are reported by multiple linters for the same issue.
90
91
```python { .api }
92
def remove_duplicates(errors: List[Error]) -> Generator[Error, None, None]:
93
"""
94
Remove duplicate errors from different linters.
95
96
Args:
97
errors: List of Error objects potentially containing duplicates
98
99
Yields:
100
Error: Unique errors with duplicates removed
101
102
Deduplication rules:
103
- Errors at same location with equivalent meanings are deduplicated
104
- Priority given to more specific linters (e.g., pycodestyle over pylint for style)
105
- Common duplicate patterns handled automatically (see DUPLICATES mapping)
106
"""
107
```
108
109
### Error Sorting
110
111
Sort errors according to configurable criteria.
112
113
```python { .api }
114
def default_sorter(err: Error) -> Any:
115
"""
116
Default error sorting function.
117
118
Args:
119
err: Error object to generate sort key for
120
121
Returns:
122
Any: Sort key (typically line number for default sorter)
123
124
Default sort order:
125
- Line number (ascending)
126
"""
127
```
128
129
### Error Display
130
131
Format and output errors using various output formats.
132
133
```python { .api }
134
def display_errors(errors: List[Error], options: Namespace):
135
"""
136
Format and display errors using specified format.
137
138
Args:
139
errors: List of Error objects to display
140
options: Configuration options containing format settings
141
142
Supported formats:
143
- 'json': JSON array of error dictionaries
144
- 'pylint': Pylint-compatible format
145
- 'pycodestyle': pycodestyle-compatible format
146
- 'parsable': Default parsable format (same as default)
147
- Custom format strings
148
149
Output is sent to the configured logger at WARNING level.
150
"""
151
```
152
153
## Duplicate Error Mappings
154
155
Pylama automatically deduplicates common errors reported by multiple linters:
156
157
```python { .api }
158
DUPLICATES: Dict[Tuple[str, str], Set] = {
159
# Multiple statements on one line
160
("pycodestyle", "E701"): {("pylint", "C0321")},
161
162
# Unused variable
163
("pylint", "W0612"): {("pyflakes", "W0612")},
164
165
# Undefined variable
166
("pylint", "E0602"): {("pyflakes", "E0602")},
167
168
# Unused import
169
("pylint", "W0611"): {("pyflakes", "W0611")},
170
171
# Whitespace issues
172
("pylint", "C0326"): {
173
("pycodestyle", "E202"), # whitespace before ')'
174
("pycodestyle", "E211"), # whitespace before '('
175
("pycodestyle", "E222"), # multiple spaces after operator
176
("pycodestyle", "E225"), # missing whitespace around operator
177
("pycodestyle", "E251"), # unexpected spaces
178
},
179
180
# Long lines
181
("pylint", "C0301"): {("pycodestyle", "E501")},
182
183
# Other common duplicates...
184
}
185
```
186
187
## Usage Examples
188
189
### Basic Error Processing
190
191
```python
192
from pylama.main import check_paths
193
from pylama.config import parse_options
194
from pylama.errors import remove_duplicates
195
196
# Get errors from checking
197
options = parse_options(['--linters=pycodestyle,pylint', 'myfile.py'])
198
errors = check_paths(['myfile.py'], options)
199
200
# Remove duplicates
201
unique_errors = list(remove_duplicates(errors))
202
print(f"Found {len(errors)} total, {len(unique_errors)} unique errors")
203
```
204
205
### Custom Error Formatting
206
207
```python
208
from pylama.errors import Error
209
210
# Create error object
211
error = Error(
212
source="pycodestyle",
213
col=10,
214
lnum=42,
215
type="E",
216
text="E501 line too long (82 > 79 characters)",
217
filename="example.py"
218
)
219
220
# Format with different templates
221
default_format = "{filename}:{lnum}:{col} [{etype}] {number} {message} [{source}]"
222
pylint_format = "{filename}:{lnum}: [{etype}] {number} {message} [{source}]"
223
224
print(error.format(default_format))
225
print(error.format(pylint_format))
226
227
# Convert to dictionary
228
error_dict = error.to_dict()
229
print(error_dict)
230
231
# Access error message
232
print(f"Error message: {error.message}")
233
```
234
235
### JSON Output Processing
236
237
```python
238
import json
239
from pylama.main import check_paths
240
from pylama.config import parse_options
241
242
# Configure for JSON output
243
options = parse_options(['--format=json', '--linters=pyflakes', 'myfile.py'])
244
errors = check_paths(['myfile.py'], options)
245
246
# Process as JSON data
247
error_data = [error.to_dict() for error in errors]
248
json_output = json.dumps(error_data, indent=2)
249
print(json_output)
250
251
# Filter by error type
252
warnings = [e for e in errors if e.etype == 'W']
253
errors_only = [e for e in errors if e.etype == 'E']
254
255
# Access error messages
256
for error in errors:
257
print(f"File: {error.filename}, Message: {error.message}")
258
```
259
260
### Custom Error Sorting
261
262
```python
263
from pylama.errors import Error
264
265
errors = [
266
Error(source="pycodestyle", col=5, lnum=10, type="E", text="E501 line too long", filename="file1.py"),
267
Error(source="pylint", col=1, lnum=5, type="W", text="W0612 unused variable", filename="file1.py"),
268
Error(source="pyflakes", col=1, lnum=1, type="F", text="F401 unused import", filename="file2.py"),
269
]
270
271
# Sort by severity (errors first, then warnings)
272
def severity_sorter(err):
273
severity_order = {'E': 0, 'F': 1, 'W': 2}
274
return (severity_order.get(err.etype, 999), err.filename, err.lnum)
275
276
sorted_errors = sorted(errors, key=severity_sorter)
277
278
# Sort by error source (linter)
279
def source_sorter(err):
280
return (err.source, err.filename, err.lnum)
281
282
sorted_by_source = sorted(errors, key=source_sorter)
283
```
284
285
### Error Analysis
286
287
```python
288
from collections import defaultdict
289
from pylama.main import check_paths
290
from pylama.config import parse_options
291
292
# Analyze error patterns
293
options = parse_options(['src/'])
294
errors = check_paths(['src/'], options)
295
296
# Group by error type
297
by_type = defaultdict(list)
298
for error in errors:
299
by_type[error.etype].append(error)
300
301
# Group by source linter
302
by_source = defaultdict(list)
303
for error in errors:
304
by_source[error.source].append(error)
305
306
# Group by file
307
by_file = defaultdict(list)
308
for error in errors:
309
by_file[error.filename].append(error)
310
311
# Print summary
312
print("Error Summary:")
313
print(f"Total errors: {len(errors)}")
314
print(f"Files with issues: {len(by_file)}")
315
print(f"Error types: {list(by_type.keys())}")
316
print(f"Linters used: {list(by_source.keys())}")
317
318
# Print messages for each error
319
for error in errors:
320
print(f"{error.filename}:{error.lnum} - {error.message}")
321
```
322
323
## Format Templates
324
325
```python { .api }
326
DEFAULT_FORMAT: str = "{filename}:{lnum}:{col} [{etype}] {number} {message} [{source}]"
327
328
MESSAGE_FORMATS: Dict[str, str] = {
329
"pylint": "{filename}:{lnum}: [{etype}] {number} {message} [{source}]",
330
"pycodestyle": "{filename}:{lnum}:{col} {number} {message} [{source}]",
331
"parsable": DEFAULT_FORMAT,
332
}
333
```