Merge remote-tracking branch 'upstream/master' into mixed-line-ending

This commit is contained in:
Morgan Courbet 2017-07-18 19:40:39 +02:00
commit 55658c4bbc
No known key found for this signature in database
GPG key ID: 467299D324A21B24
47 changed files with 923 additions and 302 deletions

View file

@ -10,6 +10,8 @@ omit =
get-git-lfs.py
[report]
show_missing = True
skip_covered = True
exclude_lines =
# Have to re-enable the standard pragma
\#\s*pragma: no cover

2
.gitignore vendored
View file

@ -2,7 +2,7 @@
*.iml
*.py[co]
.*.sw[a-z]
.cache/
.cache
.coverage
.idea
.project

View file

@ -1,5 +1,5 @@
- repo: https://github.com/pre-commit/pre-commit-hooks
sha: v0.8.0
sha: v0.9.1
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
@ -13,16 +13,20 @@
- id: requirements-txt-fixer
- id: flake8
- repo: https://github.com/pre-commit/pre-commit
sha: v0.12.2
sha: v0.15.2
hooks:
- id: validate_config
- id: validate_manifest
- repo: https://github.com/asottile/reorder_python_imports
sha: v0.3.1
sha: v0.3.5
hooks:
- id: reorder-python-imports
language_version: python2.7
- repo: https://github.com/asottile/pyupgrade
sha: v1.0.0
sha: v1.1.3
hooks:
- id: pyupgrade
- repo: https://github.com/asottile/add-trailing-comma
sha: v0.5.1
hooks:
- id: add-trailing-comma

View file

@ -3,126 +3,194 @@
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$
types: [python]
args: [-i]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: check-ast
name: Check python ast
description: Simply check whether the files parse as valid python.
entry: check-ast
language: python
files: '\.py$'
types: [python]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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$'
types: [python]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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$
types: [python]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: check-executables-have-shebangs
name: Check that executables have shebangs
description: Ensures that (non-binary) executables have a shebang.
entry: check-executables-have-shebangs
language: python
types: [text, executable]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: check-json
name: Check JSON
description: This hook checks json files for parseable syntax.
entry: check-json
language: python
files: \.json$
types: [json]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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$
types: [json]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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
types: [text]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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
types: [symlink]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: check-xml
name: Check Xml
description: This hook checks xml files for parseable syntax.
entry: check-xml
language: python
files: \.xml$
types: [xml]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: check-yaml
name: Check Yaml
description: This hook checks yaml files for parseable syntax.
entry: check-yaml
language: python
files: \.(yaml|yml|eyaml)$
types: [yaml]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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$
types: [python]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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
types: [text]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: detect-private-key
name: Detect Private Key
description: Detects the presence of private keys
entry: detect-private-key
language: python
types: [text]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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$
types: [python]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- 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)$
types: [text]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: file-contents-sorter
name: File Contents Sorter
description: Sort the lines in specified files (defaults to alphabetical). You must provide list of target files as input in your .pre-commit-config.yaml file.
entry: file-contents-sorter
language: python
files: '^$'
- 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$
types: [python]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: flake8
name: Flake8
description: This hook runs flake8.
entry: flake8
language: python
files: \.py$
types: [python]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: forbid-new-submodules
name: Forbid new submodules
language: python
entry: forbid-new-submodules
description: Prevent addition of new git submodules
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: mixed-line-ending
name: Mixed line ending
language: python
@ -139,23 +207,37 @@
name: "Don't commit to branch"
entry: no-commit-to-branch
language: python
files: .*
always_run: true
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: pyflakes
name: Pyflakes (DEPRECATED, use flake8)
description: This hook runs pyflakes. (This is deprecated, use flake8).
entry: pyflakes
language: python
files: \.py$
types: [python]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0
- id: requirements-txt-fixer
name: Fix requirements.txt
description: Sorts entries in requirements.txt
entry: requirements-txt-fixer
language: python
files: requirements.*\.txt$
- id: sort-simple-yaml
name: Sort simple YAML files
language: python
entry: sort-simple-yaml
description: Sorts simple YAML files which consist only of top-level keys, preserving comments and blocks.
files: '^$'
- 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)$
types: [text]
# for backward compatibility
files: ''
minimum_pre_commit_version: 0.15.0

View file

@ -1,3 +1,17 @@
0.9.1
=====
- Add `check-executables-have-shebangs` hook.
0.9.0
=====
- Add `sort-simple-yaml` hook
- Fix `requirements-txt-fixer` for empty files
- Add `file-contents-sorter` hook for sorting flat files
- `check-merge-conflict` now recognizes rebase conflicts
- Metadata now uses `types` (and therefore requires pre-commit 0.15.0). This
allows the text processing hooks to match *all* text files (and to match
files which would only be classifiable by their shebangs).
0.8.0
=====
- Add flag allowing missing keys to `detect-aws-credentials`

View file

@ -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: v0.8.0 # Use the ref you want to point at
sha: v0.9.1 # Use the ref you want to point at
hooks:
- id: trailing-whitespace
# - id: ...
@ -25,7 +25,8 @@ Add this to your `.pre-commit-config.yaml`
- `autopep8-wrapper` - Runs autopep8 over python source.
- Ignore PEP 8 violation types with `args: ['-i', '--ignore=E000,...']` or
through configuration of the `[pep8]` section in setup.cfg / tox.ini.
through configuration of the `[pycodestyle]` section in
setup.cfg / tox.ini.
- `check-added-large-files` - Prevent giant files from being committed.
- Specify what is "too large" with `args: ['--maxkb=123']` (default=500kB).
- `check-ast` - Simply check whether files parse as valid python.
@ -34,6 +35,8 @@ Add this to your `.pre-commit-config.yaml`
case-insensitive filesystem like MacOS HFS+ or Windows FAT.
- `check-docstring-first` - Checks for a common error of placing code before
the docstring.
- `check-executables-have-shebangs` - Checks that non-binary executables have a
proper shebang.
- `check-json` - Attempts to load all json files to verify syntax.
- `check-merge-conflict` - Check for files that contain merge conflict strings.
- `check-symlinks` - Checks for symlinks which do not point to anything.
@ -51,6 +54,7 @@ Add this to your `.pre-commit-config.yaml`
with single quoted strings.
- `end-of-file-fixer` - Makes sure files end in a newline and only a newline.
- `fix-encoding-pragma` - Add `# -*- coding: utf-8 -*-` to the top of python files.
- `file-contents-sorter` - Sort the lines in specified files (defaults to alphabetical). You must provide list of target files as input to it. Note that this hook WILL remove blank lines and does NOT respect any comments.
- To remove the coding pragma pass `--remove` (useful in a python3-only codebase)
- `flake8` - Run flake8 on your python files.
- `forbid-new-submodules` - Prevent addition of new git submodules.
@ -72,6 +76,7 @@ Add this to your `.pre-commit-config.yaml`
- `--no-sort-keys` - when autofixing, retain the original key ordering (instead of sorting the keys)
- `--top-keys comma,separated,keys` - Keys to keep at the top of mappings.
- `requirements-txt-fixer` - Sorts entries in requirements.txt
- `sort-simple-yaml` - Sorts simple YAML files which consist only of top-level keys, preserving comments and blocks.
- `trailing-whitespace` - Trims trailing whitespace.
- Markdown linebreak trailing spaces preserved for `.md` and`.markdown`;
use `args: ['--markdown-linebreak-ext=txt,text']` to add other extensions,

