From 06b3d91da07c3d895a68baedb9fd2f926a170ee6 Mon Sep 17 00:00:00 2001 From: Tobias Macey Date: Thu, 19 Nov 2015 12:29:41 -0500 Subject: [PATCH 1/7] Added the additional_dependencies config parameter Added the ability to specify additional dependencies to be installed in the pre-commit environment. Fixed broken tests. --- pre_commit/languages/node.py | 6 +++++- pre_commit/languages/pcre.py | 3 ++- pre_commit/languages/python.py | 6 +++++- pre_commit/languages/ruby.py | 8 +++++++- pre_commit/languages/script.py | 3 ++- pre_commit/languages/system.py | 3 ++- pre_commit/repository.py | 13 ++++++++++++- tests/languages/all_test.py | 4 ++-- 8 files changed, 37 insertions(+), 9 deletions(-) diff --git a/pre_commit/languages/node.py b/pre_commit/languages/node.py index 20fa8572..a57c0a10 100644 --- a/pre_commit/languages/node.py +++ b/pre_commit/languages/node.py @@ -23,7 +23,8 @@ def in_env(repo_cmd_runner, language_version): yield NodeEnv(repo_cmd_runner, language_version) -def install_environment(repo_cmd_runner, version='default'): +def install_environment(repo_cmd_runner, version='default', + additional_dependencies=None): assert repo_cmd_runner.exists('package.json') directory = helpers.environment_dir(ENVIRONMENT_DIR, version) @@ -41,6 +42,9 @@ def install_environment(repo_cmd_runner, version='default'): with in_env(repo_cmd_runner, version) as node_env: node_env.run("cd '{prefix}' && npm install -g") + if additional_dependencies: + node_env.run("cd '{prefix}' && npm install -g " + + (' ').join(additional_dependencies)) def run_hook(repo_cmd_runner, hook, file_args): diff --git a/pre_commit/languages/pcre.py b/pre_commit/languages/pcre.py index 8d73e095..9d8fa410 100644 --- a/pre_commit/languages/pcre.py +++ b/pre_commit/languages/pcre.py @@ -9,7 +9,8 @@ from pre_commit.util import shell_escape ENVIRONMENT_DIR = None -def install_environment(repo_cmd_runner, version='default'): +def install_environment(repo_cmd_runner, version='default', + additional_dependencies=None): """Installation for pcre type is a noop.""" raise AssertionError('Cannot install pcre repo.') diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py index 52b07bbd..ebfba1b7 100644 --- a/pre_commit/languages/python.py +++ b/pre_commit/languages/python.py @@ -42,7 +42,8 @@ def norm_version(version): return version -def install_environment(repo_cmd_runner, version='default'): +def install_environment(repo_cmd_runner, version='default', + additional_dependencies=None): assert repo_cmd_runner.exists('setup.py') directory = helpers.environment_dir(ENVIRONMENT_DIR, version) @@ -57,6 +58,9 @@ def install_environment(repo_cmd_runner, version='default'): repo_cmd_runner.run(venv_cmd) with in_env(repo_cmd_runner, version) as env: env.run("cd '{prefix}' && pip install .") + if additional_dependencies: + env.run("cd '{prefix}' && pip install -U" + + (' ').join(additional_dependencies)) def run_hook(repo_cmd_runner, hook, file_args): diff --git a/pre_commit/languages/ruby.py b/pre_commit/languages/ruby.py index 0931a588..55a18c69 100644 --- a/pre_commit/languages/ruby.py +++ b/pre_commit/languages/ruby.py @@ -78,7 +78,8 @@ def _install_ruby(environment, version): environment.run('rbenv install {0}'.format(version)) -def install_environment(repo_cmd_runner, version='default'): +def install_environment(repo_cmd_runner, version='default', + additional_dependencies=None): directory = helpers.environment_dir(ENVIRONMENT_DIR, version) with clean_path_on_failure(repo_cmd_runner.path(directory)): # TODO: this currently will fail if there's no version specified and @@ -91,6 +92,11 @@ def install_environment(repo_cmd_runner, version='default'): 'cd {prefix} && gem build *.gemspec' ' && gem install --no-ri --no-rdoc *.gem', ) + if additional_dependencies: + ruby_env.run( + 'cd {prefix} && gem install --no-document ' + (' ').join( + additional_dependencies) + ) def run_hook(repo_cmd_runner, hook, file_args): diff --git a/pre_commit/languages/script.py b/pre_commit/languages/script.py index 1b357e4d..5f6d97db 100644 --- a/pre_commit/languages/script.py +++ b/pre_commit/languages/script.py @@ -6,7 +6,8 @@ from pre_commit.languages.helpers import file_args_to_stdin ENVIRONMENT_DIR = None -def install_environment(repo_cmd_runner, version='default'): +def install_environment(repo_cmd_runner, version='default', + additional_dependencies=None): """Installation for script type is a noop.""" raise AssertionError('Cannot install script repo.') diff --git a/pre_commit/languages/system.py b/pre_commit/languages/system.py index 3de48aac..1b49a8ce 100644 --- a/pre_commit/languages/system.py +++ b/pre_commit/languages/system.py @@ -8,7 +8,8 @@ from pre_commit.languages.helpers import file_args_to_stdin ENVIRONMENT_DIR = None -def install_environment(repo_cmd_runner, version='default'): +def install_environment(repo_cmd_runner, version='default', + additional_dependencies=None): """Installation for system type is a noop.""" raise AssertionError('Cannot install system repo.') diff --git a/pre_commit/repository.py b/pre_commit/repository.py index 83a3c01e..e64b78e1 100644 --- a/pre_commit/repository.py +++ b/pre_commit/repository.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import logging import shutil +from collections import defaultdict from cached_property import cached_property @@ -49,6 +50,14 @@ class Repository(object): for _, hook in self.hooks ) + @cached_property + def additional_dependencies(self): + dep_dict = defaultdict(lambda: defaultdict(set)) + for _, hook in self.hooks: + dep_dict[hook['language']][hook['language_version']].update( + hook.get('dependencies', [])) + return dep_dict + @cached_property def hooks(self): # TODO: merging in manifest dicts is a smell imo @@ -107,7 +116,9 @@ class Repository(object): if self.cmd_runner.exists(directory): shutil.rmtree(self.cmd_runner.path(directory)) - language.install_environment(self.cmd_runner, language_version) + language.install_environment( + self.cmd_runner, language_version, + self.additional_dependencies[language_name][language_version]) # Touch the .installed file (atomic) to indicate we've installed open(self.cmd_runner.path(directory, '.installed'), 'w').close() diff --git a/tests/languages/all_test.py b/tests/languages/all_test.py index 90db9ec7..2254e388 100644 --- a/tests/languages/all_test.py +++ b/tests/languages/all_test.py @@ -11,10 +11,10 @@ from pre_commit.languages.all import languages @pytest.mark.parametrize('language', all_languages) def test_install_environment_argspec(language): expected_argspec = inspect.ArgSpec( - args=['repo_cmd_runner', 'version'], + args=['repo_cmd_runner', 'version', 'additional_dependencies'], varargs=None, keywords=None, - defaults=('default',), + defaults=('default', None), ) argspec = inspect.getargspec(languages[language].install_environment) assert argspec == expected_argspec From 3726f07a3f5105da33879f4ffe2510f6cae2bd76 Mon Sep 17 00:00:00 2001 From: Tobias Macey Date: Thu, 19 Nov 2015 15:16:02 -0500 Subject: [PATCH 2/7] Reformatted method signatures, fixed typos --- pre_commit/languages/node.py | 5 +++-- pre_commit/languages/pcre.py | 3 ++- pre_commit/languages/python.py | 5 +++-- pre_commit/languages/ruby.py | 7 ++++--- pre_commit/languages/script.py | 3 ++- pre_commit/languages/system.py | 3 ++- pre_commit/repository.py | 2 +- 7 files changed, 17 insertions(+), 11 deletions(-) diff --git a/pre_commit/languages/node.py b/pre_commit/languages/node.py index a57c0a10..962ab2e6 100644 --- a/pre_commit/languages/node.py +++ b/pre_commit/languages/node.py @@ -23,7 +23,8 @@ def in_env(repo_cmd_runner, language_version): yield NodeEnv(repo_cmd_runner, language_version) -def install_environment(repo_cmd_runner, version='default', +def install_environment(repo_cmd_runner, + version='default', additional_dependencies=None): assert repo_cmd_runner.exists('package.json') directory = helpers.environment_dir(ENVIRONMENT_DIR, version) @@ -44,7 +45,7 @@ def install_environment(repo_cmd_runner, version='default', node_env.run("cd '{prefix}' && npm install -g") if additional_dependencies: node_env.run("cd '{prefix}' && npm install -g " + - (' ').join(additional_dependencies)) + ' '.join(additional_dependencies)) def run_hook(repo_cmd_runner, hook, file_args): diff --git a/pre_commit/languages/pcre.py b/pre_commit/languages/pcre.py index 9d8fa410..4a7882c0 100644 --- a/pre_commit/languages/pcre.py +++ b/pre_commit/languages/pcre.py @@ -9,7 +9,8 @@ from pre_commit.util import shell_escape ENVIRONMENT_DIR = None -def install_environment(repo_cmd_runner, version='default', +def install_environment(repo_cmd_runner, + version='default', additional_dependencies=None): """Installation for pcre type is a noop.""" raise AssertionError('Cannot install pcre repo.') diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py index ebfba1b7..6da5e357 100644 --- a/pre_commit/languages/python.py +++ b/pre_commit/languages/python.py @@ -42,7 +42,8 @@ def norm_version(version): return version -def install_environment(repo_cmd_runner, version='default', +def install_environment(repo_cmd_runner, + version='default', additional_dependencies=None): assert repo_cmd_runner.exists('setup.py') directory = helpers.environment_dir(ENVIRONMENT_DIR, version) @@ -59,7 +60,7 @@ def install_environment(repo_cmd_runner, version='default', with in_env(repo_cmd_runner, version) as env: env.run("cd '{prefix}' && pip install .") if additional_dependencies: - env.run("cd '{prefix}' && pip install -U" + + env.run("cd '{prefix}' && pip install " + (' ').join(additional_dependencies)) diff --git a/pre_commit/languages/ruby.py b/pre_commit/languages/ruby.py index 55a18c69..8602daac 100644 --- a/pre_commit/languages/ruby.py +++ b/pre_commit/languages/ruby.py @@ -78,7 +78,8 @@ def _install_ruby(environment, version): environment.run('rbenv install {0}'.format(version)) -def install_environment(repo_cmd_runner, version='default', +def install_environment(repo_cmd_runner, + version='default', additional_dependencies=None): directory = helpers.environment_dir(ENVIRONMENT_DIR, version) with clean_path_on_failure(repo_cmd_runner.path(directory)): @@ -94,8 +95,8 @@ def install_environment(repo_cmd_runner, version='default', ) if additional_dependencies: ruby_env.run( - 'cd {prefix} && gem install --no-document ' + (' ').join( - additional_dependencies) + 'cd {prefix} && gem install --no-document ' + + ' '.join(additional_dependencies) ) diff --git a/pre_commit/languages/script.py b/pre_commit/languages/script.py index 5f6d97db..d6b25d05 100644 --- a/pre_commit/languages/script.py +++ b/pre_commit/languages/script.py @@ -6,7 +6,8 @@ from pre_commit.languages.helpers import file_args_to_stdin ENVIRONMENT_DIR = None -def install_environment(repo_cmd_runner, version='default', +def install_environment(repo_cmd_runner, + version='default', additional_dependencies=None): """Installation for script type is a noop.""" raise AssertionError('Cannot install script repo.') diff --git a/pre_commit/languages/system.py b/pre_commit/languages/system.py index 1b49a8ce..eec64ad3 100644 --- a/pre_commit/languages/system.py +++ b/pre_commit/languages/system.py @@ -8,7 +8,8 @@ from pre_commit.languages.helpers import file_args_to_stdin ENVIRONMENT_DIR = None -def install_environment(repo_cmd_runner, version='default', +def install_environment(repo_cmd_runner, + version='default', additional_dependencies=None): """Installation for system type is a noop.""" raise AssertionError('Cannot install system repo.') diff --git a/pre_commit/repository.py b/pre_commit/repository.py index e64b78e1..66374649 100644 --- a/pre_commit/repository.py +++ b/pre_commit/repository.py @@ -55,7 +55,7 @@ class Repository(object): dep_dict = defaultdict(lambda: defaultdict(set)) for _, hook in self.hooks: dep_dict[hook['language']][hook['language_version']].update( - hook.get('dependencies', [])) + hook.get('additional_dependencies', [])) return dep_dict @cached_property From fb0d67bd87f52c3ca57d49c0fc7c9841d7f249c9 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 19 Nov 2015 12:46:02 -0800 Subject: [PATCH 3/7] Some slight fixups --- pre_commit/languages/all.py | 6 +++++- pre_commit/languages/node.py | 8 +++++--- pre_commit/languages/pcre.py | 8 +++++--- pre_commit/languages/python.py | 8 +++++--- pre_commit/languages/ruby.py | 8 +++++--- pre_commit/languages/script.py | 8 +++++--- pre_commit/languages/system.py | 8 +++++--- 7 files changed, 35 insertions(+), 19 deletions(-) diff --git a/pre_commit/languages/all.py b/pre_commit/languages/all.py index 4aa8787f..63c1d514 100644 --- a/pre_commit/languages/all.py +++ b/pre_commit/languages/all.py @@ -12,7 +12,11 @@ from pre_commit.languages import system # # Use None for no environment # ENVIRONMENT_DIR = 'foo_env' # -# def install_environment(repo_cmd_runner, version='default'): +# def install_environment( +# repo_cmd_runner, +# version='default', +# additional_dependencies=None, +# ): # """Installs a repository in the given repository. Note that the current # working directory will already be inside the repository. # diff --git a/pre_commit/languages/node.py b/pre_commit/languages/node.py index 962ab2e6..33eee82c 100644 --- a/pre_commit/languages/node.py +++ b/pre_commit/languages/node.py @@ -23,9 +23,11 @@ def in_env(repo_cmd_runner, language_version): yield NodeEnv(repo_cmd_runner, language_version) -def install_environment(repo_cmd_runner, - version='default', - additional_dependencies=None): +def install_environment( + repo_cmd_runner, + version='default', + additional_dependencies=None, +): assert repo_cmd_runner.exists('package.json') directory = helpers.environment_dir(ENVIRONMENT_DIR, version) diff --git a/pre_commit/languages/pcre.py b/pre_commit/languages/pcre.py index 4a7882c0..11d24eed 100644 --- a/pre_commit/languages/pcre.py +++ b/pre_commit/languages/pcre.py @@ -9,9 +9,11 @@ from pre_commit.util import shell_escape ENVIRONMENT_DIR = None -def install_environment(repo_cmd_runner, - version='default', - additional_dependencies=None): +def install_environment( + repo_cmd_runner, + version='default', + additional_dependencies=None, +): """Installation for pcre type is a noop.""" raise AssertionError('Cannot install pcre repo.') diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py index 6da5e357..15fc7234 100644 --- a/pre_commit/languages/python.py +++ b/pre_commit/languages/python.py @@ -42,9 +42,11 @@ def norm_version(version): return version -def install_environment(repo_cmd_runner, - version='default', - additional_dependencies=None): +def install_environment( + repo_cmd_runner, + version='default', + additional_dependencies=None, +): assert repo_cmd_runner.exists('setup.py') directory = helpers.environment_dir(ENVIRONMENT_DIR, version) diff --git a/pre_commit/languages/ruby.py b/pre_commit/languages/ruby.py index 8602daac..acaefcbf 100644 --- a/pre_commit/languages/ruby.py +++ b/pre_commit/languages/ruby.py @@ -78,9 +78,11 @@ def _install_ruby(environment, version): environment.run('rbenv install {0}'.format(version)) -def install_environment(repo_cmd_runner, - version='default', - additional_dependencies=None): +def install_environment( + repo_cmd_runner, + version='default', + additional_dependencies=None, +): directory = helpers.environment_dir(ENVIRONMENT_DIR, version) with clean_path_on_failure(repo_cmd_runner.path(directory)): # TODO: this currently will fail if there's no version specified and diff --git a/pre_commit/languages/script.py b/pre_commit/languages/script.py index d6b25d05..cf2cee46 100644 --- a/pre_commit/languages/script.py +++ b/pre_commit/languages/script.py @@ -6,9 +6,11 @@ from pre_commit.languages.helpers import file_args_to_stdin ENVIRONMENT_DIR = None -def install_environment(repo_cmd_runner, - version='default', - additional_dependencies=None): +def install_environment( + repo_cmd_runner, + version='default', + additional_dependencies=None, +): """Installation for script type is a noop.""" raise AssertionError('Cannot install script repo.') diff --git a/pre_commit/languages/system.py b/pre_commit/languages/system.py index eec64ad3..3930422b 100644 --- a/pre_commit/languages/system.py +++ b/pre_commit/languages/system.py @@ -8,9 +8,11 @@ from pre_commit.languages.helpers import file_args_to_stdin ENVIRONMENT_DIR = None -def install_environment(repo_cmd_runner, - version='default', - additional_dependencies=None): +def install_environment( + repo_cmd_runner, + version='default', + additional_dependencies=None, +): """Installation for system type is a noop.""" raise AssertionError('Cannot install system repo.') From d6be9cdf7cd2e8e74ea2252df325f8ca623caa15 Mon Sep 17 00:00:00 2001 From: Tobias Macey Date: Thu, 19 Nov 2015 16:04:51 -0500 Subject: [PATCH 4/7] Added shell_escape to shell escape dependencies --- pre_commit/languages/node.py | 8 ++++++-- pre_commit/languages/python.py | 8 ++++++-- pre_commit/languages/ruby.py | 10 +++++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/pre_commit/languages/node.py b/pre_commit/languages/node.py index 962ab2e6..129a1515 100644 --- a/pre_commit/languages/node.py +++ b/pre_commit/languages/node.py @@ -5,6 +5,7 @@ import sys from pre_commit.languages import helpers from pre_commit.util import clean_path_on_failure +from pre_commit.util import shell_escape ENVIRONMENT_DIR = 'node_env' @@ -44,8 +45,11 @@ def install_environment(repo_cmd_runner, with in_env(repo_cmd_runner, version) as node_env: node_env.run("cd '{prefix}' && npm install -g") if additional_dependencies: - node_env.run("cd '{prefix}' && npm install -g " + - ' '.join(additional_dependencies)) + node_env.run("cd '{prefix}' && npm install -g {deps}".format( + ' '.join( + [shell_escape(dep) for dep in additional_dependencies] + ) + )) def run_hook(repo_cmd_runner, hook, file_args): diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py index 6da5e357..1acdcead 100644 --- a/pre_commit/languages/python.py +++ b/pre_commit/languages/python.py @@ -9,6 +9,7 @@ import virtualenv from pre_commit.languages import helpers from pre_commit.util import clean_path_on_failure +from pre_commit.util import shell_escape ENVIRONMENT_DIR = 'py_env' @@ -60,8 +61,11 @@ def install_environment(repo_cmd_runner, with in_env(repo_cmd_runner, version) as env: env.run("cd '{prefix}' && pip install .") if additional_dependencies: - env.run("cd '{prefix}' && pip install " + - (' ').join(additional_dependencies)) + env.run("cd '{prefix}' && pip install {deps}".format( + ' '.join( + shell_escape(dep) for dep in additional_dependencies + ) + )) def run_hook(repo_cmd_runner, hook, file_args): diff --git a/pre_commit/languages/ruby.py b/pre_commit/languages/ruby.py index 8602daac..b80d8194 100644 --- a/pre_commit/languages/ruby.py +++ b/pre_commit/languages/ruby.py @@ -8,6 +8,7 @@ from pre_commit.languages import helpers from pre_commit.util import CalledProcessError from pre_commit.util import clean_path_on_failure from pre_commit.util import resource_filename +from pre_commit.util import shell_escape from pre_commit.util import tarfile_open @@ -95,9 +96,12 @@ def install_environment(repo_cmd_runner, ) if additional_dependencies: ruby_env.run( - 'cd {prefix} && gem install --no-document ' + - ' '.join(additional_dependencies) - ) + 'cd {prefix} && gem install --no-document {deps}'.format( + ' '.join( + shell_escape(dep) for dep in + additional_dependencies + ) + )) def run_hook(repo_cmd_runner, hook, file_args): From 0ee4c3efa78af0231ac9e78068cbff37895d5844 Mon Sep 17 00:00:00 2001 From: Tobias Macey Date: Fri, 20 Nov 2015 11:20:01 -0500 Subject: [PATCH 5/7] Added unit tests for dependencies --- pre_commit/languages/node.py | 8 +++--- pre_commit/languages/python.py | 5 ++-- pre_commit/languages/ruby.py | 12 ++++----- tests/repository_test.py | 48 ++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/pre_commit/languages/node.py b/pre_commit/languages/node.py index 839daf00..7f78fdb4 100644 --- a/pre_commit/languages/node.py +++ b/pre_commit/languages/node.py @@ -47,11 +47,13 @@ def install_environment( with in_env(repo_cmd_runner, version) as node_env: node_env.run("cd '{prefix}' && npm install -g") if additional_dependencies: - node_env.run("cd '{prefix}' && npm install -g {deps}".format( + node_env.run( + "cd '{prefix}' && npm install -g " + ' '.join( - [shell_escape(dep) for dep in additional_dependencies] + [shell_escape(dep) for dep in + additional_dependencies] ) - )) + ) def run_hook(repo_cmd_runner, hook, file_args): diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py index 67e330e3..0268a211 100644 --- a/pre_commit/languages/python.py +++ b/pre_commit/languages/python.py @@ -63,11 +63,12 @@ def install_environment( with in_env(repo_cmd_runner, version) as env: env.run("cd '{prefix}' && pip install .") if additional_dependencies: - env.run("cd '{prefix}' && pip install {deps}".format( + env.run( + "cd '{prefix}' && pip install " + ' '.join( shell_escape(dep) for dep in additional_dependencies ) - )) + ) def run_hook(repo_cmd_runner, hook, file_args): diff --git a/pre_commit/languages/ruby.py b/pre_commit/languages/ruby.py index 8d80d5b7..6cf5f457 100644 --- a/pre_commit/languages/ruby.py +++ b/pre_commit/languages/ruby.py @@ -98,12 +98,12 @@ def install_environment( ) if additional_dependencies: ruby_env.run( - 'cd {prefix} && gem install --no-document {deps}'.format( - ' '.join( - shell_escape(dep) for dep in - additional_dependencies - ) - )) + 'cd {prefix} && gem install --no-document ' + + ' '.join( + shell_escape(dep) for dep in + additional_dependencies + ) + ) def run_hook(repo_cmd_runner, hook, file_args): diff --git a/tests/repository_test.py b/tests/repository_test.py index 798cff67..e02e3653 100644 --- a/tests/repository_test.py +++ b/tests/repository_test.py @@ -5,6 +5,7 @@ import io import os import os.path import shutil +from collections import defaultdict import mock import pytest @@ -278,6 +279,7 @@ def mock_repo_config(): 'hooks': [{ 'id': 'pyflakes', 'files': '\\.py$', + 'additional_dependencies': ['pep8'] }], } config_wrapped = apply_defaults([config], CONFIG_JSON_SCHEMA) @@ -303,6 +305,52 @@ def test_languages(tempdir_factory, store): assert repo.languages == set([('python', 'default')]) +@pytest.mark.integration +def test_additional_dependencies(tempdir_factory, store): + path = make_repo(tempdir_factory, 'python_hooks_repo') + config = make_config_from_repo(path) + config['hooks'][0]['additional_dependencies'] = ['pep8'] + repo = Repository.create(config, store) + expected_deps = defaultdict(lambda: defaultdict(set)) + expected_deps['python']['default'].update(['pep8']) + assert repo.additional_dependencies == expected_deps + + +@pytest.mark.integration +def test_additional_python_dependencies_installed(tempdir_factory, store): + path = make_repo(tempdir_factory, 'python_hooks_repo') + config = make_config_from_repo(path) + config['hooks'][0]['additional_dependencies'] = ['pep8'] + repo = Repository.create(config, store) + repo.run_hook(repo.hooks[0][1], []) + output = repo.cmd_runner.run(['pip', 'freeze']) + assert 'pep8' in output[1] + + +@pytest.mark.integration +def test_additional_ruby_dependencies_installed(tempdir_factory, store): + path = make_repo(tempdir_factory, 'ruby_hooks_repo') + config = make_config_from_repo(path) + config['hooks'][0]['additional_dependencies'] = ['rubocop'] + repo = Repository.create(config, store) + repo.run_hook(repo.hooks[0][1], []) + output = repo.cmd_runner.run(['gem', 'list', '--local']) + assert 'rubocop' in output[1] + + +@pytest.mark.integration +def test_additional_node_dependencies_installed(tempdir_factory, store): + path = make_repo(tempdir_factory, 'node_hooks_repo') + config = make_config_from_repo(path) + config['hooks'][0]['additional_dependencies'] = ['eslint'] + repo = Repository.create(config, store) + repo.run_hook(repo.hooks[0][1], []) + repo.cmd_runner.run(['npm', 'config', 'set', 'global', 'true', + '&&', 'npm', 'ls']) + output = repo.cmd_runner.run(['npm', 'ls']) + assert 'eslint' in output[1] + + def test_reinstall(tempdir_factory, store, log_info_mock): path = make_repo(tempdir_factory, 'python_hooks_repo') config = make_config_from_repo(path) From 738c2ad7bd9b138594d70024007791d627322b2c Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Fri, 20 Nov 2015 13:52:20 -0800 Subject: [PATCH 6/7] Fixups + make the tests work --- pre_commit/languages/node.py | 3 +-- pre_commit/languages/ruby.py | 9 ++++---- pre_commit/languages/script.py | 1 - tests/repository_test.py | 39 +++++++++++++++++----------------- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/pre_commit/languages/node.py b/pre_commit/languages/node.py index 7f78fdb4..1cf0d999 100644 --- a/pre_commit/languages/node.py +++ b/pre_commit/languages/node.py @@ -50,8 +50,7 @@ def install_environment( node_env.run( "cd '{prefix}' && npm install -g " + ' '.join( - [shell_escape(dep) for dep in - additional_dependencies] + shell_escape(dep) for dep in additional_dependencies ) ) diff --git a/pre_commit/languages/ruby.py b/pre_commit/languages/ruby.py index 6cf5f457..aedf0bc6 100644 --- a/pre_commit/languages/ruby.py +++ b/pre_commit/languages/ruby.py @@ -93,15 +93,14 @@ def install_environment( if version != 'default': _install_ruby(ruby_env, version) ruby_env.run( - 'cd {prefix} && gem build *.gemspec' - ' && gem install --no-ri --no-rdoc *.gem', + 'cd {prefix} && gem build *.gemspec && ' + 'gem install --no-ri --no-rdoc *.gem', ) if additional_dependencies: ruby_env.run( - 'cd {prefix} && gem install --no-document ' + + 'cd {prefix} && gem install --no-ri --no-rdoc ' + ' '.join( - shell_escape(dep) for dep in - additional_dependencies + shell_escape(dep) for dep in additional_dependencies ) ) diff --git a/pre_commit/languages/script.py b/pre_commit/languages/script.py index cf2cee46..5ba871ea 100644 --- a/pre_commit/languages/script.py +++ b/pre_commit/languages/script.py @@ -18,7 +18,6 @@ def install_environment( def run_hook(repo_cmd_runner, hook, file_args): return repo_cmd_runner.run( ['xargs', '-0', '{{prefix}}{0}'.format(hook['entry'])] + hook['args'], - # TODO: this is duplicated in pre_commit/languages/helpers.py stdin=file_args_to_stdin(file_args), retcode=None, encoding=None, diff --git a/tests/repository_test.py b/tests/repository_test.py index e02e3653..0050295b 100644 --- a/tests/repository_test.py +++ b/tests/repository_test.py @@ -5,7 +5,6 @@ import io import os import os.path import shutil -from collections import defaultdict import mock import pytest @@ -14,8 +13,9 @@ from pre_commit import five from pre_commit.clientlib.validate_config import CONFIG_JSON_SCHEMA from pre_commit.clientlib.validate_config import validate_config_extra from pre_commit.jsonschema_extensions import apply_defaults -from pre_commit.languages.python import norm_version -from pre_commit.languages.python import PythonEnv +from pre_commit.languages import node +from pre_commit.languages import python +from pre_commit.languages import ruby from pre_commit.repository import Repository from pre_commit.util import cmd_output from pre_commit.util import cwd @@ -311,44 +311,45 @@ def test_additional_dependencies(tempdir_factory, store): config = make_config_from_repo(path) config['hooks'][0]['additional_dependencies'] = ['pep8'] repo = Repository.create(config, store) - expected_deps = defaultdict(lambda: defaultdict(set)) - expected_deps['python']['default'].update(['pep8']) - assert repo.additional_dependencies == expected_deps + assert repo.additional_dependencies['python']['default'] == set(('pep8',)) @pytest.mark.integration def test_additional_python_dependencies_installed(tempdir_factory, store): path = make_repo(tempdir_factory, 'python_hooks_repo') config = make_config_from_repo(path) - config['hooks'][0]['additional_dependencies'] = ['pep8'] + config['hooks'][0]['additional_dependencies'] = ['mccabe'] repo = Repository.create(config, store) repo.run_hook(repo.hooks[0][1], []) - output = repo.cmd_runner.run(['pip', 'freeze']) - assert 'pep8' in output[1] + with python.in_env(repo.cmd_runner, 'default') as env: + output = env.run('pip freeze -l')[1] + assert 'mccabe' in output @pytest.mark.integration def test_additional_ruby_dependencies_installed(tempdir_factory, store): path = make_repo(tempdir_factory, 'ruby_hooks_repo') config = make_config_from_repo(path) - config['hooks'][0]['additional_dependencies'] = ['rubocop'] + config['hooks'][0]['additional_dependencies'] = ['mime-types'] repo = Repository.create(config, store) repo.run_hook(repo.hooks[0][1], []) - output = repo.cmd_runner.run(['gem', 'list', '--local']) - assert 'rubocop' in output[1] + with ruby.in_env(repo.cmd_runner, 'default') as env: + output = env.run('gem list --local')[1] + assert 'mime-types' in output @pytest.mark.integration def test_additional_node_dependencies_installed(tempdir_factory, store): path = make_repo(tempdir_factory, 'node_hooks_repo') config = make_config_from_repo(path) - config['hooks'][0]['additional_dependencies'] = ['eslint'] + # Careful to choose a small package that's not depped by npm + config['hooks'][0]['additional_dependencies'] = ['lodash'] repo = Repository.create(config, store) repo.run_hook(repo.hooks[0][1], []) - repo.cmd_runner.run(['npm', 'config', 'set', 'global', 'true', - '&&', 'npm', 'ls']) - output = repo.cmd_runner.run(['npm', 'ls']) - assert 'eslint' in output[1] + with node.in_env(repo.cmd_runner, 'default') as env: + env.run('npm config set global true') + output = env.run(('npm ls'))[1] + assert 'lodash' in output def test_reinstall(tempdir_factory, store, log_info_mock): @@ -383,7 +384,7 @@ def test_control_c_control_c_on_install(tempdir_factory, store): # raise as well. with pytest.raises(MyKeyboardInterrupt): with mock.patch.object( - PythonEnv, 'run', side_effect=MyKeyboardInterrupt, + python.PythonEnv, 'run', side_effect=MyKeyboardInterrupt, ): with mock.patch.object( shutil, 'rmtree', side_effect=MyKeyboardInterrupt, @@ -474,5 +475,5 @@ def test_norm_version_expanduser(): # pragma: no cover else: path = '~/.pyenv/versions/3.4.3/bin/python' expected_path = home + '/.pyenv/versions/3.4.3/bin/python' - result = norm_version(path) + result = python.norm_version(path) assert result == expected_path From 0980887f57afd01dbf27c27c8946c50655f54573 Mon Sep 17 00:00:00 2001 From: Tobias Macey Date: Fri, 20 Nov 2015 20:22:47 -0500 Subject: [PATCH 7/7] Added new parameter to config schema --- pre_commit/clientlib/validate_config.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pre_commit/clientlib/validate_config.py b/pre_commit/clientlib/validate_config.py index e4a90a6c..e4cbbddf 100644 --- a/pre_commit/clientlib/validate_config.py +++ b/pre_commit/clientlib/validate_config.py @@ -39,6 +39,10 @@ CONFIG_JSON_SCHEMA = { 'type': 'array', 'items': {'type': 'string'}, }, + 'additional_dependencies': { + 'type': 'array', + 'items': {'type': 'string'} + } }, 'required': ['id'], }