Skip to content

Commit

Permalink
Fix dedent definition for search function end (#2534)
Browse files Browse the repository at this point in the history
* Test and fix

* fix noqa tests

* change type and test input name
  • Loading branch information
blablatdinov committed Oct 28, 2022
1 parent 4b7b659 commit f6ca32e
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def test_wrong(
assert_errors(visitor, [WrongEmptyLinesCountViolation])


@pytest.mark.parametrize('input_', [
@pytest.mark.parametrize('template', [
class_with_valid_method,
allow_function,
allow_function_with_comments,
Expand All @@ -202,14 +202,14 @@ def test_wrong(
module_level_empty_lines,
])
def test_success(
input_,
template,
parse_tokens,
default_options,
assert_errors,
mode,
):
"""Testing available cases."""
file_tokens = parse_tokens(mode(input_))
file_tokens = parse_tokens(mode(template))

visitor = WrongEmptyLinesCountVisitor(
default_options, file_tokens=file_tokens,
Expand All @@ -235,15 +235,20 @@ def test_zero_option(
assert_errors(visitor, [WrongEmptyLinesCountViolation])


@pytest.mark.parametrize('template', [
class_with_valid_method,
file_with_few_class,
])
def test_zero_option_with_valid_method(
template,
parse_tokens,
default_options,
assert_errors,
options,
mode,
):
"""Test zero configuration with valid method."""
file_tokens = parse_tokens(mode(class_with_valid_method))
file_tokens = parse_tokens(mode(template))
visitor = WrongEmptyLinesCountVisitor(
options(exps_for_one_empty_line=0), file_tokens=file_tokens,
)
Expand Down
36 changes: 25 additions & 11 deletions wemake_python_styleguide/visitors/ast/function_empty_lines.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import math
import tokenize
from typing import List
from typing import Iterator, List

from typing_extensions import final

Expand All @@ -26,7 +26,10 @@ def body(self) -> str:
return ''.join([target_token.string for target_token in target_tokens])

def _is_target_line(self, token: tokenize.TokenInfo) -> bool:
is_comment = '#' in token.line
stripped_token_line = token.line.strip()
is_comment = False
if stripped_token_line:
is_comment = '#' in stripped_token_line[0]
is_string = token.type == tokenize.STRING
is_multistring_end = '"""' in token.line
return is_comment or is_string or is_multistring_end
Expand All @@ -39,30 +42,41 @@ def __init__(self, file_tokens: List[tokenize.TokenInfo]) -> None:
self._file_tokens = file_tokens

def as_list(self) -> List[_Function]:
functions = []
return list(self._search_functions())

def _search_functions(self) -> Iterator[_Function]:
function_tokens: List[tokenize.TokenInfo] = []
in_function = False
function_start_column = 0
for token in self._file_tokens:
if self._is_function_start(token):
function_ended = self._is_function_end(
token,
bool(function_tokens),
function_start_column,
)
if not in_function and self._is_function_start(token):
in_function = True
elif self._is_function_end(token, bool(function_tokens)):
function_start_column = token.start[1]
elif function_ended:
in_function = False
functions.append(_Function(function_tokens))
function_start_column = 0
yield _Function(function_tokens)
function_tokens = []
if in_function:
function_tokens.append(token)
return functions

def _is_function_start(self, token: tokenize.TokenInfo) -> bool:
return token.type == tokenize.NAME and token.string == 'def'
return token.type == tokenize.NAME and token.string in {'def', 'async'}

def _is_function_end(
self,
token: tokenize.TokenInfo,
function_tokens_exists: bool,
function_start_column: int,
) -> bool:
is_dedent_token = token.type == tokenize.DEDENT and token.start[1] == 0
return is_dedent_token and function_tokens_exists
column_valid = token.start[1] in {0, function_start_column}
is_dedent_token = token.type == tokenize.DEDENT
return is_dedent_token and function_tokens_exists and column_valid


@final
Expand All @@ -84,7 +98,7 @@ def analyze(self) -> List[best_practices.WrongEmptyLinesCountViolation]:
line for line in splitted_function_body if line == ''
])
if not empty_lines_count:
return []
continue

available_empty_lines = self._available_empty_lines(
len(splitted_function_body), empty_lines_count,
Expand Down

0 comments on commit f6ca32e

Please sign in to comment.