• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pyta-uoft / pyta / 18064290483

27 Sep 2025 08:03PM UTC coverage: 94.752% (-0.2%) from 95.001%
18064290483

push

github

web-flow
Refactored pycodestyle custom renderer functions (#1237)

78 of 78 new or added lines in 1 file covered. (100.0%)

2 existing lines in 1 file now uncovered.

3521 of 3716 relevant lines covered (94.75%)

17.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.1
/python_ta/reporters/node_printers.py
1
"""Specify how errors should be rendered."""
2

3
import re
20✔
4
from enum import Enum
20✔
5

6
from astroid import nodes
20✔
7

8
NEW_BLANK_LINE_MESSAGE = "# INSERT NEW BLANK LINE HERE"
20✔
9

10

11
def render_message(msg, node, source_lines):
20✔
12
    """Render a message based on type."""
13
    renderer = CUSTOM_MESSAGES.get(msg.symbol, render_generic)
20✔
14
    yield from renderer(msg, node, source_lines)
20✔
15

16

17
def render_generic(msg, node=None, source_lines=None):
20✔
18
    """Default rendering for a message."""
19
    if node is not None:
20✔
20
        start_line, start_col = node.fromlineno, node.col_offset
20✔
21

22
        if isinstance(node, (nodes.FunctionDef, nodes.ClassDef)):
20✔
23
            end_line, end_col = start_line, None
20✔
24
        else:
25
            end_line, end_col = node.end_lineno, node.end_col_offset
20✔
26

27
        # Display up to 2 lines before node for context:
28
        yield from render_context(start_line - 2, start_line, source_lines)
20✔
29

30
        if start_line == end_line:
20✔
31
            yield (
20✔
32
                start_line,
33
                slice(start_col, end_col),
34
                LineType.ERROR,
35
                source_lines[start_line - 1],
36
            )
37
        else:
38
            yield (start_line, slice(start_col, None), LineType.ERROR, source_lines[start_line - 1])
20✔
39
            yield from (
20✔
40
                (line, slice(None, None), LineType.ERROR, source_lines[line - 1])
41
                for line in range(start_line + 1, end_line)
42
            )
43
            yield (end_line, slice(None, end_col), LineType.ERROR, source_lines[end_line - 1])
20✔
44

45
        # Display up to 2 lines after node for context:
46
        yield from render_context(end_line + 1, end_line + 3, source_lines)
20✔
47

48
    else:
49
        line = msg.line
20✔
50
        yield from render_context(line - 2, line, source_lines)
20✔
51
        yield (line, slice(None, None), LineType.ERROR, source_lines[line - 1])
20✔
52
        yield from render_context(line + 1, line + 3, source_lines)
20✔
53

54

55
def render_missing_docstring(_msg, node, source_lines=None):
20✔
56
    """Render a missing docstring message."""
57
    if isinstance(node, nodes.Module):
20✔
58
        yield (None, slice(None, None), LineType.DOCSTRING, '"""YOUR DOCSTRING HERE"""')
20✔
59
        yield from render_context(1, 3, source_lines)
20✔
60
    elif isinstance(node, nodes.ClassDef) or isinstance(node, nodes.FunctionDef):
20✔
61
        start = node.fromlineno
20✔
62
        end = node.body[0].fromlineno
20✔
63
        yield from render_context(start, end, source_lines)
20✔
64
        # Calculate indentation
65
        body = source_lines[end - 1]
20✔
66
        indentation = len(body) - len(body.lstrip())
20✔
67
        yield (
20✔
68
            None,
69
            slice(None, None),
70
            LineType.DOCSTRING,
71
            body[:indentation] + '"""YOUR DOCSTRING HERE"""',
72
        )
73
        yield from render_context(end, end + 2, source_lines)
20✔
74

75

76
def render_trailing_newlines(msg, _node, source_lines=None):
20✔
77
    """Render a trailing newlines message."""
78
    start_line = msg.line - 1
20✔
79
    yield from render_context(start_line - 2, start_line, source_lines)
20✔
80
    yield from (
20✔
81
        (line, slice(None, None), LineType.OTHER, source_lines[line - 1])
82
        for line in range(start_line, len(source_lines) + 1)
83
    )
84

85

86
def render_trailing_whitespace(msg, _node, source_lines=None):
20✔
87
    """Render a trailing whitespace message."""
88
    line = msg.line
20✔
89
    start_index, end_index = len(source_lines[line - 1].rstrip()), len(source_lines[line - 1])
20✔
90
    yield from render_context(line - 1, line, source_lines)
20✔
91
    yield (line, slice(start_index, end_index), LineType.ERROR, source_lines[line - 1])
20✔
92
    yield from render_context(line + 1, line + 2, source_lines)
20✔
93

94

95
def render_context(start, stop, source_lines):
20✔
96
    """Helper for rendering context lines."""
97
    start, stop = max(start, 1), min(stop, len(source_lines))
20✔
98
    yield from (
20✔
99
        (line, slice(None, None), LineType.CONTEXT, source_lines[line - 1])
100
        for line in range(start, stop)
101
    )
102

103

104
def render_missing_return_type(_msg, node, source_lines=None):
20✔
105
    """Render a type annotation return message."""
106
    start_line, start_col = node.fromlineno, node.parent.col_offset
20✔
107
    end_line, end_col = node.end_lineno, node.end_col_offset
20✔
108

109
    # Display up to 2 lines before node for context:
110
    yield from render_context(start_line - 2, start_line, source_lines)
20✔
111
    yield from (
20✔
112
        (line, slice(None, end_col + 1), LineType.ERROR, source_lines[line - 1])
113
        for line in range(start_line, end_line + 1)
114
    )
115
    # Display up to 2 lines after node for context:
116
    yield from render_context(end_line + 1, end_line + 3, source_lines)
20✔
117

118

119
def render_too_many_arguments(msg, node, source_lines=None):
20✔
120
    """Render a too many arguments message."""
121
    # node is a FunctionDef node so replace it with its Arguments child
122
    yield from render_generic(msg, node.args, source_lines)
20✔
123

124

125
def render_missing_space_in_doctest(msg, _node, source_lines=None):
20✔
126
    """Render a missing space in doctest message"""
127
    line = msg.line
20✔
128

129
    # Display 2 lines before and after the erroneous line
130
    yield from render_context(line - 2, line, source_lines)
20✔
131
    yield (line, slice(None, None), LineType.ERROR, source_lines[line - 1])
20✔
132
    yield from render_context(line + 1, line + 3, source_lines)
20✔
133

134

135
def get_col(msg):
20✔
136
    """Return the column number of the character causing the error"""
137
    res = re.search(r"column (\d+)", msg.msg)
20✔
138
    col = int(res.group().split()[-1])
20✔
139
    return col
20✔
140

141

142
def render_pep8_errors(msg, _node, source_lines=None):
20✔
143
    """Render a PEP8 error message."""
144
    # Extract the raw error message
145
    raw_msg = getattr(msg, "msg", "")
20✔
146

147
    # Search for the first appearance of the error code in the extracted error text
148
    matched_error = re.search(r"(E\d{3})", raw_msg)
20✔
149
    if matched_error:
20✔
150
        error_code = matched_error.group(1)
20✔
151
        # Render the appropriate error through the RENDERERS dict
152
        if error_code in RENDERERS:
20✔
153
            line = msg.line
20✔
154
            col = get_col(msg)
20✔
155
            yield from render_context(line - 3, line, source_lines)
20✔
156
            yield from RENDERERS[error_code](msg, line, col, source_lines[line - 1])
20✔
157
            yield from render_context(line + 1, line + 3, source_lines)
20✔
158
            return
20✔
159

160
    # If none of the error codes were present, render the error using the generic error renderer
161
    yield from render_generic(msg, _node, source_lines)
20✔
162

163

164
def render_blank_line(line):
20✔
165
    """Render a blank line for a PEP8 error message."""
166
    yield (line + 1, slice(None, None), LineType.ERROR, " " * 28)
20✔
167

168

169
def render_pep8_errors_e101_and_e123_and_e116(msg, line, col, source_line=None):
20✔
170
    """Render a PEP8 indentation contains mixed spaces and tabs message
171
    AND a PEP8 closing bracket does not match indentation of opening bracket's line message."""
172
    curr_idx = len(source_line) - len(source_line.lstrip())
20✔
173
    yield (line, slice(0, curr_idx), LineType.ERROR, source_line)
20✔
174

175

176
def render_pep8_errors_e115(msg, line, col, source_line=None):
20✔
177
    """Render a PEP8 expected an indented block (comment) message."""
178
    yield (
20✔
179
        line,
180
        slice(0, len(source_line)),
181
        LineType.ERROR,
182
        source_line + "  # INDENT THIS LINE",
183
    )
184

185

186
def render_pep8_errors_e122_and_e127_and_e131(msg, line, col, source_line=None):
20✔
187
    """
188
    Render a PEP8 continuation line missing indentation or outdented message, a line over-indented for visual indent
189
    message, and a continuation line unaligned for hanging indent message.
190
    """
191
    curr_line_start_index = len(source_line) - len(source_line.lstrip())
20✔
192
    end_index = curr_line_start_index if curr_line_start_index > 0 else len(source_line)
20✔
193
    yield (
20✔
194
        line,
195
        slice(0, end_index),
196
        LineType.ERROR,
197
        source_line,
198
    )
199

200

201
def render_pep8_errors_e124(msg, line, col, source_line=None):
20✔
202
    """Render a PEP8 closing bracket does not match visual indentation message."""
203
    yield (line, slice(col, col + 1), LineType.ERROR, source_line)
20✔
204

205

206
def render_pep8_errors_e125_and_e129(msg, line, col, source_line=None):
20✔
207
    """Render a PEP8 continuation line with same indent as next logical line message
208
    AND a PEP8 visually indented line with same indent as next logical line messsage"""
209
    curr_idx = len(source_line) - len(source_line.lstrip())
20✔
210
    yield (
20✔
211
        line,
212
        slice(curr_idx, len(source_line)),
213
        LineType.ERROR,
214
        source_line + " " * 2 + "# INDENT THIS LINE",
215
    )
216

217

218
def render_pep8_errors_e128(msg, line, col, source_line):
20✔
219
    """Render a PEP8 continuation line under-indented for visual indent message."""
220
    yield (line, slice(0, col if col != 0 else None), LineType.ERROR, source_line)
20✔
221

222

223
def render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272(msg, line, col, source_line=None):
20✔
224
    """Render a PEP8 whitespace after '(' message,
225
    a PEP8 whitespace before ')' message,
226
    a PEP8 whitespace before ‘,’, ‘;’, or ‘:’ message,
227
    a PEP8 whitespace before '(' message,
228
    a PEP8 multiple spaces before operator message,
229
    a PEP8 multiple spaces after keyword message,
230
    a PEP8 multiple spaces before keyword message
231
    and a PEP8 multiple spaces after operator message."""
232
    curr_idx = col + len(source_line[col:]) - len(source_line[col:].lstrip())
20✔
233

234
    yield (line, slice(col, curr_idx), LineType.ERROR, source_line)
20✔
235

236

237
def render_pep8_errors_e204(msg, line, col, source_line=None):
20✔
238
    """Render a PEP8 whitespace after decorator '@' message"""
239
    # calculates the length of the leading whitespaces by subtracting the length of everything after the first character after stripping all leading whitespaces from the total line length
240
    curr_idx = col + len(source_line[col:]) - len(source_line[col + 1 :].lstrip())
20✔
241

242
    yield (line, slice(col, curr_idx), LineType.ERROR, source_line)
20✔
243

244

245
def render_pep8_errors_e223_and_e274(msg, line, col, source_line=None):
20✔
246
    """Render a PEP8 tab before operator message and a PEP8 tab before keyword message."""
247
    curr_idx = col + len(source_line[col:]) - len(source_line[col:].lstrip("\t"))
20✔
248

249
    yield (line, slice(col, curr_idx), LineType.ERROR, source_line)
20✔
250

251

252
def render_pep8_errors_e224_and_e273(msg, line, col, source_line):
20✔
253
    """Render a PEP8 tab after operator message and a PEP8 tab after keyword message."""
254
    curr_idx = col + len(source_line[col:]) - len(source_line[col:].lstrip("\t"))
20✔
255

256
    yield (line, slice(col, curr_idx), LineType.ERROR, source_line)
20✔
257

258

259
def render_pep8_errors_e225(msg, line, col, source_line):
20✔
260
    """Render a PEP8 missing whitespace around operator message"""
261
    curr_idx = col + 1
20✔
262

263
    two_char_operators = {
20✔
264
        "==",
265
        ">=",
266
        "<=",
267
        "!=",
268
        ":=",
269
        "&=",
270
        "->",
271
        "%=",
272
        "/=",
273
        "+=",
274
        "-=",
275
        "*=",
276
        "|=",
277
        "^=",
278
        "@=",
279
    }
280
    three_char_operators = {"//=", ">>=", "<<=", "**="}
20✔
281
    # highlight multiple characters for operators that are longer than one character
282
    if source_line[col : col + 2] in two_char_operators:
20✔
283
        curr_idx += 1
20✔
284
    elif source_line[col : col + 3] in three_char_operators:
20✔
285
        curr_idx += 2
20✔
286

287
    yield (line, slice(col, curr_idx), LineType.ERROR, source_line)
20✔
288

289

290
def render_pep8_errors_e226(msg, line, col, source_line):
20✔
291
    """Render a PEP8 missing whitespace around arithmetic operator message"""
292
    end_idx = col + 1
20✔
293

294
    multi_char_operators = {"//"}
20✔
295
    # highlight multiple characters for arithmetic operators that are longer than one character
296
    if source_line[col : col + 2] in multi_char_operators:
20✔
297
        end_idx += 1
20✔
298

299
    yield (line, slice(col, end_idx), LineType.ERROR, source_line)
20✔
300

301

302
def render_pep8_errors_e227(msg, line, col, source_line=None):
20✔
303
    """Render a PEP8 missing whitespace around bitwise or shift operator message."""
304
    # Check which operator to get the correct range of the line to highlight.
305
    # Default highlight is one character, but may be updated to two.
306
    # Note that only binary bitwise operators that are more than one character are included.
307
    operators = {">>", "<<"}
20✔
308
    end_idx = col + 1
20✔
309
    end_idx = end_idx + 1 if source_line[col : col + 2] in operators else end_idx
20✔
310

311
    yield (line, slice(col, end_idx), LineType.ERROR, source_line)
20✔
312

313

314
def render_pep8_errors_e228(msg, line, col, source_line=None):
20✔
315
    """Render a PEP8 missing whitespace around modulo operator message."""
316
    yield (
20✔
317
        line,
318
        slice(col, col + 1),
319
        LineType.ERROR,
320
        source_line + "  # INSERT A SPACE BEFORE AND AFTER THE % OPERATOR",
321
    )
322

323

324
def render_pep8_errors_e231(msg, line, col, source_line=None):
20✔
325
    curr_idx = col + 1
20✔
326

327
    yield (line, slice(col, curr_idx), LineType.ERROR, source_line)
20✔
328

329

330
def render_pep8_errors_e251(msg, line, col, source_line=None):
20✔
331
    """Render a PEP8 unexpected spaces around keyword / parameter equals message."""
332
    equals_sign_idx = source_line[col:].find("=")
20✔
333
    code = source_line[col : col + equals_sign_idx if equals_sign_idx != -1 else None]
20✔
334
    end_idx = col + len(code) - len(code.lstrip())
20✔
335

336
    yield (line, slice(col, end_idx), LineType.ERROR, source_line)
20✔
337

338

339
def render_pep8_errors_e261(msg, line, col, source_line=None):
20✔
340
    """Render a PEP8 at least two spaces before inline comment message."""
341
    yield (
20✔
342
        line,
343
        slice(col, len(source_line)),
344
        LineType.ERROR,
345
        source_line + "  # INSERT TWO SPACES BEFORE THE '#'",
346
    )
347

348

349
def render_pep8_errors_e262(msg, line, col, source_line=None):
20✔
350
    """Render a PEP8 inline comment should start with '# ' message"""
351
    keyword_idx = len(source_line) - len(source_line[col:].lstrip("# \t"))
20✔
352

353
    yield (line, slice(col, keyword_idx), LineType.ERROR, source_line)
20✔
354

355

356
def render_pep8_errors_e265(msg, line, col, source_line=None):
20✔
357
    """Render a PEP8 block comment should start with '# ' message."""
358
    yield (
20✔
359
        line,
360
        slice(0, len(source_line)),
361
        LineType.ERROR,
362
        source_line + "  # INSERT SPACE AFTER THE '#'",
363
    )
364

365

366
def render_pep8_errors_e266(msg, line, col, source_line=None):
20✔
367
    """Render a PEP8 too many leading ‘#’ for block comment message."""
368
    curr_idx = col + len(source_line[col:]) - len(source_line[col:].lstrip("#"))
20✔
369

370
    yield (
20✔
371
        line,
372
        slice(col, curr_idx),
373
        LineType.ERROR,
374
        source_line + "  # THERE SHOULD ONLY BE ONE '#'",
375
    )
376

377

378
def render_pep8_errors_e275(msg, line, col, source_line=None):
20✔
379
    """Render a PEP8 missing whitespace after keyword message."""
380
    # Get the range for highlighting the corresponding keyword.
381
    keyword = source_line[:col].split()[-1]
20✔
382
    keyword_idx = source_line.index(keyword)
20✔
383

384
    yield (
20✔
385
        line,
386
        slice(keyword_idx, col),
387
        LineType.ERROR,
388
        source_line + "  # INSERT SPACE AFTER KEYWORD",
389
    )
390

391

392
def render_pep8_errors_e301(msg, line, col, source_line=None):
20✔
393
    """Render a PEP8 expected 1 blank line message."""
394
    line -= 1
20✔
395
    body = source_line[line]
20✔
396
    indentation = len(body) - len(body.lstrip())
20✔
397
    yield (
20✔
398
        None,
399
        slice(None, None),
400
        LineType.ERROR,
401
        body[:indentation] + NEW_BLANK_LINE_MESSAGE,
402
    )
403

404

405
def render_pep8_errors_e302(msg, line, col, source_line=None):
20✔
406
    """Render a PEP8 expected 2 blank lines message."""
407
    line -= 1
20✔
408
    if "found 0" in msg.msg:
20✔
409
        yield from (
20✔
410
            (
411
                None,
412
                slice(None, None),
413
                LineType.ERROR,
414
                NEW_BLANK_LINE_MESSAGE,
415
            )
416
            for _ in range(0, 2)
417
        )
418
    else:
419
        line -= 1
20✔
420
        yield from render_blank_line(line)
20✔
421
        yield (None, slice(None, None), LineType.ERROR, NEW_BLANK_LINE_MESSAGE)
20✔
422

423

424
def render_pep8_errors_e303(msg, line, col, source_line=None):
20✔
425
    """Render a PEP8 too many blank lines message."""
426
    line -= 1
20✔
427
    while source_line.strip() == "":
20✔
UNCOV
428
        line -= 1
×
429

430
    body = source_line[msg.line - 1]
20✔
431
    indentation = len(body) - len(body.lstrip())
20✔
432
    yield from (
20✔
433
        (curr_line, slice(None, None), LineType.ERROR, " " * (indentation + 28))
434
        for curr_line in range(line + 1, msg.line)
435
    )
436

437

438
def render_pep8_errors_e304(msg, line, col, source_line=None):
20✔
439
    """Render a PEP8 blank lines found after function decorator message."""
440
    line -= 1
20✔
441
    while source_line.strip() == "":
20✔
UNCOV
442
        line -= 1
×
443

444
    yield from (
20✔
445
        (curr_line, slice(None, None), LineType.ERROR, " " * 28)
446
        for curr_line in range(line + 1, msg.line)
447
    )
448

449

450
def render_pep8_errors_e305(msg, line, col, source_line=None):
20✔
451
    """Render a PEP8 expected 2 blank lines after class or function definition message."""
452
    line -= 1
20✔
453
    if "found 0" in msg.msg:
20✔
454
        yield from (
20✔
455
            (
456
                None,
457
                slice(None, None),
458
                LineType.ERROR,
459
                NEW_BLANK_LINE_MESSAGE,
460
            )
461
            for _ in range(0, 2)
462
        )
463
    else:
464
        line -= 1
20✔
465
        yield from render_blank_line(line)
20✔
466
        yield (None, slice(None, None), LineType.ERROR, NEW_BLANK_LINE_MESSAGE)
20✔
467

468

469
def render_pep8_errors_e306(msg, line, col, source_line=None):
20✔
470
    """Render a PEP8 expected 1 blank line before a nested definition message."""
471
    line -= 1
20✔
472
    body = source_line[line]
20✔
473
    indentation = len(body) - len(body.lstrip())
20✔
474
    yield (
20✔
475
        None,
476
        slice(None, None),
477
        LineType.ERROR,
478
        body[:indentation] + NEW_BLANK_LINE_MESSAGE,
479
    )
480

481

482
def render_pep8_errors_e502(msg, line, col, source_line=None):
20✔
483
    """Render a PEP8 the backslash is redundant between brackets."""
484
    yield (line, slice(col, col + 1), LineType.ERROR, source_line)
20✔
485

486

487
def render_missing_return_statement(msg, node, source_lines=None):
20✔
488
    """
489
    Render a missing return statements message
490
    """
491
    yield from render_context(msg.line, msg.end_line + 1, source_lines)
20✔
492

493
    # calculate indentation for the insertion point
494
    body = source_lines[msg.end_line - 1]
20✔
495
    indentation = len(source_lines[msg.line - 1]) - len(source_lines[msg.line - 1].lstrip())
20✔
496

497
    # determine whether reaching the end of function
498
    first_statement_line = node.end_lineno if len(node.body) == 0 else node.body[0].lineno
20✔
499
    function_indentation = len(source_lines[first_statement_line - 1]) - len(
20✔
500
        source_lines[first_statement_line - 1].lstrip()
501
    )
502

503
    if msg.end_line == node.end_lineno and indentation == function_indentation:
20✔
504
        insertion_text = body[:indentation] + "# INSERT RETURN STATEMENT HERE"
20✔
505
    else:
506
        insertion_text = body[:indentation] + "# INSERT RETURN STATEMENT HERE (OR BELOW)"
20✔
507

508
    # insert the message
509
    yield (
20✔
510
        None,
511
        slice(indentation, None),
512
        LineType.ERROR,
513
        insertion_text,
514
    )
515

516
    yield from render_context(msg.end_line + 1, msg.end_line + 3, source_lines)
20✔
517

518

519
def render_static_type_checker_errors(msg, _node=None, source_lines=None):
20✔
520
    """Render a message for incompatible argument types."""
521
    start_line = msg.line
20✔
522
    start_col = msg.column
20✔
523
    end_line = msg.end_line
20✔
524
    end_col = msg.end_column
20✔
525
    yield from render_context(start_line - 2, start_line, source_lines)
20✔
526

527
    if start_line == end_line:
20✔
528
        yield (
20✔
529
            start_line,
530
            slice(start_col - 1, end_col),
531
            LineType.ERROR,
532
            source_lines[start_line - 1],
533
        )
534
    else:
535
        yield (start_line, slice(start_col - 1, None), LineType.ERROR, source_lines[start_line - 1])
20✔
536
        yield from (
20✔
537
            (line, slice(None, None), LineType.ERROR, source_lines)
538
            for line in range(start_line + 1, end_line)
539
        )
540
        yield (end_line, slice(None, end_col), LineType.ERROR, source_lines[end_line - 1])
20✔
541
    yield from render_context(end_line + 1, end_line + 3, source_lines)
20✔
542

543

544
CUSTOM_MESSAGES = {
20✔
545
    "missing-module-docstring": render_missing_docstring,
546
    "missing-class-docstring": render_missing_docstring,
547
    "missing-function-docstring": render_missing_docstring,
548
    "trailing-newlines": render_trailing_newlines,
549
    "trailing-whitespace": render_trailing_whitespace,
550
    "missing-return-type": render_missing_return_type,
551
    "too-many-arguments": render_too_many_arguments,
552
    "missing-space-in-doctest": render_missing_space_in_doctest,
553
    "pep8-errors": render_pep8_errors,
554
    "missing-return-statement": render_missing_return_statement,
555
    "incompatible-argument-type": render_static_type_checker_errors,
556
    "incompatible-assignment": render_static_type_checker_errors,
557
    "list-item-type-mismatch": render_static_type_checker_errors,
558
    "unsupported-operand-types": render_static_type_checker_errors,
559
    "union-attr-error": render_static_type_checker_errors,
560
    "dict-item-type-mismatch": render_static_type_checker_errors,
561
}
562

563
RENDERERS = {
20✔
564
    "E101": render_pep8_errors_e101_and_e123_and_e116,
565
    "E123": render_pep8_errors_e101_and_e123_and_e116,
566
    "E115": render_pep8_errors_e115,
567
    "E116": render_pep8_errors_e101_and_e123_and_e116,
568
    "E122": render_pep8_errors_e122_and_e127_and_e131,
569
    "E127": render_pep8_errors_e122_and_e127_and_e131,
570
    "E131": render_pep8_errors_e122_and_e127_and_e131,
571
    "E124": render_pep8_errors_e124,
572
    "E125": render_pep8_errors_e125_and_e129,
573
    "E129": render_pep8_errors_e125_and_e129,
574
    "E128": render_pep8_errors_e128,
575
    "E201": render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272,
576
    "E202": render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272,
577
    "E203": render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272,
578
    "E204": render_pep8_errors_e204,
579
    "E211": render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272,
580
    "E221": render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272,
581
    "E222": render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272,
582
    "E223": render_pep8_errors_e223_and_e274,
583
    "E224": render_pep8_errors_e224_and_e273,
584
    "E225": render_pep8_errors_e225,
585
    "E231": render_pep8_errors_e231,
586
    "E273": render_pep8_errors_e224_and_e273,
587
    "E274": render_pep8_errors_e223_and_e274,
588
    "E226": render_pep8_errors_e226,
589
    "E227": render_pep8_errors_e227,
590
    "E228": render_pep8_errors_e228,
591
    "E251": render_pep8_errors_e251,
592
    "E261": render_pep8_errors_e261,
593
    "E262": render_pep8_errors_e262,
594
    "E265": render_pep8_errors_e265,
595
    "E266": render_pep8_errors_e266,
596
    "E271": render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272,
597
    "E272": render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272,
598
    "E275": render_pep8_errors_e275,
599
    "E301": render_pep8_errors_e301,
600
    "E302": render_pep8_errors_e302,
601
    "E303": render_pep8_errors_e303,
602
    "E304": render_pep8_errors_e304,
603
    "E305": render_pep8_errors_e305,
604
    "E306": render_pep8_errors_e306,
605
    "E502": render_pep8_errors_e502,
606
}
607

608

609
class LineType(Enum):
20✔
610
    """An enumeration for _add_line method line types."""
611

612
    ERROR = 1  # line with error
20✔
613
    CONTEXT = 2  # non-error/other line added for context
20✔
614
    OTHER = 3  # line included in source but not error
20✔
615
    ELLIPSIS = 5  # code replaced with ellipsis
20✔
616
    DOCSTRING = 6  # docstring needed warning
20✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc