mirror of
https://github.com/pre-commit/pre-commit-hooks.git
synced 2026-04-08 20:44:18 +00:00
Merge pull request #34 from struys/string_fixer
implemented a basic double quote string fixer
This commit is contained in:
commit
5207d1f29a
6 changed files with 138 additions and 1 deletions
|
|
@ -36,6 +36,7 @@ Add this to your `.pre-commit-config.yaml`
|
||||||
- `name-tests-test` - Assert that files in tests/ end in _test.py
|
- `name-tests-test` - Assert that files in tests/ end in _test.py
|
||||||
- `pyflakes` - Run pyflakes on your python files
|
- `pyflakes` - Run pyflakes on your python files
|
||||||
- `requirements-txt-fixer` - Sorts entries in requirements.txt
|
- `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.
|
- `trailing-whitespace` - Trims trailing whitespace.
|
||||||
|
|
||||||
### As a standalone package
|
### As a standalone package
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,12 @@
|
||||||
entry: requirements-txt-fixer
|
entry: requirements-txt-fixer
|
||||||
language: python
|
language: python
|
||||||
files: requirements.*\.txt$
|
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
|
- id: trailing-whitespace
|
||||||
name: Trim Trailing Whitespace
|
name: Trim Trailing Whitespace
|
||||||
description: This hook trims trailing whitespace.
|
description: This hook trims trailing whitespace.
|
||||||
|
|
|
||||||
49
pre_commit_hooks/string_fixer.py
Normal file
49
pre_commit_hooks/string_fixer.py
Normal 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
|
||||||
1
setup.py
1
setup.py
|
|
@ -46,6 +46,7 @@ setup(
|
||||||
'debug-statement-hook = pre_commit_hooks.debug_statement_hook:debug_statement_hook',
|
'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',
|
'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',
|
'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',
|
'requirements-txt-fixer = pre_commit_hooks.requirements_txt_fixer:fix_requirements_txt',
|
||||||
'trailing-whitespace-fixer = pre_commit_hooks.trailing_whitespace_fixer:fix_trailing_whitespace',
|
'trailing-whitespace-fixer = pre_commit_hooks.trailing_whitespace_fixer:fix_trailing_whitespace',
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ TESTS = (
|
||||||
('', 0, ''),
|
('', 0, ''),
|
||||||
# Acceptable
|
# Acceptable
|
||||||
('"foo"', 0, ''),
|
('"foo"', 0, ''),
|
||||||
# Docstrin after code
|
# Docstring after code
|
||||||
(
|
(
|
||||||
'from __future__ import unicode_literals\n'
|
'from __future__ import unicode_literals\n'
|
||||||
'"foo"\n',
|
'"foo"\n',
|
||||||
|
|
|
||||||
80
tests/string_fixer_test.py
Normal file
80
tests/string_fixer_test.py
Normal 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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue