Skip to content

Commit

Permalink
Merge 5a7b108 into 5846009
Browse files Browse the repository at this point in the history
  • Loading branch information
myslak71 committed Aug 3, 2019
2 parents 5846009 + 5a7b108 commit 7f86e92
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 125 deletions.
52 changes: 32 additions & 20 deletions flake8_koles/checker.py
Expand Up @@ -18,7 +18,7 @@ class KolesChecker:

name = 'flake8-koles'
options = optparse.Values()
SWEAR_DATA_DIR = '/data/swear_list'
SWEAR_DATA_DIR = 'data/swear_list'
version = __version__

def __init__(self, tree: ast.Module, filename: str) -> None:
Expand Down Expand Up @@ -47,30 +47,21 @@ def add_options(cls, parser: OptionManager) -> None:
parse_from_config=True,
action='store_true'
)

lang_choices = cls._get_lang_choices()
parser.add_option(
'--lang',
default='english',
parse_from_config=True,
comma_separated_list=True
comma_separated_list=True,
choices=lang_choices
)

@classmethod
def parse_options(cls, options: optparse.Values) -> None:
"""Get parser options from flake8."""
cls.options = options

def _check_row(self, string: str) -> List[Tuple[int, str]]:
"""Return a list containing bad words and their positions."""
if self._pattern == '':
return []

regex = re.compile(f'(?=({self._pattern}))', flags=re.IGNORECASE)

return [
(match.start(), match.group(1))
for match in regex.finditer(string)
]

def _get_bad_words(self) -> Set[str]:
"""Get a set of bad words."""
data = self._get_swears_data()
Expand Down Expand Up @@ -99,12 +90,6 @@ def _get_file_content(self) -> List[str]:
else:
return readlines(self.filename)

def _censor_word(self, word: str) -> str:
"""Replace all letters but first with `*` if censor_msg option is True."""
if self.options.censor_msg:
return word[0] + '*' * (len(word) - 1)
return word

def _get_filename_errors(self) -> Generator[Tuple[int, int, str, type], None, None]:
"""Get filename errors if exist."""
filename_errors = self._check_row(os.path.basename(self.filename))
Expand Down Expand Up @@ -134,3 +119,30 @@ def _get_content_errors(
)
for column, word in errors
)

def _check_row(self, string: str) -> List[Tuple[int, str]]:
"""Return a list containing bad words and their positions."""
if self._pattern == '':
return []

regex = re.compile(f'(?=({self._pattern}))', flags=re.IGNORECASE)

return [
(match.start(), match.group(1))
for match in regex.finditer(string)
]

def _censor_word(self, word: str) -> str:
"""Replace all letters but first with `*` if censor_msg option is True."""
if self.options.censor_msg:
return word[0] + '*' * (len(word) - 1)
return word

@classmethod
def _get_lang_choices(cls) -> List[str]:
"""Get language choices by removing .dat from language filenames."""
return [
lang_file.replace('.dat', '')
for lang_file in
pkg_resources.resource_listdir(__name__, cls.SWEAR_DATA_DIR)
]
232 changes: 127 additions & 105 deletions tests/test_checker.py
Expand Up @@ -8,6 +8,62 @@
from flake8_koles.checker import KolesChecker


@mock.patch('flake8_koles.checker.readlines')
@mock.patch('flake8_koles.checker.KolesChecker._get_bad_words')
def test_run(
mock_get_bad_words,
mock_readlines
):
"""Test that flake interface returns appropriate error messages."""
mock_get_bad_words.return_value = ['very', 'bad', 'words']
mock_readlines.return_value = ['Test very', 'nice', 'and bad words']
koles_checker = KolesChecker(tree='test_tree', filename='test_filename')
koles_checker.options = Mock(censor_msg=True)
result = [*koles_checker.run()]

assert result == [
(1, 5, 'KOL001 Bad language found: v***', KolesChecker),
(3, 4, 'KOL001 Bad language found: b**', KolesChecker),
(3, 8, 'KOL001 Bad language found: w****', KolesChecker)]


def test_add_options(koles_checker):
"""Test that all options are added to the parser."""
option_manager = OptionManager()
koles_checker.add_options(option_manager)

assert repr(option_manager.options) == repr(
[
Option(
long_option_name='--ignore-shorties',
default=0,
type='int',
parse_from_config=True
),
Option(
long_option_name='--censor-msg',
default=0,
parse_from_config=True,
action='store_true'
),
Option(
long_option_name='--lang',
default='english',
parse_from_config=True,
comma_separated_list=True
)
]
)


def test_parse_options(koles_checker):
"""Test that options are correctly assigned to the class."""
test_options = {'kick_it': True}
koles_checker.parse_options(test_options)

assert koles_checker.options == test_options


