Merge pull request #34 from struys/string_fixer

implemented a basic double quote string fixer
This commit is contained in:
Anthony Sottile 2015-02-09 10:13:57 -08:00
commit 5207d1f29a
6 changed files with 138 additions and 1 deletions

View file

@ -36,6 +36,7 @@ Add this to your `.pre-commit-config.yaml`
- `name-tests-test` - Assert that files in tests/ end in _test.py
- `pyflakes` - Run pyflakes on your python files
- `requirements-txt-fixer` - Sorts entries in requirements.txt
- `double-quote-string-fixer` - This hook replaces double quoted strings with single quoted strings
- `trailing-whitespace` - Trims trailing whitespace.
### As a standalone package

View file

@ -79,6 +79,12 @@
entry: requirements-txt-fixer
language: python
files: requirements.*\.txt$
- id: double-quote-string-fixer
name: Fix double quoted strings
description: This hook replaces double quoted strings with single quoted strings
entry: double-quote-string-fixer
language: python
files: \.py$
- id: trailing-whitespace
name: Trim Trailing Whitespace
description: This hook trims trailing whitespace.

View file

@ -0,0 +1,49 @@
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import re
import tokenize
double_quote_starts = tuple(s for s in tokenize.single_quoted if '"' in s)
compiled_tokenize_string = re.compile('(?<!")' + tokenize.String + '(?!")')
def handle_match(m):
string = m.group(0)
for double_quote_start in double_quote_starts:
if string.startswith(double_quote_start):
meat = string[len(double_quote_start):-1]
if '"' in meat or "'" in meat:
break
return double_quote_start.replace('"', "'") + meat + "'"
return string
def fix_strings(filename):
contents = open(filename).read()
new_contents = compiled_tokenize_string.sub(handle_match, contents)
retval = int(new_contents != contents)
if retval:
with open(filename, 'w') as write_handle:
write_handle.write(new_contents)
return retval
def main(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='*', help='Filenames to fix')
args = parser.parse_args(argv)
retv = 0
for filename in args.filenames:
return_value = fix_strings(filename)
if return_value != 0:
print('Fixing strings in {0}'.format(filename))
retv |= return_value
return retv

View file

@ -46,6 +46,7 @@ setup(
'debug-statement-hook = pre_commit_hooks.debug_statement_hook:debug_statement_hook',
'end-of-file-fixer = pre_commit_hooks.end_of_file_fixer:end_of_file_fixer',
'name-tests-test = pre_commit_hooks.tests_should_end_in_test:validate_files',
'double-quote-string-fixer = pre_commit_hooks.string_fixer:main',
'requirements-txt-fixer = pre_commit_hooks.requirements_txt_fixer:fix_requirements_txt',
'trailing-whitespace-fixer = pre_commit_hooks.trailing_whitespace_fixer:fix_trailing_whitespace',
],

View file

@ -15,7 +15,7 @@ TESTS = (
('', 0, ''),
# Acceptable
('"foo"', 0, ''),
# Docstrin after code
# Docstring after code
(
'from __future__ import unicode_literals\n'
'"foo"\n',

View file

@ -0,0 +1,80 @@
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import pytest
from pre_commit_hooks.string_fixer import main
TESTS = (
# Base cases
(
"''",
"''",
0
),
(
'""',
"''",
1
),
(
r'"\'"',
r'"\'"',
0
),
(
r'"\""',
r'"\""',
0
),
(
r"'\"\"'",
r"'\"\"'",
0
),
# String somewhere in the line
(
'x = "foo"',
"x = 'foo'",
1
),
# Test escaped characters
(
r'"\'"',
r'"\'"',
0
),
# Docstring
(
'""" Foo """',
'""" Foo """',
0
),
# Fuck it, won't even try to fix
(
"""
x = " \\n
foo \\n
"\n
""",
"""
x = " \\n
foo \\n
"\n
""",
0
),
)
@pytest.mark.parametrize(('input_s', 'expected_output', 'expected_retval'), TESTS)
def test_rewrite(input_s, expected_output, expected_retval, tmpdir):
tmpfile = tmpdir.join('file.txt')
with open(tmpfile.strpath, 'w') as f:
f.write(input_s)
retval = main([tmpfile.strpath])
assert tmpfile.read() == expected_output
assert retval == expected_retval