diff --git a/pre_commit_hooks/check_case_conflict.py b/pre_commit_hooks/check_case_conflict.py index 6a837d9..dd4ad86 100644 --- a/pre_commit_hooks/check_case_conflict.py +++ b/pre_commit_hooks/check_case_conflict.py @@ -4,9 +4,8 @@ from __future__ import unicode_literals import argparse -from plumbum import local - from pre_commit_hooks.util import added_files +from pre_commit_hooks.util import cmd_output def lower_set(iterable): @@ -14,7 +13,7 @@ def lower_set(iterable): def find_conflicting_filenames(filenames): - repo_files = set(local['git']('ls-files').splitlines()) + repo_files = set(cmd_output('git', 'ls-files').splitlines()) relevant_files = set(filenames) | added_files() repo_files -= relevant_files retv = 0 diff --git a/pre_commit_hooks/trailing_whitespace_fixer.py b/pre_commit_hooks/trailing_whitespace_fixer.py index 7ac3d73..0642ac0 100644 --- a/pre_commit_hooks/trailing_whitespace_fixer.py +++ b/pre_commit_hooks/trailing_whitespace_fixer.py @@ -4,7 +4,7 @@ import argparse import fileinput import sys -from plumbum import local +from pre_commit_hooks.util import cmd_output def _fix_file(filename): @@ -17,9 +17,9 @@ def fix_trailing_whitespace(argv=None): parser.add_argument('filenames', nargs='*', help='Filenames to fix') args = parser.parse_args(argv) - bad_whitespace_files = local['grep'][ - ('-l', '[[:space:]]$') + tuple(args.filenames) - ](retcode=None).strip().splitlines() + bad_whitespace_files = cmd_output( + 'grep', '-l', '[[:space:]]$', *args.filenames, retcode=None + ).strip().splitlines() if bad_whitespace_files: for bad_whitespace_file in bad_whitespace_files: diff --git a/pre_commit_hooks/util.py b/pre_commit_hooks/util.py index eedf7b6..7c2175e 100644 --- a/pre_commit_hooks/util.py +++ b/pre_commit_hooks/util.py @@ -2,10 +2,26 @@ from __future__ import absolute_import from __future__ import print_function from __future__ import unicode_literals -from plumbum import local +import subprocess + + +class CalledProcessError(RuntimeError): + pass def added_files(): - return set(local['git']( - 'diff', '--staged', '--name-only', '--diff-filter', 'A', + return set(cmd_output( + 'git', 'diff', '--staged', '--name-only', '--diff-filter', 'A', ).splitlines()) + + +def cmd_output(*cmd, **kwargs): + retcode = kwargs.pop('retcode', 0) + popen_kwargs = {'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE} + popen_kwargs.update(kwargs) + proc = subprocess.Popen(cmd, **popen_kwargs) + stdout, stderr = proc.communicate() + stdout, stderr = stdout.decode('UTF-8'), stderr.decode('UTF-8') + if retcode is not None and proc.returncode != retcode: + raise CalledProcessError(cmd, retcode, proc.returncode, stdout, stderr) + return stdout diff --git a/pylintrc b/pylintrc index ce9ebdb..7b2247d 100644 --- a/pylintrc +++ b/pylintrc @@ -1,5 +1,5 @@ [MESSAGES CONTROL] -disable=bad-open-mode,invalid-name,missing-docstring,redefined-outer-name +disable=bad-open-mode,invalid-name,missing-docstring,redefined-outer-name,star-args [REPORTS] output-format=colorized diff --git a/setup.py b/setup.py index 0455b53..0b3ed31 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,6 @@ setup( 'flake8', 'argparse', 'autopep8>=1.1', - 'plumbum', 'pyflakes', 'pyyaml', 'simplejson', diff --git a/testing/util.py b/testing/util.py index 0bc8142..3b90631 100644 --- a/testing/util.py +++ b/testing/util.py @@ -1,3 +1,7 @@ +from __future__ import absolute_import +from __future__ import unicode_literals + +import contextlib import io import os.path @@ -5,6 +9,16 @@ import os.path TESTING_DIR = os.path.abspath(os.path.dirname(__file__)) +@contextlib.contextmanager +def cwd(path): + pwd = os.getcwd() + os.chdir(path) + try: + yield + finally: + os.chdir(pwd) + + def get_resource_path(path): return os.path.join(TESTING_DIR, 'resources', path) diff --git a/tests/autopep8_wrapper_test.py b/tests/autopep8_wrapper_test.py index 9a395c9..a218e4b 100644 --- a/tests/autopep8_wrapper_test.py +++ b/tests/autopep8_wrapper_test.py @@ -2,7 +2,6 @@ from __future__ import absolute_import from __future__ import unicode_literals import io -import os import pytest @@ -25,16 +24,6 @@ def test_main_failing(tmpdir, input_src, expected_ret, output_src): assert io.open(filename).read() == output_src -@pytest.yield_fixture -def in_tmpdir(tmpdir): - pwd = os.getcwd() - os.chdir(tmpdir.strpath) - try: - yield - finally: - os.chdir(pwd) - - @pytest.mark.usefixtures('in_tmpdir') def test_respects_config_file(): with io.open('setup.cfg', 'w') as setup_cfg: diff --git a/tests/check_added_large_files_test.py b/tests/check_added_large_files_test.py index b72a315..b49f118 100644 --- a/tests/check_added_large_files_test.py +++ b/tests/check_added_large_files_test.py @@ -1,35 +1,35 @@ from __future__ import absolute_import from __future__ import unicode_literals -from plumbum import local - from pre_commit_hooks.check_added_large_files import find_large_added_files from pre_commit_hooks.check_added_large_files import main +from pre_commit_hooks.util import cmd_output +from testing.util import cwd from testing.util import write_file def test_nothing_added(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): assert find_large_added_files(['f.py'], 0) == 0 def test_adding_something(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): write_file('f.py', "print('hello world')") - local['git']('add', 'f.py') + cmd_output('git', 'add', 'f.py') # Should fail with max size of 0 assert find_large_added_files(['f.py'], 0) == 1 def test_add_something_giant(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): write_file('f.py', 'a' * 10000) # Should not fail when not added assert find_large_added_files(['f.py'], 0) == 0 - local['git']('add', 'f.py') + cmd_output('git', 'add', 'f.py') # Should fail with strict bound assert find_large_added_files(['f.py'], 0) == 1 @@ -42,20 +42,20 @@ def test_add_something_giant(temp_git_dir): def test_added_file_not_in_pre_commits_list(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): write_file('f.py', "print('hello world')") - local['git']('add', 'f.py') + cmd_output('git', 'add', 'f.py') # Should pass even with a size of 0 assert find_large_added_files(['g.py'], 0) == 0 def test_integration(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): assert main(argv=[]) == 0 write_file('f.py', 'a' * 10000) - local['git']('add', 'f.py') + cmd_output('git', 'add', 'f.py') # Should not fail with default assert main(argv=['f.py']) == 0 diff --git a/tests/check_case_conflict_test.py b/tests/check_case_conflict_test.py index 344725d..2a32918 100644 --- a/tests/check_case_conflict_test.py +++ b/tests/check_case_conflict_test.py @@ -1,66 +1,66 @@ from __future__ import absolute_import from __future__ import unicode_literals -from plumbum import local - from pre_commit_hooks.check_case_conflict import find_conflicting_filenames from pre_commit_hooks.check_case_conflict import main +from pre_commit_hooks.util import cmd_output +from testing.util import cwd from testing.util import write_file def test_nothing_added(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): assert find_conflicting_filenames(['f.py']) == 0 def test_adding_something(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): write_file('f.py', "print('hello world')") - local['git']('add', 'f.py') + cmd_output('git', 'add', 'f.py') assert find_conflicting_filenames(['f.py']) == 0 def test_adding_something_with_conflict(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): write_file('f.py', "print('hello world')") - local['git']('add', 'f.py') + cmd_output('git', 'add', 'f.py') write_file('F.py', "print('hello world')") - local['git']('add', 'F.py') + cmd_output('git', 'add', 'F.py') assert find_conflicting_filenames(['f.py', 'F.py']) == 1 def test_added_file_not_in_pre_commits_list(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): write_file('f.py', "print('hello world')") - local['git']('add', 'f.py') + cmd_output('git', 'add', 'f.py') assert find_conflicting_filenames(['g.py']) == 0 def test_file_conflicts_with_committed_file(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): write_file('f.py', "print('hello world')") - local['git']('add', 'f.py') - local['git']('commit', '--no-verify', '-m', 'Add f.py') + cmd_output('git', 'add', 'f.py') + cmd_output('git', 'commit', '--no-verify', '-m', 'Add f.py') write_file('F.py', "print('hello world')") - local['git']('add', 'F.py') + cmd_output('git', 'add', 'F.py') assert find_conflicting_filenames(['F.py']) == 1 def test_integration(temp_git_dir): - with local.cwd(temp_git_dir): + with cwd(temp_git_dir): assert main(argv=[]) == 0 write_file('f.py', "print('hello world')") - local['git']('add', 'f.py') + cmd_output('git', 'add', 'f.py') assert main(argv=['f.py']) == 0 write_file('F.py', "print('hello world')") - local['git']('add', 'F.py') + cmd_output('git', 'add', 'F.py') assert main(argv=['F.py']) == 1 diff --git a/tests/conftest.py b/tests/conftest.py index 157da6b..de9c2fe 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,11 +3,19 @@ from __future__ import print_function from __future__ import unicode_literals import pytest -from plumbum import local + +from pre_commit_hooks.util import cmd_output +from testing.util import cwd + + +@pytest.yield_fixture +def in_tmpdir(tmpdir): + with cwd(tmpdir.strpath): + yield tmpdir @pytest.yield_fixture def temp_git_dir(tmpdir): git_dir = tmpdir.join('gits').strpath - local['git']('init', git_dir) + cmd_output('git', 'init', git_dir) yield git_dir diff --git a/tests/trailing_whitespace_fixer_test.py b/tests/trailing_whitespace_fixer_test.py index bf508c0..e24a722 100644 --- a/tests/trailing_whitespace_fixer_test.py +++ b/tests/trailing_whitespace_fixer_test.py @@ -1,10 +1,12 @@ -from plumbum import local +from __future__ import absolute_import +from __future__ import unicode_literals from pre_commit_hooks.trailing_whitespace_fixer import fix_trailing_whitespace +from testing.util import cwd def test_fixes_trailing_whitespace(tmpdir): - with local.cwd(tmpdir.strpath): + with cwd(tmpdir.strpath): for filename, contents in ( ('foo.py', 'foo \nbar \n'), ('bar.py', 'bar\t\nbaz\t\n'), diff --git a/tests/util_test.py b/tests/util_test.py new file mode 100644 index 0000000..9b2d723 --- /dev/null +++ b/tests/util_test.py @@ -0,0 +1,17 @@ +from __future__ import absolute_import +from __future__ import unicode_literals + +import pytest + +from pre_commit_hooks.util import CalledProcessError +from pre_commit_hooks.util import cmd_output + + +def test_raises_on_error(): + with pytest.raises(CalledProcessError): + cmd_output('sh', '-c', 'exit 1') + + +def test_output(): + ret = cmd_output('sh', '-c', 'echo hi') + assert ret == 'hi\n'