From bb365a6e6898f222878b9b25a6904bebb652a9b3 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 12 Apr 2014 18:19:57 -0700 Subject: [PATCH] Python 3 compatibility. --- .travis.yml | 2 ++ pre_commit/jsonschema_extensions.py | 4 ++-- pre_commit/logging_handler.py | 5 +++-- pre_commit/prefixed_command_runner.py | 3 +++ pre_commit/repository.py | 2 +- pre_commit/run.py | 9 ++++++--- tests/logging_handler_test.py | 18 ++++++------------ tests/repository_test.py | 8 ++++---- tests/staged_files_only_test.py | 4 ++-- tox.ini | 2 +- 10 files changed, 30 insertions(+), 27 deletions(-) diff --git a/.travis.yml b/.travis.yml index d3316a1b..05fe11aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ language: python env: # These should match the tox env list - TOXENV=py26 - TOXENV=py27 + - TOXENV=py33 + - TOXENV=pypy install: pip install tox --use-mirrors script: tox diff --git a/pre_commit/jsonschema_extensions.py b/pre_commit/jsonschema_extensions.py index 5217843c..1187415e 100644 --- a/pre_commit/jsonschema_extensions.py +++ b/pre_commit/jsonschema_extensions.py @@ -21,7 +21,7 @@ def extend_validator_cls(validator_cls, modify): def default_values(properties, instance): - for property, subschema in properties.iteritems(): + for property, subschema in properties.items(): if 'default' in subschema: instance.setdefault( property, copy.deepcopy(subschema['default']), @@ -29,7 +29,7 @@ def default_values(properties, instance): def remove_default_values(properties, instance): - for property, subschema in properties.iteritems(): + for property, subschema in properties.items(): if ( 'default' in subschema and instance.get(property) == subschema['default'] diff --git a/pre_commit/logging_handler.py b/pre_commit/logging_handler.py index 1d3fdca0..3226b8c0 100644 --- a/pre_commit/logging_handler.py +++ b/pre_commit/logging_handler.py @@ -14,12 +14,13 @@ LOG_LEVEL_COLORS = { class LoggingHandler(logging.Handler): - def __init__(self, use_color): + def __init__(self, use_color, print_fn=print): logging.Handler.__init__(self) self.use_color = use_color + self.__print_fn = print_fn def emit(self, record): - print( + self.__print_fn( u'{0}{1}'.format( color.format_color( '[{0}]'.format(record.levelname), diff --git a/pre_commit/prefixed_command_runner.py b/pre_commit/prefixed_command_runner.py index 91bb474a..8e3c930d 100644 --- a/pre_commit/prefixed_command_runner.py +++ b/pre_commit/prefixed_command_runner.py @@ -55,6 +55,9 @@ class PrefixedCommandRunner(object): 'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE, } + if stdin is not None: + stdin = stdin.encode('utf-8') + popen_kwargs.update(kwargs) self._create_path_if_not_exists() replaced_cmd = _replace_cmd(cmd, prefix=self.prefix_dir) diff --git a/pre_commit/repository.py b/pre_commit/repository.py index 6b27aa11..f94336cb 100644 --- a/pre_commit/repository.py +++ b/pre_commit/repository.py @@ -70,7 +70,7 @@ class Repository(object): logger.info('Installing environment for {0}.'.format(self.repo_url)) logger.info('Once installed this environment will be reused.') logger.info('This may take a few minutes...') - with clean_path_on_failure(unicode(local.path(self.sha))): + with clean_path_on_failure(str(local.path(self.sha))): local['git']['clone', '--no-checkout', self.repo_url, self.sha]() with self.in_checkout(): local['git']['checkout', self.sha]() diff --git a/pre_commit/run.py b/pre_commit/run.py index dc88e368..fe6c94ee 100644 --- a/pre_commit/run.py +++ b/pre_commit/run.py @@ -45,7 +45,6 @@ def _run_single_hook(runner, repository, hook_id, args): get_filenames(hook['files'], hook['exclude']), ) - output = '\n'.join([stdout, stderr]).strip() if retcode != repository.hooks[hook_id]['expected_return_value']: retcode = 1 print_color = color.RED @@ -57,8 +56,12 @@ def _run_single_hook(runner, repository, hook_id, args): print(color.format_color(pass_fail, print_color, args.color)) - if output and (retcode or args.verbose): - print('\n' + output) + if (stdout or stderr) and (retcode or args.verbose): + print() + for output in (stdout, stderr): + if output.strip(): + print(output.strip()) + print() return retcode diff --git a/tests/logging_handler_test.py b/tests/logging_handler_test.py index d2fed418..6e8d1835 100644 --- a/tests/logging_handler_test.py +++ b/tests/logging_handler_test.py @@ -1,17 +1,9 @@ -import __builtin__ import mock -import pytest from pre_commit import color from pre_commit.logging_handler import LoggingHandler -@pytest.yield_fixture -def print_mock(): - with mock.patch.object(__builtin__, 'print', autospec=True) as print_mock: - yield print_mock - - class FakeLogRecord(object): def __init__(self, message, levelname, levelno): self.message = message @@ -22,16 +14,18 @@ class FakeLogRecord(object): return self.message -def test_logging_handler_color(print_mock): - handler = LoggingHandler(True) +def test_logging_handler_color(): + print_mock = mock.Mock() + handler = LoggingHandler(True, print_mock) handler.emit(FakeLogRecord('hi', 'WARNING', 30)) print_mock.assert_called_once_with( color.YELLOW + '[WARNING]' + color.NORMAL + ' hi', ) -def test_logging_handler_no_color(print_mock): - handler = LoggingHandler(False) +def test_logging_handler_no_color(): + print_mock = mock.Mock() + handler = LoggingHandler(False, print_mock) handler.emit(FakeLogRecord('hi', 'WARNING', 30)) print_mock.assert_called_once_with( '[WARNING] hi', diff --git a/tests/repository_test.py b/tests/repository_test.py index 7079e301..f2f98720 100644 --- a/tests/repository_test.py +++ b/tests/repository_test.py @@ -55,7 +55,7 @@ def test_run_a_python_hook(config_for_python_hooks_repo): ) assert ret[0] == 0 - assert ret[1] == "['/dev/null']\nHello World\n" + assert ret[1] == b"['/dev/null']\nHello World\n" @pytest.mark.integration @@ -77,7 +77,7 @@ def test_cwd_of_hook(config_for_prints_cwd_repo): ) assert ret[0] == 0 - assert ret[1] == '{0}\n'.format(repo.repo_url) + assert ret[1] == repo.repo_url.encode('utf-8') + b'\n' @pytest.mark.skipif( @@ -90,7 +90,7 @@ def test_run_a_node_hook(config_for_node_hooks_repo): ret = repo.run_hook(PrefixedCommandRunner(C.HOOKS_WORKSPACE), 'foo', []) assert ret[0] == 0 - assert ret[1] == 'Hello World\n' + assert ret[1] == b'Hello World\n' @pytest.mark.integration @@ -101,7 +101,7 @@ def test_run_a_script_hook(config_for_script_hooks_repo): ) assert ret[0] == 0 - assert ret[1] == 'bar\nHello World\n' + assert ret[1] == b'bar\nHello World\n' @pytest.fixture diff --git a/tests/staged_files_only_test.py b/tests/staged_files_only_test.py index 065c73df..5722af3a 100644 --- a/tests/staged_files_only_test.py +++ b/tests/staged_files_only_test.py @@ -118,8 +118,8 @@ def img_staged(empty_git_dir): def _test_img_state(path, expected_file='img1.jpg', status='A'): assert os.path.exists(path.img_filename) assert ( - open(path.img_filename).read() == - open(get_resource_path(expected_file)).read() + open(path.img_filename, 'rb').read() == + open(get_resource_path(expected_file), 'rb').read() ) actual_status = get_short_git_status()['img.jpg'] assert status == actual_status diff --git a/tox.ini b/tox.ini index 8f29214f..5cf24830 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] project = pre_commit # These should match the travis env list -envlist = py26,py27 +envlist = py26,py27,py33,pypy [testenv] install_command = pip install --use-wheel {opts} {packages}