@pytest.mark.parametrize(
"ignore_shorties, expected_result, get_swears_data_value",
(
Expand Down Expand Up @@ -59,7 +115,7 @@ def test_get_bad_words(
),
)
@mock.patch('flake8_koles.checker.pkg_resources.resource_string')
def test_get_swear_data(
def test_get_swears_data(
mock_resource_string,
lang,
resource_string_value,
Expand All @@ -76,64 +132,6 @@ def test_get_swear_data(
assert result == expected_result


@pytest.mark.parametrize(
'pattern, string, expected_result',
(
# Case 1: Multiple overlapping patterns
('abcd|ab|abc|cd', 'abcdab', [(0, 'abcd'), (2, 'cd'), (4, 'ab')]),
# Case 2: Single non-overlapping pattern
('ab', 'abcdab', [(0, 'ab'), (4, 'ab')]),
# Case 3: Empty string
('(?=(ab))', '', []),
# Case 4: Empty pattern
('', 'abcdab', []),
# Case 6: Empty string and pattern
('', '', []),
# Case 7: Uppercase string
('abcd|ab|abc|cd', 'ABCDAB', [(0, 'ABCD'), (2, 'CD'), (4, 'AB')]),
),
)
def test_check_row(
pattern,
string,
expected_result,
koles_checker
):
"""Test that check_string returns appropriate value for given pattern and string."""
koles_checker._pattern = pattern
result = koles_checker._check_row(string)

assert [*result] == expected_result


@pytest.mark.parametrize(
'word, censor_msg, expected_result',
(
('Mike D', True, 'M*****'),
('Mike D', False, 'Mike D'),
('MCA', True, 'M**'),
('MCA', False, 'MCA'),
('Ad-Rock', True, 'A******'),
('Ad-Rock', False, 'Ad-Rock'),
),
)
def test_censor_word(
word,
censor_msg,
expected_result,
koles_checker
):
"""Test censor_word.
Test that the function returns proper set of bad words
depending on ignore-shorties option.
"""
koles_checker.options = Mock(censor_msg=censor_msg)
result = koles_checker._censor_word(word)

assert result == expected_result


@pytest.mark.parametrize(
'filename,',
(
Expand Down Expand Up @@ -261,56 +259,80 @@ def test_get_content_errors(
assert result == expected_result


@mock.patch('flake8_koles.checker.readlines')
@mock.patch('flake8_koles.checker.KolesChecker._get_bad_words')
def test_run(
mock_get_bad_words,
mock_readlines
@pytest.mark.parametrize(
'pattern, string, expected_result',
(
# Case 1: Multiple overlapping patterns
('abcd|ab|abc|cd', 'abcdab', [(0, 'abcd'), (2, 'cd'), (4, 'ab')]),
# Case 2: Single non-overlapping pattern
('ab', 'abcdab', [(0, 'ab'), (4, 'ab')]),
# Case 3: Empty string
('(?=(ab))', '', []),
# Case 4: Empty pattern
('', 'abcdab', []),
# Case 6: Empty string and pattern
('', '', []),
# Case 7: Uppercase string
('abcd|ab|abc|cd', 'ABCDAB', [(0, 'ABCD'), (2, 'CD'), (4, 'AB')]),
),
)
def test_check_row(
pattern,
string,
expected_result,
koles_checker
):
"""Test that flake interface returns appropriate error messages."""
mock_get_bad_words.return_value = ['very', 'bad', 'words']
mock_readlines.return_value = ['Test very', 'nice', 'and bad words']
koles_checker = KolesChecker(tree='test_tree', filename='test_filename')
koles_checker.options = Mock(censor_msg=True)
result = [*koles_checker.run()]
assert result == [
(1, 5, 'KOL001 Bad language found: v***', KolesChecker),
(3, 4, 'KOL001 Bad language found: b**', KolesChecker),
(3, 8, 'KOL001 Bad language found: w****', KolesChecker)]
"""Test that check_string returns appropriate value for given pattern and string."""
koles_checker._pattern = pattern
result = koles_checker._check_row(string)

assert [*result] == expected_result

def test_add_options(koles_checker):
"""Test that all options are added to the parser."""
option_manager = OptionManager()
koles_checker.add_options(option_manager)

assert repr(option_manager.options) == repr(
[
Option(
long_option_name='--ignore-shorties',
default=0,
type='int',
parse_from_config=True
),
Option(
long_option_name='--censor-msg',
default=0,
parse_from_config=True,
action='store_true'
),
Option(
long_option_name='--lang',
default='english',
parse_from_config=True,
comma_separated_list=True
)
]
)
@pytest.mark.parametrize(
'word, censor_msg, expected_result',
(
('Mike D', True, 'M*****'),
('Mike D', False, 'Mike D'),
('MCA', True, 'M**'),
('MCA', False, 'MCA'),
('Ad-Rock', True, 'A******'),
('Ad-Rock', False, 'Ad-Rock'),
),
)
def test_censor_word(
word,
censor_msg,
expected_result,
koles_checker
):
"""Test censor_word.
Test that the function returns proper set of bad words
depending on ignore-shorties option.
"""
koles_checker.options = Mock(censor_msg=censor_msg)
result = koles_checker._censor_word(word)

def test_parse_options(koles_checker):
"""Test that options are correctly assigned to the class."""
test_options = {'kick_it': True}
koles_checker.parse_options(test_options)
assert result == expected_result

assert koles_checker.options == test_options

@pytest.mark.parametrize(
'listdir_value, expected_result',
(
# Case: empty language dir
([], []),
(['english.dat'], ['english']),
(['english.dat', 'polish.dat'], ['english', 'polish']),
),
)
@mock.patch('flake8_koles.checker.pkg_resources.resource_listdir')
def test_get_lang_choices(
listdir_mock,
listdir_value,
expected_result,
koles_checker):
"""Test that proper language names are fetched from the resources."""
listdir_mock.return_value = listdir_value

assert koles_checker._get_lang_choices() == expected_result

0 comments on commit 7f86e92

Please sign in to comment.