View file

@ -1,128 +1,135 @@
- 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]
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: check-ast
name: Check python ast
description: Simply check whether the files parse as valid python.
entry: check-ast
language: python
files: '\.py$'
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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$'
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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$
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: check-executables-have-shebangs
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: check-json
name: Check JSON
description: This hook checks json files for parseable syntax.
entry: check-json
language: python
files: \.json$
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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$
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: check-xml
name: Check Xml
description: This hook checks xml files for parseable syntax.
entry: check-xml
language: python
files: \.xml$
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: check-yaml
name: Check Yaml
description: This hook checks yaml files for parseable syntax.
entry: check-yaml
language: python
files: \.(yaml|yml|eyaml)$
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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$
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: detect-private-key
name: Detect Private Key
description: Detects the presence of private keys
entry: detect-private-key
language: python
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: end-of-file-fixer
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: file-contents-sorter
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: fix-encoding-pragma
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: flake8
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: forbid-new-submodules
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: mixed-line-ending
name: Mixed line ending
language: python
@ -130,32 +137,38 @@
description: Replaces or checks mixed line ending
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$
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: no-commit-to-branch
name: "Don't commit to branch"
entry: no-commit-to-branch
language: python
files: .*
always_run: true
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: pyflakes
name: Pyflakes (DEPRECATED, use flake8)
description: This hook runs pyflakes. (This is deprecated, use flake8).
entry: pyflakes
language: python
files: \.py$
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: requirements-txt-fixer
name: Fix requirements.txt
description: Sorts entries in requirements.txt
entry: requirements-txt-fixer
language: python
files: requirements.*\.txt$
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- id: sort-simple-yaml
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0
- 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)$
language: system
name: upgrade-your-pre-commit-version
entry: upgrade-your-pre-commit-version
files: ''
minimum_pre_commit_version: 0.15.0

View file

@ -51,7 +51,7 @@ def main(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument(
'filenames', nargs='*',
help='Filenames pre-commit believes are changed.'
help='Filenames pre-commit believes are changed.',
)
parser.add_argument(
'--maxkb', type=int, default=500,

View file

@ -4,7 +4,7 @@ from __future__ import unicode_literals
import argparse
import ast
import os.path
import platform
import sys
import traceback
@ -14,19 +14,19 @@ def check_ast(argv=None):
parser.add_argument('filenames', nargs='*')
args = parser.parse_args(argv)
_, interpreter = os.path.split(sys.executable)
retval = 0
for filename in args.filenames:
try:
ast.parse(open(filename, 'rb').read(), filename=filename)
except SyntaxError:
print('{}: failed parsing with {}:'.format(
filename, interpreter,
print('{}: failed parsing with {} {}:'.format(
filename,
platform.python_implementation(),
sys.version.partition(' ')[0],
))
print('\n{}'.format(
' ' + traceback.format_exc().replace('\n', '\n ')
' ' + traceback.format_exc().replace('\n', '\n '),
))
retval = 1
return retval

View file

@ -45,7 +45,7 @@ def main(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument(
'filenames', nargs='*',
help='Filenames pre-commit believes are changed.'
help='Filenames pre-commit believes are changed.',
)
args = parser.parse_args(argv)

View file

@ -1,4 +1,5 @@
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import argparse
@ -30,7 +31,7 @@ def check_docstring_first(src, filename='<unknown>'):
'{}:{} Multiple module docstrings '
'(first docstring on line {}).'.format(
filename, sline, found_docstring_line,
)
),
)
return 1
elif found_code_line is not None:
@ -38,7 +39,7 @@ def check_docstring_first(src, filename='<unknown>'):
'{}:{} Module docstring appears after code '
'(code seen on line {}).'.format(
filename, sline, found_code_line,
)
),
)
return 1
else:

View file

@ -0,0 +1,40 @@
"""Check that executable text files have a shebang."""
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import pipes
import sys
def check_has_shebang(path):
with open(path, 'rb') as f:
first_bytes = f.read(2)
if first_bytes != b'#!':
print(
'{path}: marked executable but has no (or invalid) shebang!\n'
" If it isn't supposed to be executable, try: chmod -x {quoted}\n"
' If it is supposed to be executable, double-check its shebang.'.format(
path=path,
quoted=pipes.quote(path),
),
file=sys.stderr,
)
return 1
else:
return 0
def main(argv=None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('filenames', nargs='*')
args = parser.parse_args(argv)
retv = 0
for filename in args.filenames:
retv |= check_has_shebang(filename)
return retv

View file

@ -7,7 +7,7 @@ CONFLICT_PATTERNS = [
b'<<<<<<< ',
b'======= ',
b'=======\n',
b'>>>>>>> '
b'>>>>>>> ',
]
WARNING_MSG = 'Merge conflict string "{0}" found in {1}:{2}'
@ -15,7 +15,11 @@ WARNING_MSG = 'Merge conflict string "{0}" found in {1}:{2}'
def is_in_merge():
return (
os.path.exists(os.path.join('.git', 'MERGE_MSG')) and
os.path.exists(os.path.join('.git', 'MERGE_HEAD'))
(
os.path.exists(os.path.join('.git', 'MERGE_HEAD')) or
os.path.exists(os.path.join('.git', 'rebase-apply')) or
os.path.exists(os.path.join('.git', 'rebase-merge'))
)
)

View file

@ -29,7 +29,7 @@ class ImportStatementParser(ast.NodeVisitor):
def visit_ImportFrom(self, node):
if node.module in DEBUG_STATEMENTS:
self.debug_import_statements.append(
DebugStatement(node.module, node.lineno, node.col_offset)
DebugStatement(node.module, node.lineno, node.col_offset),
)
@ -52,7 +52,7 @@ def check_file_for_debug_statements(filename):
debug_statement.line,
debug_statement.col,
debug_statement.name,
)
),
)
return 1
else:

View file

@ -12,7 +12,7 @@ def get_aws_credential_files_from_env():
files = set()
for env_var in (
'AWS_CONFIG_FILE', 'AWS_CREDENTIAL_FILE', 'AWS_SHARED_CREDENTIALS_FILE',
'BOTO_CONFIG'
'BOTO_CONFIG',
):
if env_var in os.environ:
files.add(os.environ[env_var])
@ -23,7 +23,7 @@ def get_aws_secrets_from_env():
"""Extract AWS secrets from environment variables."""
keys = set()
for env_var in (
'AWS_SECRET_ACCESS_KEY', 'AWS_SECURITY_TOKEN', 'AWS_SESSION_TOKEN'
'AWS_SECRET_ACCESS_KEY', 'AWS_SECURITY_TOKEN', 'AWS_SESSION_TOKEN',
):
if env_var in os.environ:
keys.add(os.environ[env_var])
@ -50,7 +50,7 @@ def get_aws_secrets_from_file(credentials_file):
for section in parser.sections():
for var in (
'aws_secret_access_key', 'aws_security_token',
'aws_session_token'
'aws_session_token',
):
try:
keys.add(parser.get(section, var))
@ -93,13 +93,13 @@ def main(argv=None):
help=(
'Location of additional AWS credential files from which to get '
'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.'
help='Allow hook to pass when no credentials are detected.',
)
args = parser.parse_args(argv)
@ -124,7 +124,7 @@ def main(argv=None):
print(
'No AWS keys were found in the configured credential files and '
'environment variables.\nPlease ensure you have the correct '
'setting for --credentials-file'
'setting for --credentials-file',
)
return 2

View file

@ -0,0 +1,52 @@
"""
A very simple pre-commit hook that, when passed one or more filenames
as arguments, will sort the lines in those files.
An example use case for this: you have a deploy-whitelist.txt file
in a repo that contains a list of filenames that is used to specify
files to be included in a docker container. This file has one filename
per line. Various users are adding/removing lines from this file; using
this hook on that file should reduce the instances of git merge
conflicts and keep the file nicely ordered.
"""
from __future__ import print_function
import argparse
PASS = 0
FAIL = 1
def sort_file_contents(f):
before = list(f)
after = sorted([line.strip(b'\n\r') for line in before if line.strip()])
before_string = b''.join(before)
after_string = b'\n'.join(after) + b'\n'
if before_string == after_string:
return PASS
else:
f.seek(0)
f.write(after_string)
f.truncate()
return FAIL
def main(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='+', help='Files to sort')
args = parser.parse_args(argv)
retv = PASS
for arg in args.filenames:
with open(arg, 'rb+') as file_obj:
ret_for_file = sort_file_contents(file_obj)
if ret_for_file:
print('Sorting {}'.format(arg))
retv |= ret_for_file
return retv

View file

@ -15,7 +15,8 @@ def is_on_branch(protected):
def main(argv=[]):
parser = argparse.ArgumentParser()
parser.add_argument(
'-b', '--branch', default='master', help='branch to disallow commits to')
'-b', '--branch', default='master', help='branch to disallow commits to',
)
args = parser.parse_args(argv)
return int(is_on_branch(args.branch))

View file

@ -120,7 +120,7 @@ def pretty_format_json(argv=None):
except simplejson.JSONDecodeError:
print(
"Input File {} is not a valid JSON, consider using check-json"
.format(json_file)
.format(json_file),
)
return 1

View file

@ -3,6 +3,10 @@ from __future__ import print_function
import argparse
PASS = 0
FAIL = 1
class Requirement(object):
def __init__(self):
@ -30,21 +34,25 @@ class Requirement(object):
def fix_requirements(f):
requirements = []
before = []
before = tuple(f)
after = []
for line in f:
before.append(line)
before_string = b''.join(before)
# If the most recent requirement object has a value, then it's time to
# start building the next requirement object.
# If the file is empty (i.e. only whitespace/newlines) exit early
if before_string.strip() == b'':
return PASS
for line in before:
# If the most recent requirement object has a value, then it's
# time to start building the next requirement object.
if not len(requirements) or requirements[-1].value is not None:
requirements.append(Requirement())
requirement = requirements[-1]
# If we see a newline before any requirements, then this is a top of
# file comment.
# If we see a newline before any requirements, then this is a
# top of file comment.
if len(requirements) == 1 and line.strip() == b'':
if len(requirement.comments) and requirement.comments[0].startswith(b'#'):
requirement.value = b'\n'
@ -56,20 +64,18 @@ def fix_requirements(f):
requirement.value = line
for requirement in sorted(requirements):
for comment in requirement.comments:
after.append(comment)
after.extend(requirement.comments)
after.append(requirement.value)
before_string = b''.join(before)
after_string = b''.join(after)
if before_string == after_string:
return 0
return PASS
else:
f.seek(0)
f.write(after_string)
f.truncate()
return 1
return FAIL
def fix_requirements_txt(argv=None):
@ -77,7 +83,7 @@ def fix_requirements_txt(argv=None):
parser.add_argument('filenames', nargs='*', help='Filenames to fix')
args = parser.parse_args(argv)
retv = 0
retv = PASS
for arg in args.filenames:
with open(arg, 'rb+') as file_obj:

View file

