Merge pull request #4 from pre-commit/master

merge from upstream
This commit is contained in:
Evan Felix 2017-03-16 23:09:28 -07:00 committed by GitHub
commit 564a82ca89
31 changed files with 274 additions and 61 deletions

View file

@ -1,5 +1,5 @@
- repo: https://github.com/pre-commit/pre-commit-hooks
sha: 9ba5af45ce2d29b64c9a348a6fcff5553eea1f2c
sha: v0.7.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
@ -13,12 +13,16 @@
- id: requirements-txt-fixer
- id: flake8
- repo: https://github.com/pre-commit/pre-commit
sha: 8dba3281d5051060755459dcf88e28fc26c27526
sha: v0.12.2
hooks:
- id: validate_config
- id: validate_manifest
- repo: https://github.com/asottile/reorder_python_imports
sha: 3d86483455ab5bd06cc1069fdd5ac57be5463f10
sha: v0.3.1
hooks:
- id: reorder-python-imports
language_version: python2.7
- repo: https://github.com/asottile/pyupgrade
sha: v1.0.0
hooks:
- id: pyupgrade

149
.pre-commit-hooks.yaml Normal file
View file

@ -0,0 +1,149 @@
- id: autopep8-wrapper
name: autopep8 wrapper
description: "Runs autopep8 over python source. If you configure additional arguments you'll want to at least include -i."
entry: autopep8-wrapper
language: python
files: \.py$
args: [-i]
- id: check-added-large-files
name: Check for added large files
description: Prevent giant files from being committed
entry: check-added-large-files
language: python
# Match all files
files: ''
- id: check-ast
name: Check python ast
description: Simply check whether the files parse as valid python.
entry: check-ast
language: python
files: '\.py$'
- id: check-byte-order-marker
name: Check for byte-order marker
description: Forbid files which have a UTF-8 byte-order marker
entry: check-byte-order-marker
language: python
files: '\.py$'
- id: check-case-conflict
name: Check for case conflicts
description: Check for files that would conflict in case-insensitive filesystems
entry: check-case-conflict
language: python
# Match all files
files: ''
- id: check-docstring-first
name: Check docstring is first
description: Checks a common error of defining a docstring after code.
entry: check-docstring-first
language: python
files: \.py$
- id: check-json
name: Check JSON
description: This hook checks json files for parseable syntax.
entry: check-json
language: python
files: \.json$
- id: pretty-format-json
name: Pretty format JSON
description: This hook sets a standard for formatting JSON files.
entry: pretty-format-json
language: python
files: \.json$
- id: check-merge-conflict
name: Check for merge conflicts
description: Check for files that contain merge conflict strings.
entry: check-merge-conflict
language: python
# Match all files
files: ''
- id: check-symlinks
name: Check for broken symlinks
description: Checks for symlinks which do not point to anything.
entry: check-symlinks
language: python
# Match all files
files: ''
- id: check-xml
name: Check Xml
description: This hook checks xml files for parseable syntax.
entry: check-xml
language: python
files: \.xml$
- id: check-yaml
name: Check Yaml
description: This hook checks yaml files for parseable syntax.
entry: check-yaml
language: python
files: \.(yaml|yml|eyaml)$
- id: debug-statements
name: Debug Statements (Python)
description: This hook checks that debug statements (pdb, ipdb, pudb) are not imported on commit.
entry: debug-statement-hook
language: python
files: \.py$
- id: detect-aws-credentials
name: Detect AWS Credentials
description: Detects *your* aws credentials from the aws cli credentials file
entry: detect-aws-credentials
language: python
files: ''
- id: detect-private-key
name: Detect Private Key
description: Detects the presence of private keys
entry: detect-private-key
language: python
files: ''
- 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: end-of-file-fixer
name: Fix End of Files
description: Ensures that a file is either empty, or ends with one newline.
entry: end-of-file-fixer
language: python
files: \.(asciidoc|adoc|coffee|cpp|css|c|ejs|erb|groovy|h|haml|hh|hpp|hxx|html|in|j2|jade|json|js|less|markdown|md|ml|mli|pp|py|rb|rs|R|scala|scss|sh|slim|tex|tmpl|ts|txt|yaml|yml)$
- id: fix-encoding-pragma
name: Fix python encoding pragma
language: python
entry: fix-encoding-pragma
description: 'Add # -*- coding: utf-8 -*- to the top of python files'
files: \.py$
- id: flake8
name: Flake8
description: This hook runs flake8.
entry: flake8
language: python
files: \.py$
- id: forbid-new-submodules
name: Forbid new submodules
language: python
entry: forbid-new-submodules
description: Prevent addition of new git submodules
files: ''
- id: name-tests-test
name: Tests should end in _test.py
description: This verifies that test files are named correctly
entry: name-tests-test
language: python
files: tests/.+\.py$
- id: pyflakes
name: Pyflakes (DEPRECATED, use flake8)
description: This hook runs pyflakes. (This is deprecated, use flake8).
entry: pyflakes
language: python
files: \.py$
- id: requirements-txt-fixer
name: Fix requirements.txt
description: Sorts entries in requirements.txt
entry: requirements-txt-fixer
language: python
files: requirements.*\.txt$
- id: trailing-whitespace
name: Trim Trailing Whitespace
description: This hook trims trailing whitespace.
entry: trailing-whitespace-fixer
language: python
files: \.(asciidoc|adoc|coffee|cpp|css|c|ejs|erb|groovy|h|haml|hh|hpp|hxx|html|in|j2|jade|json|js|less|markdown|md|ml|mli|pp|py|rb|rs|R|scala|scss|sh|slim|tex|tmpl|ts|txt|yaml|yml)$

