From 871ab4d72fb32b441e66370b58da642436caaf83 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 13 Mar 2014 22:12:33 -0700 Subject: [PATCH] OMG we're running a hook --- pre_commit/constants.py | 4 ++-- pre_commit/languages/__init__.py | 0 pre_commit/languages/all.py | 24 ++++++++++++++++++++++++ pre_commit/languages/node.py | 7 +++++++ pre_commit/languages/python.py | 32 ++++++++++++++++++++++++++++++++ pre_commit/languages/ruby.py | 7 +++++++ pre_commit/repository.py | 29 +++++++---------------------- tests/conftest.py | 1 + tests/languages/__init__.py | 0 tests/languages/all_test.py | 15 +++++++++++++++ tests/repository_test.py | 11 ++++++++++- 11 files changed, 105 insertions(+), 25 deletions(-) create mode 100644 pre_commit/languages/__init__.py create mode 100644 pre_commit/languages/all.py create mode 100644 pre_commit/languages/node.py create mode 100644 pre_commit/languages/python.py create mode 100644 pre_commit/languages/ruby.py create mode 100644 tests/languages/__init__.py create mode 100644 tests/languages/all_test.py diff --git a/pre_commit/constants.py b/pre_commit/constants.py index 8a52a03c..b9df1995 100644 --- a/pre_commit/constants.py +++ b/pre_commit/constants.py @@ -5,8 +5,8 @@ HOOKS_WORKSPACE = '.pre-commit-files' MANIFEST_FILE = 'manifest.yaml' -SUPPORTED_LANGUAGES = [ +SUPPORTED_LANGUAGES = set([ 'python', 'ruby', 'node', -] \ No newline at end of file +]) \ No newline at end of file diff --git a/pre_commit/languages/__init__.py b/pre_commit/languages/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pre_commit/languages/all.py b/pre_commit/languages/all.py new file mode 100644 index 00000000..033eee14 --- /dev/null +++ b/pre_commit/languages/all.py @@ -0,0 +1,24 @@ + +from pre_commit.languages import node +from pre_commit.languages import python +from pre_commit.languages import ruby + +# A language implements the following two functions in its module: +# +# def install_environment(): +# """Installs a repository in the given repository. Note that the current +# working directory will already be inside the repository. +# """ +# +# def run_hook(hook, file_args): +# """Runs a hook and returns the returncode and output of running that hook. +# +# Returns: +# (returncode, stdout, stderr) +# """ + +languages = { + 'node': node, + 'python': python, + 'ruby': ruby, +} \ No newline at end of file diff --git a/pre_commit/languages/node.py b/pre_commit/languages/node.py new file mode 100644 index 00000000..e2e40da4 --- /dev/null +++ b/pre_commit/languages/node.py @@ -0,0 +1,7 @@ + +def install_environment(): + raise NotImplementedError + + +def run_hook(hook, file_args): + raise NotImplementedError \ No newline at end of file diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py new file mode 100644 index 00000000..c5cab017 --- /dev/null +++ b/pre_commit/languages/python.py @@ -0,0 +1,32 @@ + +import contextlib +from plumbum import local +from plumbum.machines.session import ShellSession + +PY_ENV = 'py_env' + + +@contextlib.contextmanager +def in_env(): + with ShellSession(local['bash'].popen()) as env: + env.run('source {0}/bin/activate'.format(PY_ENV)) + yield env + + +def install_environment(): + assert local.path('setup.py').exists() + # Install a virtualenv + local['virtualenv'][PY_ENV]() + + with in_env() as env: + # Run their setup.py + env.run('pip install .') + + +def run_hook(hook, file_args): + with in_env() as env: + # TODO: batch filenames + return env.run( + ' '.join([hook['entry']] + hook.get('args', []) + list(file_args)), + retcode=None, + ) \ No newline at end of file diff --git a/pre_commit/languages/ruby.py b/pre_commit/languages/ruby.py new file mode 100644 index 00000000..e2e40da4 --- /dev/null +++ b/pre_commit/languages/ruby.py @@ -0,0 +1,7 @@ + +def install_environment(): + raise NotImplementedError + + +def run_hook(hook, file_args): + raise NotImplementedError \ No newline at end of file diff --git a/pre_commit/repository.py b/pre_commit/repository.py index 0b524ef8..3235d82f 100644 --- a/pre_commit/repository.py +++ b/pre_commit/repository.py @@ -5,30 +5,10 @@ from plumbum import local import pre_commit.constants as C from pre_commit.clientlib.validate_manifest import validate_manifest from pre_commit.hooks_workspace import in_hooks_workspace +from pre_commit.languages.all import languages from pre_commit.util import cached_property -def install_python(repo): - assert local.path('setup.py').exists() - local['virtualenv']['py_env']() - local['bash']['-c', 'source py_env/bin/activate && pip install .']() - - -def install_ruby(repo): - raise NotImplementedError - - -def install_node(repo): - raise NotImplementedError - - -language_to_repo_setup_strategy = { - 'python': install_python, - 'ruby': install_ruby, - 'node': install_node, -} - - class Repository(object): def __init__(self, repo_config): self.repo_config = repo_config @@ -84,4 +64,9 @@ class Repository(object): with self.in_checkout(): for language in C.SUPPORTED_LANGUAGES: if language in self.languages: - language_to_repo_setup_strategy[language](self) \ No newline at end of file + languages[language].install_environment() + + def run_hook(self, hook_id, file_args): + with self.in_checkout(): + hook = self.hooks[hook_id] + return languages[hook['language']].run_hook(hook, file_args) \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index d8817f1c..feae5f1e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -66,6 +66,7 @@ setup( local.path('__init__.py').write('') local.path('main.py').write(""" def func(): + print 'Hello World' return 0 """) diff --git a/tests/languages/__init__.py b/tests/languages/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/languages/all_test.py b/tests/languages/all_test.py new file mode 100644 index 00000000..6a17771a --- /dev/null +++ b/tests/languages/all_test.py @@ -0,0 +1,15 @@ + +import pytest + +import pre_commit.constants as C +from pre_commit.languages.all import languages + + +def test_all_languages_have_repo_setups(): + assert set(languages.keys()) == C.SUPPORTED_LANGUAGES + + +@pytest.mark.parametrize('language', C.SUPPORTED_LANGUAGES) +def test_all_languages_support_interface(language): + assert hasattr(languages[language], 'install_environment') + assert hasattr(languages[language], 'run_hook') \ No newline at end of file diff --git a/tests/repository_test.py b/tests/repository_test.py index 824d7b09..b6f98bb3 100644 --- a/tests/repository_test.py +++ b/tests/repository_test.py @@ -30,7 +30,6 @@ def test_create_repo_in_env(dummy_repo_config, dummy_git_repo): @pytest.mark.integration def test_install_python_repo_in_env(python_pre_commit_git_repo, config_for_python_pre_commit_git_repo): repo = Repository(config_for_python_pre_commit_git_repo) - # TODO: do we need create here? repo.install() assert os.path.exists( @@ -43,6 +42,16 @@ def test_install_python_repo_in_env(python_pre_commit_git_repo, config_for_pytho ) +@pytest.mark.integration +def test_run_a_hook_omg(config_for_python_pre_commit_git_repo): + repo = Repository(config_for_python_pre_commit_git_repo) + repo.install() + ret = repo.run_hook('foo', []) + + assert ret[0] == 0 + assert ret[1] == 'Hello World\n' + + @pytest.fixture def mock_repo_config(): config = {