@ -0,0 +1,123 @@
#!/usr/bin/env python
"""Sort a simple YAML file, keeping blocks of comments and definitions
together.
We assume a strict subset of YAML that looks like:
# block of header comments
# here that should always
# be at the top of the file
# optional comments
# can go here
key: value
key: value
key: value
In other words, we don't sort deeper than the top layer, and might corrupt
complicated YAML files.
"""
from __future__ import print_function
import argparse
QUOTES = ["'", '"']
def sort(lines):
"""Sort a YAML file in alphabetical order, keeping blocks together.
:param lines: array of strings (without newlines)
:return: sorted array of strings
"""
# make a copy of lines since we will clobber it
lines = list(lines)
new_lines = parse_block(lines, header=True)
for block in sorted(parse_blocks(lines), key=first_key):
if new_lines:
new_lines.append('')
new_lines.extend(block)
return new_lines
def parse_block(lines, header=False):
"""Parse and return a single block, popping off the start of `lines`.
If parsing a header block, we stop after we reach a line that is not a
comment. Otherwise, we stop after reaching an empty line.
:param lines: list of lines
:param header: whether we are parsing a header block
:return: list of lines that form the single block
"""
block_lines = []
while lines and lines[0] and (not header or lines[0].startswith('#')):
block_lines.append(lines.pop(0))
return block_lines
def parse_blocks(lines):
"""Parse and return all possible blocks, popping off the start of `lines`.
:param lines: list of lines
:return: list of blocks, where each block is a list of lines
"""
blocks = []
while lines:
if lines[0] == '':
lines.pop(0)
else:
blocks.append(parse_block(lines))
return blocks
def first_key(lines):
"""Returns a string representing the sort key of a block.
The sort key is the first YAML key we encounter, ignoring comments, and
stripping leading quotes.
>>> print(test)
# some comment
'foo': true
>>> first_key(test)
'foo'
"""
for line in lines:
if line.startswith('#'):
continue
if any(line.startswith(quote) for quote in QUOTES):
return line[1:]
return line
def main(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='*', help='Filenames to fix')
args = parser.parse_args(argv)
retval = 0
for filename in args.filenames:
with open(filename, 'r+') as f:
lines = [line.rstrip() for line in f.readlines()]
new_lines = sort(lines)
if lines != new_lines:
print("Fixing file `{filename}`".format(filename=filename))
f.seek(0)
f.write("\n".join(new_lines) + "\n")
f.truncate()
retval = 1
return retval
if __name__ == '__main__':
exit(main())

View file

@ -11,7 +11,7 @@ def validate_files(argv=None):
parser.add_argument('filenames', nargs='*')
parser.add_argument(
'--django', default=False, action='store_true',
help='Use Django-style test naming pattern (test*.py)'
help='Use Django-style test naming pattern (test*.py)',
)
args = parser.parse_args(argv)
@ -27,8 +27,8 @@ def validate_files(argv=None):
retcode = 1
print(
'{} does not match pattern "{}"'.format(
filename, test_name_pattern
)
filename, test_name_pattern,
),
)
return retcode

View file