View file

@ -1,18 +1,19 @@
language: python
python: 3.5
env: # These should match the tox env list
- TOXENV=py27
- TOXENV=py34
- TOXENV=py35
- TOXENV=pypy
sudo: false
matrix:
include: # These should match the tox env list
- env: TOXENV=py27
- env: TOXENV=py35
python: 3.5
- env: TOXENV=py36
python: 3.6
- env: TOXENV=pypy
install: pip install coveralls tox
script: tox
before_install:
# Install git-lfs for a test
- './get-git-lfs.py && export PATH="/tmp/git-lfs:$PATH"'
after_success:
- coveralls
sudo: false
after_success: coveralls
cache:
directories:
- $HOME/.cache/pip

View file

@ -1,3 +1,12 @@
0.7.1
=====
- Don't false positive on files where trailing whitespace isn't changed.
0.7.0
=====
- Improve search for detecting aws keys
- Add .pre-commit-hooks.yaml for forward compatibility
0.6.1
=====
- trailing-whitespace-hook: restore original file on catastrophic failure

View file

@ -1,5 +1,5 @@
[![Build Status](https://travis-ci.org/pre-commit/pre-commit-hooks.svg?branch=master)](https://travis-ci.org/pre-commit/pre-commit-hooks)
[![Coverage Status](https://img.shields.io/coveralls/pre-commit/pre-commit-hooks.svg?branch=master)](https://coveralls.io/r/pre-commit/pre-commit-hooks)
[![Coverage Status](https://coveralls.io/repos/github/pre-commit/pre-commit-hooks/badge.svg?branch=master)](https://coveralls.io/github/pre-commit/pre-commit-hooks?branch=master)
[![Build status](https://ci.appveyor.com/api/projects/status/dfcpng35u4g0r0t1/branch/master?svg=true)](https://ci.appveyor.com/project/asottile/pre-commit-hooks/branch/master)
pre-commit-hooks
@ -15,7 +15,7 @@ See also: https://github.com/pre-commit/pre-commit
Add this to your `.pre-commit-config.yaml`
- repo: git://github.com/pre-commit/pre-commit-hooks
sha: '' # Use the sha you want to point at
sha: v0.7.1 # Use the ref you want to point at
hooks:
- id: trailing-whitespace
# - id: ...

View file

@ -1,10 +1,10 @@
environment:
matrix:
- TOXENV: py27
- TOXENV: py35
- TOXENV: py36
install:
- "SET PATH=C:\\Python35;C:\\Python35\\Scripts;%PATH%"
- "SET PATH=C:\\Python36;C:\\Python36\\Scripts;%PATH%"
- pip install tox
# Not a C# project

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python3.4
#!/usr/bin/env python3
"""This is a script to install git-lfs to a tempdir for use in tests"""
import io
import os.path

View file

@ -17,7 +17,7 @@ def main(argv=None):
original_contents = io.open(filename).read()
new_contents = autopep8.fix_code(original_contents, args)
if original_contents != new_contents:
print('Fixing {0}'.format(filename))
print('Fixing {}'.format(filename))
retv = 1
with io.open(filename, 'w') as output_file:
output_file.write(new_contents)

View file

@ -26,10 +26,10 @@ def lfs_files():
assert mode in ('A', 'R')
return filepart if mode == 'A' else filepart.split(' -> ')[1]
return set(
return {
to_file_part(mode, filepart) for mode, filepart in modes_and_fileparts
if mode in ('A', 'R')
)
}
def find_large_added_files(filenames, maxkb):
@ -41,7 +41,7 @@ def find_large_added_files(filenames, maxkb):
for filename in filenames:
kb = int(math.ceil(os.stat(filename).st_size / 1024))
if kb > maxkb:
print('{0} ({1} KB) exceeds {2} KB.'.format(filename, kb, maxkb))
print('{} ({} KB) exceeds {} KB.'.format(filename, kb, maxkb))
retv = 1
return retv

View file

@ -22,10 +22,10 @@ def check_ast(argv=None):
try:
ast.parse(open(filename, 'rb').read(), filename=filename)
except SyntaxError:
print('{0}: failed parsing with {1}:'.format(
print('{}: failed parsing with {}:'.format(
filename, interpreter,
))
print('\n{0}'.format(
print('\n{}'.format(
' ' + traceback.format_exc().replace('\n', '\n ')
))
retval = 1

View file

@ -16,7 +16,7 @@ def main(argv=None):
with open(filename, 'rb') as f:
if f.read(3) == b'\xef\xbb\xbf':
retv = 1
print('{0}: Has a byte-order marker'.format(filename))
print('{}: Has a byte-order marker'.format(filename))
return retv

View file

@ -9,7 +9,7 @@ from pre_commit_hooks.util import cmd_output
def lower_set(iterable):
return set(x.lower() for x in iterable)
return {x.lower() for x in iterable}
def find_conflicting_filenames(filenames):
@ -35,7 +35,7 @@ def find_conflicting_filenames(filenames):
if x.lower() in conflicts
]
for filename in sorted(conflicting_files):
print('Case-insensitivity conflict found: {0}'.format(filename))
print('Case-insensitivity conflict found: {}'.format(filename))
retv = 1
return retv

View file

@ -27,16 +27,16 @@ def check_docstring_first(src, filename='<unknown>'):
if tok_type == tokenize.STRING and scol == 0:
if found_docstring_line is not None:
print(
'{0}:{1} Multiple module docstrings '
'(first docstring on line {2}).'.format(
'{}:{} Multiple module docstrings '
'(first docstring on line {}).'.format(
filename, sline, found_docstring_line,
)
)
return 1
elif found_code_line is not None:
print(
'{0}:{1} Module docstring appears after code '
'(code seen on line {2}).'.format(
'{}:{} Module docstring appears after code '
'(code seen on line {}).'.format(
filename, sline, found_code_line,
)
)

View file

@ -16,7 +16,7 @@ def check_json(argv=None):
try:
simplejson.load(open(filename))
except (simplejson.JSONDecodeError, UnicodeDecodeError) as exc:
print('{0}: Failed to json decode ({1})'.format(filename, exc))
print('{}: Failed to json decode ({})'.format(filename, exc))
retval = 1
return retval

View file

@ -19,7 +19,7 @@ def check_symlinks(argv=None):
os.path.islink(filename) and
not os.path.exists(filename)
): # pragma: no cover (symlink support required)
print('{0}: Broken symlink'.format(filename))
print('{}: Broken symlink'.format(filename))
retv = 1
return retv

View file

@ -19,7 +19,7 @@ def check_xml(argv=None):
with io.open(filename, 'rb') as xml_file:
xml.sax.parse(xml_file, xml.sax.ContentHandler())
except xml.sax.SAXException as exc:
print('{0}: Failed to xml parse ({1})'.format(filename, exc))
print('{}: Failed to xml parse ({})'.format(filename, exc))
retval = 1
return retval

View file

@ -7,7 +7,7 @@ import collections
import traceback
DEBUG_STATEMENTS = set(['pdb', 'ipdb', 'pudb', 'q', 'rdb'])
DEBUG_STATEMENTS = {'pdb', 'ipdb', 'pudb', 'q', 'rdb'}
DebugStatement = collections.namedtuple(
@ -37,7 +37,7 @@ def check_file_for_debug_statements(filename):
try:
ast_obj = ast.parse(open(filename).read(), filename=filename)
except SyntaxError:
print('{0} - Could not parse ast'.format(filename))
print('{} - Could not parse ast'.format(filename))
print()
print('\t' + traceback.format_exc().replace('\n', '\n\t'))
print()
@ -47,7 +47,7 @@ def check_file_for_debug_statements(filename):
if visitor.debug_import_statements:
for debug_statement in visitor.debug_import_statements:
print(
'{0}:{1}:{2} - {3} imported'.format(
'{}:{}:{} - {} imported'.format(
filename,
debug_statement.line,
debug_statement.col,

View file

@ -95,6 +95,12 @@ def main(argv=None):
'secret keys from'
)
)
parser.add_argument(
'--allow-missing-credentials',
dest='allow_missing_credentials',
action='store_true',
help='Allow hook to pass when no credentials are detected.'
)
args = parser.parse_args(argv)
credential_files = set(args.credential_files)
@ -111,6 +117,9 @@ def main(argv=None):
# the set of keys.
keys |= get_aws_secrets_from_env()
if not keys and args.allow_missing_credentials:
return 0
if not keys:
print(
'No AWS keys were found in the configured credential files and '

View file

@ -26,7 +26,7 @@ def detect_private_key(argv=None):
if private_key_files:
for private_key_file in private_key_files:
print('Private key found: {0}'.format(private_key_file))
print('Private key found: {}'.format(private_key_file))
return 1
else:
return 0

View file

@ -58,7 +58,7 @@ def end_of_file_fixer(argv=None):
with open(filename, 'rb+') as file_obj:
ret_for_file = fix_file(file_obj)
if ret_for_file:
print('Fixing {0}'.format(filename))
print('Fixing {}'.format(filename))
retv |= ret_for_file
return retv

View file

@ -25,7 +25,7 @@ def _get_pretty_format(contents, indent, sort_keys=True, top_keys=[]):
def _autofix(filename, new_contents):
print("Fixing file {0}".format(filename))
print("Fixing file {}".format(filename))
with open(filename, 'w') as f:
f.write(new_contents)
@ -100,7 +100,7 @@ def pretty_format_json(argv=None):
)
if contents != pretty_contents:
print("File {0} is not pretty-formatted".format(json_file))
print("File {} is not pretty-formatted".format(json_file))
if args.autofix:
_autofix(json_file, pretty_contents)
@ -109,7 +109,7 @@ def pretty_format_json(argv=None):
except simplejson.JSONDecodeError:
print(
"Input File {0} is not a valid JSON, consider using check-json"
"Input File {} is not a valid JSON, consider using check-json"
.format(json_file)
)
return 1

View file

@ -84,7 +84,7 @@ def fix_requirements_txt(argv=None):
ret_for_file = fix_requirements(file_obj)
if ret_for_file:
print('Sorting {0}'.format(arg))
print('Sorting {}'.format(arg))
retv |= ret_for_file

View file

@ -69,7 +69,7 @@ def main(argv=None):
for filename in args.filenames:
return_value = fix_strings(filename)
if return_value != 0:
print('Fixing strings in {0}'.format(filename))
print('Fixing strings in {}'.format(filename))
retv |= return_value
return retv

View file

@ -16,7 +16,7 @@ def validate_files(argv=None):
args = parser.parse_args(argv)
retcode = 0
test_name_pattern = 'test_.*.py' if args.django else '.*_test.py'
test_name_pattern = 'test.*.py' if args.django else '.*_test.py'
for filename in args.filenames:
base = basename(filename)
if (
@ -26,7 +26,7 @@ def validate_files(argv=None):
):
retcode = 1
print(
'{0} does not match pattern "{1}"'.format(
'{} does not match pattern "{}"'.format(
filename, test_name_pattern
)
)

View file

@ -10,10 +10,14 @@ from pre_commit_hooks.util import cmd_output
def _fix_file(filename, is_markdown):
with open(filename, mode='rb') as file_processed:
lines = file_processed.readlines()
lines = [_process_line(line, is_markdown) for line in lines]
with open(filename, mode='wb') as file_processed:
for line in lines:
file_processed.write(line)
newlines = [_process_line(line, is_markdown) for line in lines]
if newlines != lines:
with open(filename, mode='wb') as file_processed:
for line in newlines:
file_processed.write(line)
return True
else:
return False
def _process_line(line, is_markdown):
@ -55,24 +59,26 @@ def fix_trailing_whitespace(argv=None):
parser.error('--markdown-linebreak-ext requires a non-empty argument')
all_markdown = '*' in md_args
# normalize all extensions; split at ',', lowercase, and force 1 leading '.'
md_exts = ['.' + x.lower().lstrip('.')
for x in ','.join(md_args).split(',')]
md_exts = [
'.' + x.lower().lstrip('.') for x in ','.join(md_args).split(',')
]
# reject probable "eaten" filename as extension (skip leading '.' with [1:])
for ext in md_exts:
if any(c in ext[1:] for c in r'./\:'):
parser.error(
"bad --markdown-linebreak-ext extension '{0}' (has . / \\ :)\n"
"bad --markdown-linebreak-ext extension '{}' (has . / \\ :)\n"
" (probably filename; use '--markdown-linebreak-ext=EXT')"
.format(ext)
)
return_code = 0
for bad_whitespace_file in bad_whitespace_files:
print('Fixing {0}'.format(bad_whitespace_file))
_, extension = os.path.splitext(bad_whitespace_file.lower())
_fix_file(bad_whitespace_file, all_markdown or extension in md_exts)
return_code = 1
md = all_markdown or extension in md_exts
if _fix_file(bad_whitespace_file, md):
print('Fixing {}'.format(bad_whitespace_file))
return_code = 1
return return_code

View file

@ -6,7 +6,7 @@ setup(
name='pre_commit_hooks',
description='Some out-of-the-box hooks for pre-commit.',
url='https://github.com/pre-commit/pre-commit-hooks',
version='0.6.1',
version='0.7.1',
author='Anthony Sottile',
author_email='asottile@umich.edu',
@ -14,11 +14,10 @@ setup(
classifiers=[
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
],
@ -27,7 +26,6 @@ setup(
install_requires=[
# quickfix to prevent pep8 conflicts
'flake8!=2.5.3',
'argparse',
'autopep8>=1.1',
'pyyaml',
'simplejson',

View file

@ -130,3 +130,17 @@ def test_non_existent_credentials(mock_secrets_env, mock_secrets_file, capsys):
'and environment variables.\nPlease ensure you have the '
'correct setting for --credentials-file\n'
)
@patch('pre_commit_hooks.detect_aws_credentials.get_aws_secrets_from_file')
@patch('pre_commit_hooks.detect_aws_credentials.get_aws_secrets_from_env')
def test_non_existent_credentials_with_allow_flag(mock_secrets_env, mock_secrets_file):
"""Test behavior with no configured AWS secrets and flag to allow when missing."""
mock_secrets_env.return_value = set()
mock_secrets_file.return_value = set()
ret = main((
get_resource_path('aws_config_without_secrets.ini'),
"--credentials-file=testing/resources/credentailsfilethatdoesntexist",
"--allow-missing-credentials"
))
assert ret == 0

7
tests/meta_test.py Normal file
View file

@ -0,0 +1,7 @@
import io
def test_hooks_yaml_same_contents():
legacy_contents = io.open('hooks.yaml').read()
contents = io.open('.pre-commit-hooks.yaml').read()
assert legacy_contents == contents

View file

@ -10,4 +10,4 @@ def test_readme_contains_all_hooks():
readme_contents = io.open('README.md').read()
hooks = yaml.load(io.open('hooks.yaml').read())
for hook in hooks:
assert '`{0}`'.format(hook['id']) in readme_contents
assert '`{}`'.format(hook['id']) in readme_contents

View file

@ -12,7 +12,7 @@ def test_validate_files_one_fails():
def test_validate_files_django_all_pass():
ret = validate_files(['--django', 'test_foo.py', 'test_bar.py', 'tests/test_baz.py'])
ret = validate_files(['--django', 'tests.py', 'test_foo.py', 'test_bar.py', 'tests/test_baz.py'])
assert ret == 0

View file

@ -20,6 +20,22 @@ def test_fixes_trailing_whitespace(input_s, expected, tmpdir):
assert path.read() == expected
def test_ok_with_dos_line_endings(tmpdir):
filename = tmpdir.join('f')
filename.write_binary(b'foo\r\nbar\r\nbaz\r\n')
ret = fix_trailing_whitespace((filename.strpath,))
assert filename.read_binary() == b'foo\r\nbar\r\nbaz\r\n'
assert ret == 0
def test_markdown_ok(tmpdir):
filename = tmpdir.join('foo.md')
filename.write_binary(b'foo \n')
ret = fix_trailing_whitespace((filename.strpath,))
assert filename.read_binary() == b'foo \n'
assert ret == 0
# filename, expected input, expected output
MD_TESTS_1 = (
('foo.md', 'foo \nbar \n ', 'foo \nbar\n\n'),