Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the error message show what kind of string is bad. #103

Merged
merged 5 commits into from Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 10 additions & 3 deletions flake8_quotes/__init__.py
Expand Up @@ -73,6 +73,8 @@ class QuoteChecker(object):
DOCSTRING_QUOTES["'''"] = DOCSTRING_QUOTES["'"]
DOCSTRING_QUOTES['"""'] = DOCSTRING_QUOTES['"']

QUOTE_NAMES = {'"': 'double', "'": 'single'}

def __init__(self, tree, lines=None, filename='(none)'):
self.filename = filename
self.lines = lines
Expand Down Expand Up @@ -221,7 +223,7 @@ def get_quotes_errors(self, file_contents):
continue

yield {
'message': 'Q002 Remove bad quotes from docstring',
'message': self._quote_error(code='Q002', kind='doc'),
'line': start_row,
'col': start_col,
}
Expand All @@ -242,7 +244,7 @@ def get_quotes_errors(self, file_contents):

# Output our error
yield {
'message': 'Q001 Remove bad quotes from multiline string',
'message': self._quote_error(code='Q001', kind='multiline '),
'line': start_row,
'col': start_col,
}
Expand Down Expand Up @@ -276,11 +278,16 @@ def get_quotes_errors(self, file_contents):
# If not preferred type, only allow use to avoid escapes.
if not self.config['good_single'] in string_contents:
yield {
'message': 'Q000 Remove bad quotes',
'message': self._quote_error(code='Q000', kind=''),
'line': start_row,
'col': start_col,
}

def _quote_error(self, code, kind):
bad = self.QUOTE_NAMES[self.config['bad_single']]
good = self.QUOTE_NAMES[self.config['good_single']]
return f'{code} {bad.title()} quoted {kind}string literal found but {good} quotes are preferred'


class Token:
"""Python 2 and 3 compatible token"""
Expand Down
64 changes: 42 additions & 22 deletions test/test_checks.py
Expand Up @@ -22,9 +22,18 @@ def test_stdin(self):
stdout_lines = stdout.splitlines()
self.assertEqual(stderr, b'')
self.assertEqual(len(stdout_lines), 3)
self.assertRegexpMatches(stdout_lines[0], b'stdin:1:(24|25): Q000 Remove bad quotes')
self.assertRegexpMatches(stdout_lines[1], b'stdin:2:(24|25): Q000 Remove bad quotes')
self.assertRegexpMatches(stdout_lines[2], b'stdin:3:(24|25): Q000 Remove bad quotes')
self.assertRegexpMatches(
stdout_lines[0],
b'stdin:1:(24|25): Q000 Double quoted string literal found but single quotes are preferred',
)
self.assertRegexpMatches(
stdout_lines[0],
b'stdin:2:(24|25): Q000 Double quoted string literal found but single quotes are preferred',
)
self.assertRegexpMatches(
stdout_lines[0],
b'stdin:3:(24|25): Q000 Double quoted string literal found but single quotes are preferred',
)


class DoublesTestChecks(TestCase):
Expand All @@ -36,16 +45,18 @@ class DoublesOptions():

def test_multiline_string(self):
doubles_checker = QuoteChecker(None, filename=get_absolute_path('data/doubles_multiline_string.py'))
message = 'Q001 Double quoted multiline string literal found but single quotes are preferred'
self.assertEqual(list(doubles_checker.get_quotes_errors(doubles_checker.get_file_contents())), [
{'col': 4, 'line': 1, 'message': 'Q001 Remove bad quotes from multiline string'},
{'col': 4, 'line': 1, 'message': message},
])

def test_multiline_string_using_lines(self):
with open(get_absolute_path('data/doubles_multiline_string.py')) as f:
lines = f.readlines()
doubles_checker = QuoteChecker(None, lines=lines)
message = 'Q001 Double quoted multiline string literal found but single quotes are preferred'
self.assertEqual(list(doubles_checker.get_quotes_errors(doubles_checker.get_file_contents())), [
{'col': 4, 'line': 1, 'message': 'Q001 Remove bad quotes from multiline string'},
{'col': 4, 'line': 1, 'message': message},
])

def test_wrapped(self):
Expand All @@ -54,10 +65,11 @@ def test_wrapped(self):

def test_doubles(self):
doubles_checker = QuoteChecker(None, filename=get_absolute_path('data/doubles.py'))
message = 'Q000 Double quoted string literal found but single quotes are preferred'
self.assertEqual(list(doubles_checker.get_quotes_errors(doubles_checker.get_file_contents())), [
{'col': 24, 'line': 1, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 2, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 3, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 1, 'message': message},
{'col': 24, 'line': 2, 'message': message},
{'col': 24, 'line': 3, 'message': message},
])

def test_noqa_doubles(self):
Expand Down Expand Up @@ -92,10 +104,11 @@ def test_doubles(self):
self.assertEqual(list(doubles_checker.get_quotes_errors(doubles_checker.get_file_contents())), [])

doubles_checker = QuoteChecker(None, filename=get_absolute_path('data/doubles.py'))
message = 'Q000 Double quoted string literal found but single quotes are preferred'
self.assertEqual(list(doubles_checker.get_quotes_errors(doubles_checker.get_file_contents())), [
{'col': 24, 'line': 1, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 2, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 3, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 1, 'message': message},
{'col': 24, 'line': 2, 'message': message},
{'col': 24, 'line': 3, 'message': message},
])


Expand All @@ -108,8 +121,9 @@ class SinglesOptions():

def test_multiline_string(self):
singles_checker = QuoteChecker(None, filename=get_absolute_path('data/singles_multiline_string.py'))
message = 'Q001 Single quoted multiline string literal found but double quotes are preferred'
self.assertEqual(list(singles_checker.get_quotes_errors(singles_checker.get_file_contents())), [
{'col': 4, 'line': 1, 'message': 'Q001 Remove bad quotes from multiline string'},
{'col': 4, 'line': 1, 'message': message},
])

def test_wrapped(self):
Expand All @@ -118,10 +132,11 @@ def test_wrapped(self):

def test_singles(self):
singles_checker = QuoteChecker(None, filename=get_absolute_path('data/singles.py'))
message = 'Q000 Single quoted string literal found but double quotes are preferred'
self.assertEqual(list(singles_checker.get_quotes_errors(singles_checker.get_file_contents())), [
{'col': 24, 'line': 1, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 2, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 3, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 1, 'message': message},
{'col': 24, 'line': 2, 'message': message},
{'col': 24, 'line': 3, 'message': message},
])

def test_noqa_singles(self):
Expand Down Expand Up @@ -156,10 +171,11 @@ def test_singles(self):
self.assertEqual(list(singles_checker.get_quotes_errors(singles_checker.get_file_contents())), [])

singles_checker = QuoteChecker(None, filename=get_absolute_path('data/singles.py'))
message = 'Q000 Single quoted string literal found but double quotes are preferred'
self.assertEqual(list(singles_checker.get_quotes_errors(singles_checker.get_file_contents())), [
{'col': 24, 'line': 1, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 2, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 3, 'message': 'Q000 Remove bad quotes'},
{'col': 24, 'line': 1, 'message': message},
{'col': 24, 'line': 2, 'message': message},
{'col': 24, 'line': 3, 'message': message},
])


Expand All @@ -171,8 +187,9 @@ class Options():
QuoteChecker.parse_options(Options)

multiline_checker = QuoteChecker(None, filename=get_absolute_path('data/multiline_string.py'))
message = 'Q001 Double quoted multiline string literal found but single quotes are preferred'
self.assertEqual(list(multiline_checker.get_quotes_errors(multiline_checker.get_file_contents())), [
{'col': 4, 'line': 10, 'message': 'Q001 Remove bad quotes from multiline string'},
{'col': 4, 'line': 10, 'message': message},
])

def test_singles_alias(self):
Expand All @@ -182,8 +199,9 @@ class Options():
QuoteChecker.parse_options(Options)

multiline_checker = QuoteChecker(None, filename=get_absolute_path('data/multiline_string.py'))
message = 'Q001 Double quoted multiline string literal found but single quotes are preferred'
self.assertEqual(list(multiline_checker.get_quotes_errors(multiline_checker.get_file_contents())), [
{'col': 4, 'line': 10, 'message': 'Q001 Remove bad quotes from multiline string'},
{'col': 4, 'line': 10, 'message': message},
])

def test_doubles(self):
Expand All @@ -193,8 +211,9 @@ class Options():
QuoteChecker.parse_options(Options)

multiline_checker = QuoteChecker(None, filename=get_absolute_path('data/multiline_string.py'))
message = 'Q001 Single quoted multiline string literal found but double quotes are preferred'
self.assertEqual(list(multiline_checker.get_quotes_errors(multiline_checker.get_file_contents())), [
{'col': 4, 'line': 1, 'message': 'Q001 Remove bad quotes from multiline string'},
{'col': 4, 'line': 1, 'message': message},
])

def test_doubles_alias(self):
Expand All @@ -204,8 +223,9 @@ class Options():
QuoteChecker.parse_options(Options)

multiline_checker = QuoteChecker(None, filename=get_absolute_path('data/multiline_string.py'))
message = 'Q001 Single quoted multiline string literal found but double quotes are preferred'
self.assertEqual(list(multiline_checker.get_quotes_errors(multiline_checker.get_file_contents())), [
{'col': 4, 'line': 1, 'message': 'Q001 Remove bad quotes from multiline string'},
{'col': 4, 'line': 1, 'message': message},
])


Expand Down