@ -36,7 +36,7 @@ def fix_trailing_whitespace(argv=None):
const=[],
default=argparse.SUPPRESS,
dest='markdown_linebreak_ext',
help='Do not preserve linebreak spaces in Markdown'
help='Do not preserve linebreak spaces in Markdown',
)
parser.add_argument(
'--markdown-linebreak-ext',
@ -45,7 +45,7 @@ def fix_trailing_whitespace(argv=None):
default=['md,markdown'],
metavar='*|EXT[,EXT,...]',
nargs='?',
help='Markdown extensions (or *) for linebreak spaces'
help='Markdown extensions (or *) for linebreak spaces',
)
parser.add_argument('filenames', nargs='*', help='Filenames to fix')
args = parser.parse_args(argv)
@ -69,7 +69,7 @@ def fix_trailing_whitespace(argv=None):
parser.error(
"bad --markdown-linebreak-ext extension '{}' (has . / \\ :)\n"
" (probably filename; use '--markdown-linebreak-ext=EXT')"
.format(ext)
.format(ext),
)
return_code = 0

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.8.0',
version='0.9.1',
author='Anthony Sottile',
author_email='asottile@umich.edu',
@ -24,9 +24,9 @@ setup(
packages=find_packages(exclude=('tests*', 'testing*')),
install_requires=[
# quickfix to prevent pep8 conflicts
# quickfix to prevent pycodestyle conflicts
'flake8!=2.5.3',
'autopep8>=1.1',
'autopep8>=1.3',
'pyyaml',
'simplejson',
'six',
@ -39,6 +39,7 @@ setup(
'check-byte-order-marker = pre_commit_hooks.check_byte_order_marker:main',
'check-case-conflict = pre_commit_hooks.check_case_conflict:main',
'check-docstring-first = pre_commit_hooks.check_docstring_first:main',
'check-executables-have-shebangs = pre_commit_hooks.check_executables_have_shebangs:main',
'check-json = pre_commit_hooks.check_json:check_json',
'check-merge-conflict = pre_commit_hooks.check_merge_conflict:detect_merge_conflict',
'check-symlinks = pre_commit_hooks.check_symlinks:check_symlinks',
@ -49,6 +50,7 @@ setup(
'detect-private-key = pre_commit_hooks.detect_private_key:detect_private_key',
'double-quote-string-fixer = pre_commit_hooks.string_fixer:main',
'end-of-file-fixer = pre_commit_hooks.end_of_file_fixer:end_of_file_fixer',
'file-contents-sorter = pre_commit_hooks.file_contents_sorter:main',
'fix-encoding-pragma = pre_commit_hooks.fix_encoding_pragma:main',
'forbid-new-submodules = pre_commit_hooks.forbid_new_submodules:main',
'mixed-line-ending = pre_commit_hooks.mixed_line_ending:mixed_line_ending',
@ -56,6 +58,7 @@ setup(
'no-commit-to-branch = pre_commit_hooks.no_commit_to_branch:main',
'pretty-format-json = pre_commit_hooks.pretty_format_json:pretty_format_json',
'requirements-txt-fixer = pre_commit_hooks.requirements_txt_fixer:fix_requirements_txt',
'sort-simple-yaml = pre_commit_hooks.sort_simple_yaml:main',
'trailing-whitespace-fixer = pre_commit_hooks.trailing_whitespace_fixer:fix_trailing_whitespace',
],
},

View file

@ -9,4 +9,4 @@ aws_secret_access_key = z2rpgs5uit782eapz5l1z0y2lurtsyyk6hcfozlb
aws_access_key_id = AKIAJIMMINYCRICKET0A
aws_secret_access_key = ixswosj8gz3wuik405jl9k3vdajsnxfhnpui38ez
[test]
aws_session_token = foo
aws_session_token = foo

View file

@ -2,4 +2,4 @@
[production]
aws_access_key_id = AKIAVOGONSVOGONS0042
aws_secret_access_key = z2rpgs5uit782eapz5l1z0y2lurtsyyk6hcfozlb
aws_session_token = foo
aws_session_token = foo

View file

@ -1,3 +1,3 @@
# file with an AWS session token
[production]
aws_session_token = foo
aws_session_token = foo

View file

@ -23,6 +23,6 @@ def test_main_failing(tmpdir, input_src, expected_ret, output_src):
def test_respects_config_file(tmpdir):
with tmpdir.as_cwd():
tmpdir.join('setup.cfg').write('[pep8]\nignore=E221')
tmpdir.join('setup.cfg').write('[pycodestyle]\nignore=E221')
tmpdir.join('test.py').write('print(1 + 2)\n')
assert main(['test.py', '-i', '-v']) == 0

View file

@ -81,12 +81,7 @@ def test_allows_gitlfs(temp_git_dir): # pragma: no cover
with temp_git_dir.as_cwd():
# Work around https://github.com/github/git-lfs/issues/913
cmd_output(
'git',
'commit',
'--no-gpg-sign',
'--allow-empty',
'-m',
'foo',
'git', 'commit', '--no-gpg-sign', '--allow-empty', '-m', 'foo',
)
cmd_output('git', 'lfs', 'install')
temp_git_dir.join('f.py').write('a' * 10000)

View file

@ -19,7 +19,7 @@ TESTS = (
'"foo"\n',
1,
'{filename}:2 Module docstring appears after code '
'(code seen on line 1).\n'
'(code seen on line 1).\n',
),
# Test double docstring
(
@ -28,7 +28,7 @@ TESTS = (
'"fake docstring"\n',
1,
'{filename}:3 Multiple module docstrings '
'(first docstring on line 1).\n'
'(first docstring on line 1).\n',
),
# Test multiple lines of code above
(

View file

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
import pytest
from pre_commit_hooks.check_executables_have_shebangs import main
@pytest.mark.parametrize(
'content', (
b'#!/bin/bash\nhello world\n',
b'#!/usr/bin/env python3.6',
b'#!python',
'#!☃'.encode('UTF-8'),
),
)
def test_has_shebang(content, tmpdir):
path = tmpdir.join('path')
path.write(content, 'wb')
assert main((path.strpath,)) == 0
@pytest.mark.parametrize(
'content', (
b'',
b' #!python\n',
b'\n#!python\n',
b'python\n',
''.encode('UTF-8'),
),
)
def test_bad_shebang(content, tmpdir, capsys):
path = tmpdir.join('path')
path.write(content, 'wb')
assert main((path.strpath,)) == 1
_, stderr = capsys.readouterr()
assert stderr.startswith('{}: marked executable but'.format(path.strpath))

View file

@ -4,11 +4,13 @@ from pre_commit_hooks.check_json import check_json
from testing.util import get_resource_path
@pytest.mark.parametrize(('filename', 'expected_retval'), (
('bad_json.notjson', 1),
('bad_json_latin1.nonjson', 1),
('ok_json.json', 0),
))
@pytest.mark.parametrize(
('filename', 'expected_retval'), (
('bad_json.notjson', 1),
('bad_json_latin1.nonjson', 1),
('ok_json.json', 0),
),
)
def test_check_json(capsys, filename, expected_retval):
ret = check_json([get_resource_path(filename)])
assert ret == expected_retval

View file

@ -45,7 +45,7 @@ def f1_is_a_conflict_file(tmpdir):
'child\n'
'=======\n'
'parent\n'
'>>>>>>>'
'>>>>>>>',
) or f1.startswith(
'<<<<<<< HEAD\n'
'child\n'
@ -53,7 +53,15 @@ def f1_is_a_conflict_file(tmpdir):
'||||||| merged common ancestors\n'
'=======\n'
'parent\n'
'>>>>>>>'
'>>>>>>>',
) or f1.startswith(
# .gitconfig with [pull] rebase = preserve causes a rebase which
# flips parent / child
'<<<<<<< HEAD\n'
'parent\n'
'=======\n'
'child\n'
'>>>>>>>',
)
assert os.path.exists(os.path.join('.git', 'MERGE_MSG'))
yield
@ -85,7 +93,7 @@ def repository_is_pending_merge(tmpdir):
repo2_f2.write('child\n')
cmd_output('git', 'add', '--', repo2_f2.strpath)
cmd_output('git', 'commit', '--no-gpg-sign', '-m', 'clone commit2')
cmd_output('git', 'pull', '--no-commit')
cmd_output('git', 'pull', '--no-commit', '--no-rebase')
# We should end up in a pending merge
assert repo2_f1.read() == 'parent\n'
assert repo2_f2.read() == 'child\n'

View file

@ -7,10 +7,12 @@ from testing.util import get_resource_path
@pytest.mark.xfail(os.name == 'nt', reason='No symlink support on windows')
@pytest.mark.parametrize(('filename', 'expected_retval'), (
('broken_symlink', 1),
('working_symlink', 0),
))
@pytest.mark.parametrize(
('filename', 'expected_retval'), (
('broken_symlink', 1),
('working_symlink', 0),
),
)
def test_check_symlinks(filename, expected_retval):
ret = check_symlinks([get_resource_path(filename)])
assert ret == expected_retval

View file

@ -4,10 +4,12 @@ from pre_commit_hooks.check_xml import check_xml
from testing.util import get_resource_path
@pytest.mark.parametrize(('filename', 'expected_retval'), (
('bad_xml.notxml', 1),
('ok_xml.xml', 0),
))
@pytest.mark.parametrize(
('filename', 'expected_retval'), (
('bad_xml.notxml', 1),
('ok_xml.xml', 0),
),
)
def test_check_xml(filename, expected_retval):
ret = check_xml([get_resource_path(filename)])
assert ret == expected_retval

View file

@ -4,10 +4,12 @@ from pre_commit_hooks.check_yaml import check_yaml
from testing.util import get_resource_path
@pytest.mark.parametrize(('filename', 'expected_retval'), (
('bad_yaml.notyaml', 1),
('ok_yaml.yaml', 0),
))
@pytest.mark.parametrize(
('filename', 'expected_retval'), (
('bad_yaml.notyaml', 1),
('ok_yaml.yaml', 0),
),
)
def test_check_yaml(filename, expected_retval):
ret = check_yaml([get_resource_path(filename)])
assert ret == expected_retval

View file

@ -10,30 +10,36 @@ from testing.util import get_resource_path
@pytest.fixture
def ast_with_no_debug_imports():
return ast.parse("""
return ast.parse(
"""
import foo
import bar
import baz
from foo import bar
""")
""",
)
@pytest.fixture
def ast_with_debug_import_form_1():
return ast.parse("""
return ast.parse(
"""
import ipdb; ipdb.set_trace()
""")
""",
)
@pytest.fixture
def ast_with_debug_import_form_2():
return ast.parse("""
return ast.parse(
"""
from pudb import set_trace; set_trace()
""")
""",
)
def test_returns_no_debug_statements(ast_with_no_debug_imports):
@ -46,7 +52,7 @@ def test_returns_one_form_1(ast_with_debug_import_form_1):
visitor = ImportStatementParser()
visitor.visit(ast_with_debug_import_form_1)
assert visitor.debug_import_statements == [
DebugStatement('ipdb', 3, 0)
DebugStatement('ipdb', 3, 0),
]
@ -54,7 +60,7 @@ def test_returns_one_form_2(ast_with_debug_import_form_2):
visitor = ImportStatementParser()
visitor.visit(ast_with_debug_import_form_2)
assert visitor.debug_import_statements == [
DebugStatement('pudb', 3, 0)
DebugStatement('pudb', 3, 0),
]

View file

@ -21,16 +21,16 @@ from testing.util import get_resource_path
(
{
'AWS_DUMMY_KEY': '/foo', 'AWS_CONFIG_FILE': '/bar',
'AWS_CREDENTIAL_FILE': '/baz'
'AWS_CREDENTIAL_FILE': '/baz',
},
{'/bar', '/baz'}
{'/bar', '/baz'},
),
(
{
'AWS_CONFIG_FILE': '/foo', 'AWS_CREDENTIAL_FILE': '/bar',
'AWS_SHARED_CREDENTIALS_FILE': '/baz'
'AWS_SHARED_CREDENTIALS_FILE': '/baz',
},
{'/foo', '/bar', '/baz'}
{'/foo', '/bar', '/baz'},
),
),
)
@ -51,7 +51,7 @@ def test_get_aws_credentials_file_from_env(env_vars, values):
({'AWS_DUMMY_KEY': 'foo', 'AWS_SECRET_ACCESS_KEY': 'bar'}, {'bar'}),
(
{'AWS_SECRET_ACCESS_KEY': 'foo', 'AWS_SECURITY_TOKEN': 'bar'},
{'foo', 'bar'}
{'foo', 'bar'},
),
),
)
@ -66,19 +66,21 @@ def test_get_aws_secrets_from_env(env_vars, values):
(
(
'aws_config_with_secret.ini',
{'z2rpgs5uit782eapz5l1z0y2lurtsyyk6hcfozlb'}
{'z2rpgs5uit782eapz5l1z0y2lurtsyyk6hcfozlb'},
),
('aws_config_with_session_token.ini', {'foo'}),
('aws_config_with_secret_and_session_token.ini',
{'z2rpgs5uit782eapz5l1z0y2lurtsyyk6hcfozlb', 'foo'}),
(
'aws_config_with_secret_and_session_token.ini',
{'z2rpgs5uit782eapz5l1z0y2lurtsyyk6hcfozlb', 'foo'},
),
(
'aws_config_with_multiple_sections.ini',
{
'7xebzorgm5143ouge9gvepxb2z70bsb2rtrh099e',
'z2rpgs5uit782eapz5l1z0y2lurtsyyk6hcfozlb',
'ixswosj8gz3wuik405jl9k3vdajsnxfhnpui38ez',
'foo'
}
'foo',
},
),
('aws_config_without_secrets.ini', set()),
('nonsense.txt', set()),
@ -121,7 +123,7 @@ def test_non_existent_credentials(mock_secrets_env, mock_secrets_file, capsys):
mock_secrets_file.return_value = set()
ret = main((
get_resource_path('aws_config_without_secrets.ini'),
"--credentials-file=testing/resources/credentailsfilethatdoesntexist"
"--credentials-file=testing/resources/credentailsfilethatdoesntexist",
))
assert ret == 2
out, _ = capsys.readouterr()
@ -141,6 +143,6 @@ def test_non_existent_credentials_with_allow_flag(mock_secrets_env, mock_secrets
ret = main((
get_resource_path('aws_config_without_secrets.ini'),
"--credentials-file=testing/resources/credentailsfilethatdoesntexist",
"--allow-missing-credentials"
"--allow-missing-credentials",
))
assert ret == 0

View file

@ -0,0 +1,33 @@
import pytest
from pre_commit_hooks.file_contents_sorter import FAIL
from pre_commit_hooks.file_contents_sorter import main
from pre_commit_hooks.file_contents_sorter import PASS
@pytest.mark.parametrize(
('input_s', 'expected_retval', 'output'),
(
(b'', FAIL, b'\n'),
(b'lonesome\n', PASS, b'lonesome\n'),
(b'missing_newline', FAIL, b'missing_newline\n'),
(b'newline\nmissing', FAIL, b'missing\nnewline\n'),
(b'missing\nnewline', FAIL, b'missing\nnewline\n'),
(b'alpha\nbeta\n', PASS, b'alpha\nbeta\n'),
(b'beta\nalpha\n', FAIL, b'alpha\nbeta\n'),
(b'C\nc\n', PASS, b'C\nc\n'),
(b'c\nC\n', FAIL, b'C\nc\n'),
(b'mag ical \n tre vor\n', FAIL, b' tre vor\nmag ical \n'),
(b'@\n-\n_\n#\n', FAIL, b'#\n-\n@\n_\n'),
(b'extra\n\n\nwhitespace\n', FAIL, b'extra\nwhitespace\n'),
(b'whitespace\n\n\nextra\n', FAIL, b'extra\nwhitespace\n'),
),
)
def test_integration(input_s, expected_retval, output, tmpdir):
path = tmpdir.join('file.txt')
path.write_binary(input_s)
output_retval = main([path.strpath])
assert path.read_binary() == output
assert output_retval == expected_retval

View file

@ -56,7 +56,7 @@ def test_integration_remove_ok(tmpdir):
b'# -*- coding: utf-8 -*-\n'
b'foo = "bar"\n'
),
)
),
)
def test_ok_inputs(input_str):
bytesio = io.BytesIO(input_str)
@ -100,7 +100,7 @@ def test_ok_inputs(input_str):
(b'#!/usr/bin/env python\n', b''),
(b'#!/usr/bin/env python\n#coding: utf8\n', b''),
(b'#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n', b''),
)
),
)
def test_not_ok_inputs(input_str, output):
bytesio = io.BytesIO(input_str)

View file

@ -10,10 +10,14 @@ from pre_commit_hooks.forbid_new_submodules import main
def git_dir_with_git_dir(tmpdir):
with tmpdir.as_cwd():
cmd_output('git', 'init', '.')
cmd_output('git', 'commit', '-m', 'init', '--allow-empty')
cmd_output(
'git', 'commit', '-m', 'init', '--allow-empty', '--no-gpg-sign',
)
cmd_output('git', 'init', 'foo')
with tmpdir.join('foo').as_cwd():
cmd_output('git', 'commit', '-m', 'init', '--allow-empty')
cmd_output(
'git', 'commit', '-m', 'init', '--allow-empty', '--no-gpg-sign',
cwd=tmpdir.join('foo').strpath,
)
yield

View file

@ -1,7 +1,43 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import io
import yaml
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
def _assert_parseable_in_old_pre_commit(hooks):
for hook in hooks:
assert {'id', 'name', 'entry', 'files', 'language'} <= set(hook)
def test_legacy_hooks():
with io.open('hooks.yaml') as legacy_file:
legacy = yaml.load(legacy_file.read())
with io.open('.pre-commit-hooks.yaml') as hooks_file:
hooks = yaml.load(hooks_file.read())
# The same set of hooks should be defined in both files
new_hook_ids = {hook['id'] for hook in hooks}
legacy_hook_ids = {hook['id'] for hook in legacy}
assert new_hook_ids == legacy_hook_ids
# Both files should be parseable by pre-commit<0.15.0
_assert_parseable_in_old_pre_commit(legacy)
_assert_parseable_in_old_pre_commit(hooks)
# The legacy file should force upgrading
for hook in legacy:
del hook['id']
assert hook == {
'language': 'system',
'name': 'upgrade-your-pre-commit-version',
'entry': 'upgrade-your-pre-commit-version',
'files': '',
'minimum_pre_commit_version': '0.15.0',
}
# Each hook should require a new version if it uses types
for hook in hooks:
if 'types' in hook:
assert hook['minimum_pre_commit_version'] == '0.15.0'

