Better project structure

This commit is contained in:
Anthony Sottile 2014-04-12 07:28:25 -07:00
parent f31f092f9b
commit 1746a97e24
52 changed files with 221 additions and 189 deletions

View file

@ -1,19 +1,29 @@
[run]
branch = True
timid = True
source =
.
omit =
.tox/*
/usr/*
*/tmp*
setup.py
[report] [report]
exclude_lines = exclude_lines =
# Don't complain about defensive assertions # Have to re-enable the standard pragma
raise NotImplementedError \#\s*pragma: no cover
raise AssertionError
# Don't complain about non-runnable code # Don't complain if tests don't hit defensive assertion code:
if __name__ == .__main__.: ^\s*raise AssertionError\b
^\s*raise NotImplementedError\b
^\s*return NotImplemented\b
^\s*raise$
omit = # Don't complain if non-runnable code isn't run:
/usr/* ^if __name__ == ['"]__main__['"]:$
py_env/*
*/__init__.py
# Ignore test coverage [html]
tests/* directory = coverage-html
# Don't complain about our pre-commit file # vim:ft=dosini
pre-commit.py

21
.gitignore vendored
View file

@ -1,12 +1,13 @@
*.pyc
.pydevproject
.pre-commit-files
.project
.coverage
/py_env
*.db
.idea
build
dist
*.egg-info *.egg-info
*.iml *.iml
*.py[co]
.*.sw[a-z]
.coverage
.idea
.pre-commit-files
.project
.pydevproject
.tox
/venv*
coverage-html
dist

View file

@ -1,13 +1,12 @@
language: python language: python
env: # These should match the tox env list
python: - TOXENV=py26
- 2.6 - TOXENV=py27
- 2.7 install: pip install tox --use-mirrors
script: tox
install: pip install virtualenv
script: make coverage
# Special snowflake. Our tests depend on making real commits.
before_install: before_install:
- git config --global user.name "Travis CI" - git config --global user.name "Travis CI"
- git config --global user.email "user@example.com" - git config --global user.email "user@example.com"

View file

@ -1,41 +1,17 @@
.PHONY: all
all: venv test
TEST_TARGETS = .PHONY: venv
ITEST_TARGETS = -m integration venv:
UTEST_TARGETS = -m "not(integration)" tox -e venv
DEBUG= .PHONY: tests test
all: _tests
integration:
$(eval TEST_TARGETS := $(ITEST_TARGETS))
unit:
$(eval TEST_TARGETS := $(UTEST_TARGETS))
utests: test
utest: test
tests: test tests: test
test: unit _tests test:
itests: itest tox
itest: integration _tests
_tests: py_env
bash -c 'source py_env/bin/activate && py.test tests $(TEST_TARGETS) $(DEBUG)'
ucoverage: unit coverage
icoverage: integration coverage
coverage: py_env
bash -c 'source py_env/bin/activate && \
coverage erase && \
coverage run `which py.test` tests $(TEST_TARGETS) && \
coverage report -m'
py_env: requirements.txt setup.py
rm -rf py_env
virtualenv py_env
bash -c 'source py_env/bin/activate && pip install -r requirements.txt'
.PHONY: clean
clean: clean:
rm -rf py_env find . -iname '*.pyc' | xargs rm -f
rm -rf .tox
rm -rf ./venv-*

24
UNLICENSE Normal file
View file

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

View file

@ -1,4 +1,3 @@
# Hooks are set up as follows # Hooks are set up as follows
# - id: hook_id # - id: hook_id
# name: 'Readable name' # name: 'Readable name'

View file

@ -1,4 +1,3 @@
- repo: git@github.com:pre-commit/pre-commit-hooks - repo: git@github.com:pre-commit/pre-commit-hooks
sha: cd74dc150c142c3be70b24eaf0b02cae9d235f37 sha: cd74dc150c142c3be70b24eaf0b02cae9d235f37
hooks: hooks:

View file

@ -1,4 +1,3 @@
from __future__ import print_function from __future__ import print_function
import argparse import argparse

View file

@ -1,4 +1,3 @@
import re import re
import sys import sys
@ -6,7 +5,8 @@ from pre_commit.clientlib.validate_base import get_run_function
from pre_commit.clientlib.validate_base import get_validator from pre_commit.clientlib.validate_base import get_validator
class InvalidConfigError(ValueError): pass class InvalidConfigError(ValueError):
pass
CONFIG_JSON_SCHEMA = { CONFIG_JSON_SCHEMA = {

View file

@ -1,4 +1,3 @@
import sys import sys
from pre_commit.clientlib.validate_base import get_run_function from pre_commit.clientlib.validate_base import get_run_function
@ -6,7 +5,8 @@ from pre_commit.clientlib.validate_base import get_validator
from pre_commit.languages.all import all_languages from pre_commit.languages.all import all_languages
class InvalidManifestError(ValueError): pass class InvalidManifestError(ValueError):
pass
MANIFEST_JSON_SCHEMA = { MANIFEST_JSON_SCHEMA = {

View file

@ -1,4 +1,3 @@
import sys import sys
RED = '\033[41m' RED = '\033[41m'
@ -8,18 +7,19 @@ TURQUOISE = '\033[46;30m'
NORMAL = '\033[0m' NORMAL = '\033[0m'
class InvalidColorSetting(ValueError): pass class InvalidColorSetting(ValueError):
pass
def format_color(text, color, use_color): def format_color(text, color, use_color_setting):
"""Format text with color. """Format text with color.
Args: Args:
text - Text to be formatted with color if `use_color` text - Text to be formatted with color if `use_color`
color - The color start string color - The color start string
use_color - Whether or not to color use_color_setting - Whether or not to color
""" """
if not use_color: if not use_color_setting:
return text return text
else: else:
return u'{0}{1}{2}'.format(color, text, NORMAL) return u'{0}{1}{2}'.format(color, text, NORMAL)

View file

@ -1,4 +1,3 @@
from __future__ import print_function from __future__ import print_function
import os import os
@ -42,7 +41,8 @@ def uninstall(runner):
return 0 return 0
class RepositoryCannotBeUpdatedError(RuntimeError): pass class RepositoryCannotBeUpdatedError(RuntimeError):
pass
def _update_repository(repo_config): def _update_repository(repo_config):
@ -95,8 +95,8 @@ def autoupdate(runner):
print('Updating {0}...'.format(repo_config['repo']), end='') print('Updating {0}...'.format(repo_config['repo']), end='')
try: try:
new_repo_config = _update_repository(repo_config) new_repo_config = _update_repository(repo_config)
except RepositoryCannotBeUpdatedError as e: except RepositoryCannotBeUpdatedError as error:
print(e.args[0]) print(error.args[0])
output_configs.append(repo_config) output_configs.append(repo_config)
retv = 1 retv = 1
continue continue

View file

@ -1,4 +1,3 @@
CONFIG_FILE = '.pre-commit-config.yaml' CONFIG_FILE = '.pre-commit-config.yaml'
HOOKS_WORKSPACE = '.pre-commit-files' HOOKS_WORKSPACE = '.pre-commit-files'

View file

@ -43,14 +43,15 @@ def get_files_matching(all_file_list_strategy):
def wrapper(include_expr, exclude_expr): def wrapper(include_expr, exclude_expr):
include_regex = re.compile(include_expr) include_regex = re.compile(include_expr)
exclude_regex = re.compile(exclude_expr) exclude_regex = re.compile(exclude_expr)
return set(filter(os.path.exists, ( return set(
filename filename
for filename in all_file_list_strategy() for filename in all_file_list_strategy()
if ( if (
include_regex.search(filename) and include_regex.search(filename) and
not exclude_regex.search(filename) not exclude_regex.search(filename) and
os.path.exists(filename)
)
) )
)))
return wrapper return wrapper

View file

@ -1,4 +1,3 @@
import contextlib import contextlib
import os.path import os.path
from plumbum import local from plumbum import local

View file

@ -1,4 +1,3 @@
import copy import copy
import jsonschema import jsonschema
import jsonschema.validators import jsonschema.validators
@ -21,7 +20,6 @@ def extend_validator_cls(validator_cls, modify):
) )
def default_values(properties, instance): def default_values(properties, instance):
for property, subschema in properties.iteritems(): for property, subschema in properties.iteritems():
if 'default' in subschema: if 'default' in subschema:

View file

@ -1,4 +1,3 @@
from pre_commit.languages import node from pre_commit.languages import node
from pre_commit.languages import python from pre_commit.languages import python
from pre_commit.languages import ruby from pre_commit.languages import ruby

View file

@ -1,4 +1,3 @@
import contextlib import contextlib
from pre_commit.languages import helpers from pre_commit.languages import helpers

View file

@ -1,4 +1,3 @@
import contextlib import contextlib
from pre_commit.languages import helpers from pre_commit.languages import helpers
@ -11,7 +10,7 @@ ENVIRONMENT_DIR = 'rvm_env'
class RubyEnv(helpers.Environment): class RubyEnv(helpers.Environment):
@property @property
def env_prefix(self): def env_prefix(self):
return '. {{prefix}}{0}/bin/activate &&'.format(ENVIRONMENT_DIR) raise NotImplementedError
@contextlib.contextmanager @contextlib.contextmanager

View file

@ -1,4 +1,3 @@
ENVIRONMENT_DIR = None ENVIRONMENT_DIR = None

View file

@ -1,4 +1,3 @@
ENVIRONMENT_DIR = None ENVIRONMENT_DIR = None

View file

@ -1,4 +1,3 @@
from __future__ import print_function from __future__ import print_function
import logging import logging

View file

@ -1,4 +1,3 @@
import os import os
import os.path import os.path
import subprocess import subprocess

View file

@ -1,4 +1,3 @@
import contextlib import contextlib
import logging import logging
from plumbum import local from plumbum import local

View file

@ -1,4 +1,3 @@
from __future__ import print_function from __future__ import print_function
import argparse import argparse
@ -56,7 +55,6 @@ def _run_single_hook(runner, repository, hook_id, args):
print_color = color.GREEN print_color = color.GREEN
pass_fail = 'Passed' pass_fail = 'Passed'
print(color.format_color(pass_fail, print_color, args.color)) print(color.format_color(pass_fail, print_color, args.color))
if output and (retcode or args.verbose): if output and (retcode or args.verbose):
@ -111,14 +109,14 @@ def run(argv):
subparsers.add_parser('autoupdate', help='Auto-update hooks config.') subparsers.add_parser('autoupdate', help='Auto-update hooks config.')
run = subparsers.add_parser('run', help='Run hooks.') run_parser = subparsers.add_parser('run', help='Run hooks.')
run.add_argument('hook', nargs='?', help='A single hook-id to run'), run_parser.add_argument('hook', nargs='?', help='A single hook-id to run')
run.add_argument( run_parser.add_argument(
'--all-files', '-a', action='store_true', default=False, '--all-files', '-a', action='store_true', default=False,
help='Run on all the files in the repo.', help='Run on all the files in the repo.',
) )
run.add_argument('--verbose', '-v', action='store_true', default=False) run_parser.add_argument('--verbose', '-v', action='store_true', default=False)
run.add_argument( run_parser.add_argument(
'--color', default='auto', type=color.use_color, '--color', default='auto', type=color.use_color,
help='Whether to use color in output. Defaults to `auto`', help='Whether to use color in output. Defaults to `auto`',
) )

View file

@ -1,4 +1,3 @@
import os import os
import os.path import os.path
@ -40,7 +39,7 @@ class Runner(object):
def repositories(self): def repositories(self):
"""Returns a tuple of the configured repositories.""" """Returns a tuple of the configured repositories."""
config = load_config(self.config_file_path) config = load_config(self.config_file_path)
return tuple(map(Repository, config)) return tuple(Repository(x) for x in config)
@cached_property @cached_property
def pre_commit_path(self): def pre_commit_path(self):

View file

@ -1,4 +1,3 @@
import contextlib import contextlib
import logging import logging
import time import time

View file

@ -1,4 +1,3 @@
import contextlib import contextlib
import functools import functools
import os import os

View file

@ -1,4 +1,3 @@
import yaml import yaml
from pre_commit.ordereddict import OrderedDict from pre_commit.ordereddict import OrderedDict
@ -6,23 +5,27 @@ from pre_commit.ordereddict import OrderedDict
# Adapted from http://stackoverflow.com/a/21912744/812183 # Adapted from http://stackoverflow.com/a/21912744/812183
def ordered_load(s): def ordered_load(stream):
class OrderedLoader(yaml.loader.Loader): pass class OrderedLoader(yaml.loader.Loader):
pass
def constructor(loader, node): def constructor(loader, node):
return OrderedDict(loader.construct_pairs(node)) return OrderedDict(loader.construct_pairs(node))
OrderedLoader.add_constructor( OrderedLoader.add_constructor(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
constructor, constructor,
) )
return yaml.load(s, Loader=OrderedLoader) return yaml.load(stream, Loader=OrderedLoader)
def ordered_dump(s, **kwargs): def ordered_dump(obj, **kwargs):
class OrderedDumper(yaml.dumper.SafeDumper): pass class OrderedDumper(yaml.dumper.SafeDumper):
pass
def dict_representer(dumper, data): def dict_representer(dumper, data):
return dumper.represent_mapping( return dumper.represent_mapping(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
data.items(), data.items(),
) )
OrderedDumper.add_representer(OrderedDict, dict_representer) OrderedDumper.add_representer(OrderedDict, dict_representer)
return yaml.dump(s, Dumper=OrderedDumper, **kwargs) return yaml.dump(obj, Dumper=OrderedDumper, **kwargs)

19
pylintrc Normal file
View file

@ -0,0 +1,19 @@
[MESSAGES CONTROL]
disable=missing-docstring,abstract-method,redefined-builtin,useless-else-on-loop,redefined-outer-name,invalid-name
[REPORTS]
output-format=colorized
reports=no
[BASIC]
const-rgx=(([A-Za-z_][A-Za-z0-9_]*)|(__.*__))$
[FORMAT]
max-line-length=131
[TYPECHECK]
ignored-classes=pytest
[DESIGN]
min-public-methods=0

View file

@ -1,10 +1 @@
-e . .
# Testing requirements
coverage
# Fuck you ipython
ipython<2.0.0
ipdb
mock
pyflakes
pytest

7
requirements_dev.txt Normal file
View file

@ -0,0 +1,7 @@
-e .
coverage
flake8
mock
pylint
pytest

View file

@ -18,7 +18,20 @@ if sys.version_info < (2, 7):
setup( setup(
name='pre_commit', name='pre_commit',
description='A framework for managing and maintaining multi-language pre-commit hooks.',
url='http://github.com/pre-commit/pre-commit',
version='0.0.0', version='0.0.0',
author='Anthony Sottile',
author_email='asottile@umich.edu',
platforms='linux',
classifiers=[
'License :: Public Domain',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
],
packages=find_packages('.', exclude=('tests*', 'testing*')), packages=find_packages('.', exclude=('tests*', 'testing*')),
package_data={ package_data={
'pre_commit': [ 'pre_commit': [

View file

@ -1,4 +1,3 @@
import collections import collections
def auto_namedtuple(classname='auto_namedtuple', **kwargs): def auto_namedtuple(classname='auto_namedtuple', **kwargs):

View file

@ -1,4 +1,3 @@
- repo: git@github.com:pre-commit/pre-commit-hooks - repo: git@github.com:pre-commit/pre-commit-hooks
hooks: hooks:
- id: pyflakes - id: pyflakes

View file

@ -1,4 +1,4 @@
import jsonschema
import os import os
import os.path import os.path
import shutil import shutil
@ -27,3 +27,10 @@ def copy_tree_to_path(src_dir, dest_dir):
shutil.copytree(srcname, destname) shutil.copytree(srcname, destname)
else: else:
shutil.copy(srcname, destname) shutil.copy(srcname, destname)
def is_valid_according_to_schema(obj, schema):
try:
jsonschema.validate(obj, schema)
return True
except jsonschema.exceptions.ValidationError:
return False

View file

@ -1,4 +1,3 @@
import pytest import pytest
from pre_commit.clientlib.validate_base import get_validator from pre_commit.clientlib.validate_base import get_validator
@ -7,7 +6,8 @@ from pre_commit.yaml_extensions import ordered_load
from testing.util import get_resource_path from testing.util import get_resource_path
class AdditionalValidatorError(ValueError): pass class AdditionalValidatorError(ValueError):
pass
@pytest.fixture @pytest.fixture
@ -22,7 +22,7 @@ def array_validator():
@pytest.fixture @pytest.fixture
def additional_validator(): def additional_validator():
def raises_always(obj): def raises_always(_):
raise AdditionalValidatorError raise AdditionalValidatorError
return get_validator( return get_validator(

View file

@ -1,6 +1,3 @@
import jsonschema
import jsonschema.exceptions
import pytest import pytest
from pre_commit.clientlib.validate_config import CONFIG_JSON_SCHEMA from pre_commit.clientlib.validate_config import CONFIG_JSON_SCHEMA
@ -8,6 +5,7 @@ from pre_commit.clientlib.validate_config import InvalidConfigError
from pre_commit.clientlib.validate_config import run from pre_commit.clientlib.validate_config import run
from pre_commit.clientlib.validate_config import validate_config_extra from pre_commit.clientlib.validate_config import validate_config_extra
from pre_commit.jsonschema_extensions import apply_defaults from pre_commit.jsonschema_extensions import apply_defaults
from testing.util import is_valid_according_to_schema
def test_returns_0_for_valid_config(): def test_returns_0_for_valid_config():
@ -22,21 +20,13 @@ def test_returns_1_for_failing():
assert run(['tests/data/valid_yaml_but_invalid_config.yaml']) == 1 assert run(['tests/data/valid_yaml_but_invalid_config.yaml']) == 1
def is_valid_according_to_schema(obj, schema):
try:
jsonschema.validate(obj, schema)
return True
except jsonschema.exceptions.ValidationError:
return False
@pytest.mark.parametrize(('manifest_obj', 'expected'), ( @pytest.mark.parametrize(('manifest_obj', 'expected'), (
([], False), ([], False),
( (
[{ [{
'repo': 'git@github.com:pre-commit/pre-commit-hooks', 'repo': 'git@github.com:pre-commit/pre-commit-hooks',
'sha': 'cd74dc150c142c3be70b24eaf0b02cae9d235f37', 'sha': 'cd74dc150c142c3be70b24eaf0b02cae9d235f37',
'hooks': [{'id': 'pyflakes', 'files': '\.py$'}], 'hooks': [{'id': 'pyflakes', 'files': '\\.py$'}],
}], }],
True, True,
), ),
@ -47,7 +37,7 @@ def is_valid_according_to_schema(obj, schema):
'hooks': [ 'hooks': [
{ {
'id': 'pyflakes', 'id': 'pyflakes',
'files': '\.py$', 'files': '\\.py$',
'args': ['foo', 'bar', 'baz'], 'args': ['foo', 'bar', 'baz'],
}, },
], ],
@ -61,7 +51,7 @@ def is_valid_according_to_schema(obj, schema):
'hooks': [ 'hooks': [
{ {
'id': 'pyflakes', 'id': 'pyflakes',
'files': '\.py$', 'files': '\\.py$',
# Exclude pattern must be a string # Exclude pattern must be a string
'exclude': 0, 'exclude': 0,
'args': ['foo', 'bar', 'baz'], 'args': ['foo', 'bar', 'baz'],
@ -95,7 +85,7 @@ def test_config_with_ok_regexes_passes():
[{ [{
'repo': 'foo', 'repo': 'foo',
'sha': 'foo', 'sha': 'foo',
'hooks': [{'id': 'hook_id', 'files': '\.py$'}], 'hooks': [{'id': 'hook_id', 'files': '\\.py$'}],
}], }],
CONFIG_JSON_SCHEMA, CONFIG_JSON_SCHEMA,
) )

View file

@ -1,12 +1,10 @@
import jsonschema
import jsonschema.exceptions
import pytest import pytest
from pre_commit.clientlib.validate_manifest import additional_manifest_check from pre_commit.clientlib.validate_manifest import additional_manifest_check
from pre_commit.clientlib.validate_manifest import InvalidManifestError from pre_commit.clientlib.validate_manifest import InvalidManifestError
from pre_commit.clientlib.validate_manifest import MANIFEST_JSON_SCHEMA from pre_commit.clientlib.validate_manifest import MANIFEST_JSON_SCHEMA
from pre_commit.clientlib.validate_manifest import run from pre_commit.clientlib.validate_manifest import run
from testing.util import is_valid_according_to_schema
def test_returns_0_for_valid_manifest(): def test_returns_0_for_valid_manifest():
@ -34,14 +32,6 @@ def test_additional_manifest_check_languages(obj):
additional_manifest_check(obj) additional_manifest_check(obj)
def is_valid_according_to_schema(obj, schema):
try:
jsonschema.validate(obj, schema)
return True
except jsonschema.exceptions.ValidationError:
return False
@pytest.mark.parametrize(('manifest_obj', 'expected'), ( @pytest.mark.parametrize(('manifest_obj', 'expected'), (
([], False), ([], False),
([{'id': 'a', 'name': 'b', 'entry': 'c', 'language': 'python'}], True), ([{'id': 'a', 'name': 'b', 'entry': 'c', 'language': 'python'}], True),

View file

@ -1,4 +1,3 @@
import mock import mock
import pytest import pytest
import sys import sys

View file

@ -1,4 +1,3 @@
import os import os
import os.path import os.path
import pkg_resources import pkg_resources

View file

@ -81,12 +81,12 @@ def _make_config(path, hook_id, file_regex):
@pytest.yield_fixture @pytest.yield_fixture
def config_for_node_hooks_repo(node_hooks_repo): def config_for_node_hooks_repo(node_hooks_repo):
yield _make_config(node_hooks_repo, 'foo', '\.js$') yield _make_config(node_hooks_repo, 'foo', '\\.js$')
@pytest.yield_fixture @pytest.yield_fixture
def config_for_python_hooks_repo(python_hooks_repo): def config_for_python_hooks_repo(python_hooks_repo):
yield _make_config(python_hooks_repo, 'foo', '\.py$') yield _make_config(python_hooks_repo, 'foo', '\\.py$')
@pytest.yield_fixture @pytest.yield_fixture

View file

@ -1,4 +1,3 @@
import pytest import pytest
from plumbum import local from plumbum import local
@ -38,7 +37,7 @@ def test_get_files_matching_base(get_files_matching_func):
def test_get_files_matching_total_match(get_files_matching_func): def test_get_files_matching_total_match(get_files_matching_func):
ret = get_files_matching_func('^.*\.py$', '^$') ret = get_files_matching_func('^.*\\.py$', '^$')
assert ret == set([ assert ret == set([
'pre_commit/run.py', 'pre_commit/run.py',
'pre_commit/git.py', 'pre_commit/git.py',
@ -46,7 +45,7 @@ def test_get_files_matching_total_match(get_files_matching_func):
def test_does_search_instead_of_match(get_files_matching_func): def test_does_search_instead_of_match(get_files_matching_func):
ret = get_files_matching_func('\.yaml$', '^$') ret = get_files_matching_func('\\.yaml$', '^$')
assert ret == set(['hooks.yaml']) assert ret == set(['hooks.yaml'])
@ -56,5 +55,5 @@ def test_does_not_include_deleted_fileS(get_files_matching_func):
def test_exclude_removes_files(get_files_matching_func): def test_exclude_removes_files(get_files_matching_func):
ret = get_files_matching_func('', '\.py$') ret = get_files_matching_func('', '\\.py$')
assert ret == set(['hooks.yaml']) assert ret == set(['hooks.yaml'])

View file

@ -1,4 +1,3 @@
from pre_commit.jsonschema_extensions import apply_defaults from pre_commit.jsonschema_extensions import apply_defaults
from pre_commit.jsonschema_extensions import remove_defaults from pre_commit.jsonschema_extensions import remove_defaults

View file

@ -1,4 +1,3 @@
import pytest import pytest
from pre_commit.languages.all import all_languages from pre_commit.languages.all import all_languages

View file

@ -1,4 +1,3 @@
import os import os
import mock import mock
import pytest import pytest
@ -94,7 +93,8 @@ def test_path_multiple_args():
assert ret == 'foo/bar/baz' assert ret == 'foo/bar/baz'
@pytest.mark.parametrize(('prefix', 'path_end', 'expected_output'), @pytest.mark.parametrize(
('prefix', 'path_end', 'expected_output'),
tuple( tuple(
(prefix, path_end, expected_output + os.sep) (prefix, path_end, expected_output + os.sep)
for prefix, path_end, expected_output in PATH_TESTS for prefix, path_end, expected_output in PATH_TESTS

View file

@ -31,6 +31,7 @@ def test_create_repo_in_env(dummy_repo_config, dummy_git_repo):
os.path.join(dummy_git_repo, C.HOOKS_WORKSPACE, repo.sha), os.path.join(dummy_git_repo, C.HOOKS_WORKSPACE, repo.sha),
) )
@pytest.mark.integration @pytest.mark.integration
def test_install_python_repo_in_env(config_for_python_hooks_repo): def test_install_python_repo_in_env(config_for_python_hooks_repo):
repo = Repository(config_for_python_hooks_repo) repo = Repository(config_for_python_hooks_repo)
@ -110,7 +111,7 @@ def mock_repo_config():
'sha': '5e713f8878b7d100c0e059f8cc34be4fc2e8f897', 'sha': '5e713f8878b7d100c0e059f8cc34be4fc2e8f897',
'hooks': [{ 'hooks': [{
'id': 'pyflakes', 'id': 'pyflakes',
'files': '\.py$', 'files': '\\.py$',
}], }],
} }
config_wrapped = apply_defaults([config], CONFIG_JSON_SCHEMA) config_wrapped = apply_defaults([config], CONFIG_JSON_SCHEMA)

View file

@ -1,4 +1,3 @@
import os import os
import os.path import os.path
import pytest import pytest

View file

@ -1,4 +1,3 @@
import os.path import os.path
import pytest import pytest
import shutil import shutil

View file

@ -1,4 +1,3 @@
import mock import mock
import pytest import pytest
import os import os
@ -17,7 +16,7 @@ from pre_commit.util import memoize_by_cwd
def class_with_cached_property(): def class_with_cached_property():
class Foo(object): class Foo(object):
@cached_property @cached_property
def foo(self): def my_property(self):
return "Foo" + str(random.getrandbits(64)) return "Foo" + str(random.getrandbits(64))
return Foo return Foo
@ -25,14 +24,14 @@ def class_with_cached_property():
def test_cached_property(class_with_cached_property): def test_cached_property(class_with_cached_property):
instance = class_with_cached_property() instance = class_with_cached_property()
val = instance.foo val = instance.my_property
val2 = instance.foo val2 = instance.my_property
assert val is val2 assert val is val2
def test_unbound_cached_property(class_with_cached_property): def test_unbound_cached_property(class_with_cached_property):
# Make sure we don't blow up when accessing the property unbound # Make sure we don't blow up when accessing the property unbound
prop = class_with_cached_property.foo prop = class_with_cached_property.my_property
assert isinstance(prop, cached_property) assert isinstance(prop, cached_property)
@ -90,7 +89,8 @@ def test_no_arguments_passed_uses_argv(entry_func):
def test_clean_on_failure_noop(in_tmpdir): def test_clean_on_failure_noop(in_tmpdir):
with clean_path_on_failure('foo'): pass with clean_path_on_failure('foo'):
pass
def test_clean_path_on_failure_does_nothing_when_not_raising(in_tmpdir): def test_clean_path_on_failure_does_nothing_when_not_raising(in_tmpdir):
@ -100,7 +100,8 @@ def test_clean_path_on_failure_does_nothing_when_not_raising(in_tmpdir):
def test_clean_path_on_failure_cleans_for_normal_exception(in_tmpdir): def test_clean_path_on_failure_cleans_for_normal_exception(in_tmpdir):
class MyException(Exception): pass class MyException(Exception):
pass
with pytest.raises(MyException): with pytest.raises(MyException):
with clean_path_on_failure('foo'): with clean_path_on_failure('foo'):
@ -111,7 +112,8 @@ def test_clean_path_on_failure_cleans_for_normal_exception(in_tmpdir):
def test_clean_path_on_failure_cleans_for_system_exit(in_tmpdir): def test_clean_path_on_failure_cleans_for_system_exit(in_tmpdir):
class MySystemExit(SystemExit): pass class MySystemExit(SystemExit):
pass
with pytest.raises(MySystemExit): with pytest.raises(MySystemExit):
with clean_path_on_failure('foo'): with clean_path_on_failure('foo'):

View file

@ -1,4 +1,3 @@
import pre_commit.constants as C import pre_commit.constants as C
from pre_commit.ordereddict import OrderedDict from pre_commit.ordereddict import OrderedDict
from pre_commit.yaml_extensions import ordered_dump from pre_commit.yaml_extensions import ordered_dump

28
tox.ini Normal file
View file

@ -0,0 +1,28 @@
[tox]
project = pre_commit
# These should match the travis env list
envlist = py26,py27
[testenv]
install_command = pip install --use-wheel {opts} {packages}
deps = -rrequirements_dev.txt
commands =
coverage erase
coverage run -m pytest {posargs:tests}
coverage report --show-missing --fail-under 90
flake8 {[tox]project} tests setup.py
# pylint {[tox]project} tests setup.py
[testenv:venv]
envdir = venv-{[tox]project}
commands =
[testenv:docs]
deps =
{[testenv]deps}
sphinx
changedir = docs
commands = sphinx-build -b html -d build/doctrees source build/html
[flake8]
max-line-length=131