Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### 🐛 Bug fixes

- Fixed issue that caused PEP8 errors E301, E302, E303, E304, E305 and E306 to not render properly

### 🔧 Internal changes

- Added tests for node_printers.py functions rendering the PEP8 error messages: E101, E116, E124, E128, E201, E202
Expand Down
121 changes: 57 additions & 64 deletions python_ta/reporters/node_printers.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,14 @@ def render_pep8_errors(msg, _node, source_lines=None):
# Render the appropriate error through the RENDERERS dict
if error_code in RENDERERS:
line = msg.line
col = msg.column
yield from render_context(line - 3, line, source_lines)
yield from RENDERERS[error_code](msg, line, col, source_lines[line - 1])
yield from render_context(line + 1, line + 3, source_lines)
require_source_lines_renderers = {"E302", "E303", "E304", "E305"}
if error_code in require_source_lines_renderers:
yield from RENDERERS[error_code](msg, line, source_lines)
else:
col = msg.column
yield from render_context(line - 3, line, source_lines)
yield from RENDERERS[error_code](line, col, source_lines[line - 1])
yield from render_context(line + 1, line + 3, source_lines)
return

# If none of the error codes were present, render the error using the generic error renderer
Expand All @@ -159,14 +163,14 @@ def render_blank_line(line):
yield (line + 1, slice(None, None), LineType.ERROR, " " * 28)


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


def render_pep8_errors_e115(msg, line, col, source_line=None):
def render_pep8_errors_e115(line, col, source_line=None):
"""Render a PEP8 expected an indented block (comment) message."""
yield (
line,
Expand All @@ -176,7 +180,7 @@ def render_pep8_errors_e115(msg, line, col, source_line=None):
)


def render_pep8_errors_e122_and_e127_and_e131(msg, line, col, source_line=None):
def render_pep8_errors_e122_and_e127_and_e131(line, col, source_line=None):
"""
Render a PEP8 continuation line missing indentation or outdented message, a line over-indented for visual indent
message, and a continuation line unaligned for hanging indent message.
Expand All @@ -191,12 +195,12 @@ def render_pep8_errors_e122_and_e127_and_e131(msg, line, col, source_line=None):
)


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


def render_pep8_errors_e125_and_e129(msg, line, col, source_line=None):
def render_pep8_errors_e125_and_e129(line, col, source_line=None):
"""Render a PEP8 continuation line with same indent as next logical line message
AND a PEP8 visually indented line with same indent as next logical line messsage"""
curr_idx = len(source_line) - len(source_line.lstrip())
Expand All @@ -208,12 +212,12 @@ def render_pep8_errors_e125_and_e129(msg, line, col, source_line=None):
)


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


def render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272(msg, line, col, source_line=None):
def render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272(line, col, source_line=None):
"""Render a PEP8 whitespace after '(' message,
a PEP8 whitespace before ')' message,
a PEP8 whitespace before ‘,’, ‘;’, or ‘:’ message,
Expand All @@ -227,29 +231,29 @@ def render_pep8_errors_e201_e202_e203_e211_e221_e222_e271_e272(msg, line, col, s
yield (line, slice(col, curr_idx), LineType.ERROR, source_line)


def render_pep8_errors_e204(msg, line, col, source_line=None):
def render_pep8_errors_e204(line, col, source_line=None):
"""Render a PEP8 whitespace after decorator '@' message"""
# 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
curr_idx = col + len(source_line[col:]) - len(source_line[col + 1 :].lstrip())

yield (line, slice(col, curr_idx), LineType.ERROR, source_line)


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

yield (line, slice(col, curr_idx), LineType.ERROR, source_line)


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

yield (line, slice(col, curr_idx), LineType.ERROR, source_line)


def render_pep8_errors_e225(msg, line, col, source_line):
def render_pep8_errors_e225(line, col, source_line):
"""Render a PEP8 missing whitespace around operator message"""
curr_idx = col + 1

Expand Down Expand Up @@ -280,7 +284,7 @@ def render_pep8_errors_e225(msg, line, col, source_line):
yield (line, slice(col, curr_idx), LineType.ERROR, source_line)


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

Expand All @@ -292,7 +296,7 @@ def render_pep8_errors_e226(msg, line, col, source_line):
yield (line, slice(col, end_idx), LineType.ERROR, source_line)


def render_pep8_errors_e227(msg, line, col, source_line=None):
def render_pep8_errors_e227(line, col, source_line=None):
"""Render a PEP8 missing whitespace around bitwise or shift operator message."""
# Check which operator to get the correct range of the line to highlight.
# Default highlight is one character, but may be updated to two.
Expand All @@ -304,7 +308,7 @@ def render_pep8_errors_e227(msg, line, col, source_line=None):
yield (line, slice(col, end_idx), LineType.ERROR, source_line)


def render_pep8_errors_e228(msg, line, col, source_line=None):
def render_pep8_errors_e228(line, col, source_line=None):
"""Render a PEP8 missing whitespace around modulo operator message."""
yield (
line,
Expand All @@ -314,13 +318,13 @@ def render_pep8_errors_e228(msg, line, col, source_line=None):
)


def render_pep8_errors_e231(msg, line, col, source_line=None):
def render_pep8_errors_e231(line, col, source_line=None):
curr_idx = col + 1

yield (line, slice(col, curr_idx), LineType.ERROR, source_line)


def render_pep8_errors_e251(msg, line, col, source_line=None):
def render_pep8_errors_e251(line, col, source_line=None):
"""Render a PEP8 unexpected spaces around keyword / parameter equals message."""
equals_sign_idx = source_line[col:].find("=")
code = source_line[col : col + equals_sign_idx if equals_sign_idx != -1 else None]
Expand All @@ -329,7 +333,7 @@ def render_pep8_errors_e251(msg, line, col, source_line=None):
yield (line, slice(col, end_idx), LineType.ERROR, source_line)


def render_pep8_errors_e261(msg, line, col, source_line=None):
def render_pep8_errors_e261(line, col, source_line=None):
"""Render a PEP8 at least two spaces before inline comment message."""
yield (
line,
Expand All @@ -339,14 +343,14 @@ def render_pep8_errors_e261(msg, line, col, source_line=None):
)


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

yield (line, slice(col, keyword_idx), LineType.ERROR, source_line)


def render_pep8_errors_e265(msg, line, col, source_line=None):
def render_pep8_errors_e265(line, col, source_line=None):
"""Render a PEP8 block comment should start with '# ' message."""
yield (
line,
Expand All @@ -356,7 +360,7 @@ def render_pep8_errors_e265(msg, line, col, source_line=None):
)


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

Expand All @@ -368,7 +372,7 @@ def render_pep8_errors_e266(msg, line, col, source_line=None):
)