View file

@ -17,35 +17,41 @@ def test_parse_indent():
parse_indent('-2')
@pytest.mark.parametrize(('filename', 'expected_retval'), (
('not_pretty_formatted_json.json', 1),
('unsorted_pretty_formatted_json.json', 1),
('non_ascii_pretty_formatted_json.json', 1),
('pretty_formatted_json.json', 0),
))
@pytest.mark.parametrize(
('filename', 'expected_retval'), (
('not_pretty_formatted_json.json', 1),
('unsorted_pretty_formatted_json.json', 1),
('non_ascii_pretty_formatted_json.json', 1),
('pretty_formatted_json.json', 0),
),
)
def test_pretty_format_json(filename, expected_retval):
ret = pretty_format_json([get_resource_path(filename)])
assert ret == expected_retval
@pytest.mark.parametrize(('filename', 'expected_retval'), (
('not_pretty_formatted_json.json', 1),
('unsorted_pretty_formatted_json.json', 0),
('non_ascii_pretty_formatted_json.json', 1),
('pretty_formatted_json.json', 0),
))
@pytest.mark.parametrize(
('filename', 'expected_retval'), (
('not_pretty_formatted_json.json', 1),
('unsorted_pretty_formatted_json.json', 0),
('non_ascii_pretty_formatted_json.json', 1),
('pretty_formatted_json.json', 0),
),
)
def test_unsorted_pretty_format_json(filename, expected_retval):
ret = pretty_format_json(['--no-sort-keys', get_resource_path(filename)])
assert ret == expected_retval
@pytest.mark.parametrize(('filename', 'expected_retval'), (
('not_pretty_formatted_json.json', 1),
('unsorted_pretty_formatted_json.json', 1),
('non_ascii_pretty_formatted_json.json', 1),
('pretty_formatted_json.json', 1),
('tab_pretty_formatted_json.json', 0),
))
@pytest.mark.parametrize(
('filename', 'expected_retval'), (
('not_pretty_formatted_json.json', 1),
('unsorted_pretty_formatted_json.json', 1),
('non_ascii_pretty_formatted_json.json', 1),
('pretty_formatted_json.json', 1),
('tab_pretty_formatted_json.json', 0),
),
)
def test_tab_pretty_format_json(filename, expected_retval):
ret = pretty_format_json(['--indent', '\t', get_resource_path(filename)])
assert ret == expected_retval

View file

@ -1,31 +1,41 @@
import pytest
from pre_commit_hooks.requirements_txt_fixer import FAIL
from pre_commit_hooks.requirements_txt_fixer import fix_requirements_txt
from pre_commit_hooks.requirements_txt_fixer import PASS
from pre_commit_hooks.requirements_txt_fixer import Requirement
# Input, expected return value, expected output
TESTS = (
(b'foo\nbar\n', 1, b'bar\nfoo\n'),
(b'bar\nfoo\n', 0, b'bar\nfoo\n'),
(b'#comment1\nfoo\n#comment2\nbar\n', 1, b'#comment2\nbar\n#comment1\nfoo\n'),
(b'#comment1\nbar\n#comment2\nfoo\n', 0, b'#comment1\nbar\n#comment2\nfoo\n'),
(b'#comment\n\nfoo\nbar\n', 1, b'#comment\n\nbar\nfoo\n'),
(b'#comment\n\nbar\nfoo\n', 0, b'#comment\n\nbar\nfoo\n'),
(b'\nfoo\nbar\n', 1, b'bar\n\nfoo\n'),
(b'\nbar\nfoo\n', 0, b'\nbar\nfoo\n'),
(b'pyramid==1\npyramid-foo==2\n', 0, b'pyramid==1\npyramid-foo==2\n'),
(b'ocflib\nDjango\nPyMySQL\n', 1, b'Django\nocflib\nPyMySQL\n'),
(b'-e git+ssh://git_url@tag#egg=ocflib\nDjango\nPyMySQL\n', 1, b'Django\n-e git+ssh://git_url@tag#egg=ocflib\nPyMySQL\n'),
@pytest.mark.parametrize(
('input_s', 'expected_retval', 'output'),
(
(b'', PASS, b''),
(b'\n', PASS, b'\n'),
(b'foo\nbar\n', FAIL, b'bar\nfoo\n'),
(b'bar\nfoo\n', PASS, b'bar\nfoo\n'),
(b'#comment1\nfoo\n#comment2\nbar\n', FAIL, b'#comment2\nbar\n#comment1\nfoo\n'),
(b'#comment1\nbar\n#comment2\nfoo\n', PASS, b'#comment1\nbar\n#comment2\nfoo\n'),
(b'#comment\n\nfoo\nbar\n', FAIL, b'#comment\n\nbar\nfoo\n'),
(b'#comment\n\nbar\nfoo\n', PASS, b'#comment\n\nbar\nfoo\n'),
(b'\nfoo\nbar\n', FAIL, b'bar\n\nfoo\n'),
(b'\nbar\nfoo\n', PASS, b'\nbar\nfoo\n'),
(b'pyramid==1\npyramid-foo==2\n', PASS, b'pyramid==1\npyramid-foo==2\n'),
(b'ocflib\nDjango\nPyMySQL\n', FAIL, b'Django\nocflib\nPyMySQL\n'),
(
b'-e git+ssh://git_url@tag#egg=ocflib\nDjango\nPyMySQL\n',
FAIL,
b'Django\n-e git+ssh://git_url@tag#egg=ocflib\nPyMySQL\n',
),
),
)
@pytest.mark.parametrize(('input_s', 'expected_retval', 'output'), TESTS)
def test_integration(input_s, expected_retval, output, tmpdir):
path = tmpdir.join('file.txt')
path.write_binary(input_s)
assert fix_requirements_txt([path.strpath]) == expected_retval
output_retval = fix_requirements_txt([path.strpath])
assert path.read_binary() == output
assert output_retval == expected_retval
def test_requirement_object():

View file

@ -0,0 +1,120 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import pytest
from pre_commit_hooks.sort_simple_yaml import first_key
from pre_commit_hooks.sort_simple_yaml import main
from pre_commit_hooks.sort_simple_yaml import parse_block
from pre_commit_hooks.sort_simple_yaml import parse_blocks
from pre_commit_hooks.sort_simple_yaml import sort
RETVAL_GOOD = 0
RETVAL_BAD = 1
TEST_SORTS = [
(
['c: true', '', 'b: 42', 'a: 19'],
['b: 42', 'a: 19', '', 'c: true'],
RETVAL_BAD,
),
(
['# i am', '# a header', '', 'c: true', '', 'b: 42', 'a: 19'],
['# i am', '# a header', '', 'b: 42', 'a: 19', '', 'c: true'],
RETVAL_BAD,
),
(
['# i am', '# a header', '', 'already: sorted', '', 'yup: i am'],
['# i am', '# a header', '', 'already: sorted', '', 'yup: i am'],
RETVAL_GOOD,
),
(
['# i am', '# a header'],
['# i am', '# a header'],
RETVAL_GOOD,
),
]
@pytest.mark.parametrize('bad_lines,good_lines,retval', TEST_SORTS)
def test_integration_good_bad_lines(tmpdir, bad_lines, good_lines, retval):
file_path = os.path.join(tmpdir.strpath, 'foo.yaml')
with open(file_path, 'w') as f:
f.write("\n".join(bad_lines) + "\n")
assert main([file_path]) == retval
with open(file_path, 'r') as f:
assert [line.rstrip() for line in f.readlines()] == good_lines
def test_parse_header():
lines = ['# some header', '# is here', '', 'this is not a header']
assert parse_block(lines, header=True) == ['# some header', '# is here']
assert lines == ['', 'this is not a header']
lines = ['this is not a header']
assert parse_block(lines, header=True) == []
assert lines == ['this is not a header']
def test_parse_block():
# a normal block
lines = ['a: 42', 'b: 17', '', 'c: 19']
assert parse_block(lines) == ['a: 42', 'b: 17']
assert lines == ['', 'c: 19']
# a block at the end
lines = ['c: 19']
assert parse_block(lines) == ['c: 19']
assert lines == []
# no block
lines = []
assert parse_block(lines) == []
assert lines == []
def test_parse_blocks():
# normal blocks
lines = ['a: 42', 'b: 17', '', 'c: 19']
assert parse_blocks(lines) == [['a: 42', 'b: 17'], ['c: 19']]
assert lines == []
# a single block
lines = ['a: 42', 'b: 17']
assert parse_blocks(lines) == [['a: 42', 'b: 17']]
assert lines == []
# no blocks
lines = []
assert parse_blocks(lines) == []
assert lines == []
def test_first_key():
# first line
lines = ['a: 42', 'b: 17', '', 'c: 19']
assert first_key(lines) == 'a: 42'
# second line
lines = ['# some comment', 'a: 42', 'b: 17', '', 'c: 19']
assert first_key(lines) == 'a: 42'
# second line with quotes
lines = ['# some comment', '"a": 42', 'b: 17', '', 'c: 19']
assert first_key(lines) == 'a": 42'
# no lines
lines = []
assert first_key(lines) is None
@pytest.mark.parametrize('bad_lines,good_lines,_', TEST_SORTS)
def test_sort(bad_lines, good_lines, _):
assert sort(bad_lines) == good_lines

View file

@ -22,16 +22,20 @@ TESTS = (
# Docstring
('""" Foo """', '""" Foo """', 0),
(
textwrap.dedent("""
textwrap.dedent(
"""
x = " \\
foo \\
"\n
"""),
textwrap.dedent("""
""",
),
textwrap.dedent(
"""
x = ' \\
foo \\
'\n
"""),
""",
),
1,
),
('"foo""bar"', "'foo''bar'", 1),

View file

@ -69,7 +69,7 @@ def test_markdown_linebreak_ext_opt(filename, input_s, output, tmpdir):
path = tmpdir.join(filename)
path.write(input_s)
ret = fix_trailing_whitespace((
'--markdown-linebreak-ext=TxT', path.strpath
'--markdown-linebreak-ext=TxT', path.strpath,
))
assert ret == 1
assert path.read() == output

View file

@ -1,7 +1,7 @@
[tox]
project = pre_commit_hooks
# These should match the travis env list
envlist = py27,py34,py35,pypy
envlist = py27,py35,py36,pypy
[testenv]
deps = -rrequirements-dev.txt
@ -14,7 +14,7 @@ setenv =
commands =
coverage erase
coverage run -m pytest {posargs:tests}
coverage report --show-missing --fail-under 100
coverage report --fail-under 100
pre-commit install -f --install-hooks
pre-commit run --all-files