def render_pep8_errors_e275(msg, line, col, source_line=None):
def render_pep8_errors_e275(line, col, source_line=None):
"""Render a PEP8 missing whitespace after keyword message."""
# Get the range for highlighting the corresponding keyword.
keyword = source_line[:col].split()[-1]
Expand All @@ -382,23 +386,21 @@ def render_pep8_errors_e275(msg, line, col, source_line=None):
)


def render_pep8_errors_e301(msg, line, col, source_line=None):
def render_pep8_errors_e301(line, col, source_line=None):
"""Render a PEP8 expected 1 blank line message."""
line -= 1
body = source_line[line]
indentation = len(body) - len(body.lstrip())
indentation = len(source_line) - len(source_line.lstrip())
yield (
None,
slice(None, None),
LineType.ERROR,
body[:indentation] + NEW_BLANK_LINE_MESSAGE,
source_line[:indentation] + NEW_BLANK_LINE_MESSAGE,
)


def render_pep8_errors_e302(msg, line, col, source_line=None):
def render_pep8_errors_e302(msg, line, source_lines=None):
"""Render a PEP8 expected 2 blank lines message."""
line -= 1
if "found 0" in msg.msg:
yield from render_context(line - 3, line, source_lines)
yield from (
(
None,
Expand All @@ -409,41 +411,33 @@ def render_pep8_errors_e302(msg, line, col, source_line=None):
for _ in range(0, 2)
)
else:
line -= 1
yield from render_context(line - 3, line - 1, source_lines)
yield from render_blank_line(line)
yield (None, slice(None, None), LineType.ERROR, NEW_BLANK_LINE_MESSAGE)
yield from render_context(line, line + 3, source_lines)


def render_pep8_errors_e303(msg, line, col, source_line=None):
"""Render a PEP8 too many blank lines message."""
line -= 1
while source_line.strip() == "":
line -= 1

body = source_line[msg.line - 1]
def render_pep8_errors_e303_and_e304(msg, line, source_lines=None):
"""Render a PEP8 too many blank lines message
and a PEP8 blank lines found after function decorator message
"""
dline = line
while source_lines[dline - 2].strip() == "":
dline -= 1
body = source_lines[line - 1]
indentation = len(body) - len(body.lstrip())
yield from render_context(dline - 3, dline, source_lines)
yield from (
(curr_line, slice(None, None), LineType.ERROR, " " * (indentation + 28))
for curr_line in range(line + 1, msg.line)
for curr_line in range(dline, line)
)
yield from render_context(line, line + 3, source_lines)


def render_pep8_errors_e304(msg, line, col, source_line=None):
"""Render a PEP8 blank lines found after function decorator message."""
line -= 1
while source_line.strip() == "":
line -= 1

yield from (
(curr_line, slice(None, None), LineType.ERROR, " " * 28)
for curr_line in range(line + 1, msg.line)
)


def render_pep8_errors_e305(msg, line, col, source_line=None):
def render_pep8_errors_e305(msg, line, source_lines=None):
"""Render a PEP8 expected 2 blank lines after class or function definition message."""
line -= 1
if "found 0" in msg.msg:
yield from render_context(line - 3, line, source_lines)
yield from (
(
None,
Expand All @@ -454,25 +448,24 @@ def render_pep8_errors_e305(msg, line, col, source_line=None):
for _ in range(0, 2)
)
else:
line -= 1
yield from render_context(line - 3, line - 1, source_lines)
yield from render_blank_line(line)
yield (None, slice(None, None), LineType.ERROR, NEW_BLANK_LINE_MESSAGE)
yield from render_context(line, line + 3, source_lines)


def render_pep8_errors_e306(msg, line, col, source_line=None):
def render_pep8_errors_e306(line, col, source_line=None):
"""Render a PEP8 expected 1 blank line before a nested definition message."""
line -= 1
body = source_line[line]
indentation = len(body) - len(body.lstrip())
indentation = len(source_line) - len(source_line.lstrip())
yield (
None,
slice(None, None),
LineType.ERROR,
body[:indentation] + NEW_BLANK_LINE_MESSAGE,
source_line[:indentation] + NEW_BLANK_LINE_MESSAGE,
)


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

Expand Down Expand Up @@ -591,8 +584,8 @@ def render_static_type_checker_errors(msg, _node=None, source_lines=None):
"E275": render_pep8_errors_e275,
"E301": render_pep8_errors_e301,
"E302": render_pep8_errors_e302,
"E303": render_pep8_errors_e303,
"E304": render_pep8_errors_e304,
"E303": render_pep8_errors_e303_and_e304,
"E304": render_pep8_errors_e303_and_e304,
"E305": render_pep8_errors_e305,
"E306": render_pep8_errors_e306,
"E502": render_pep8_errors_e502,
Expand Down