From 0a6199fa88b62715e034483189a685c54907516e Mon Sep 17 00:00:00 2001 From: Sam Stavinoha Date: Sat, 26 Aug 2017 23:38:34 -0500 Subject: [PATCH 1/9] dont kill tox run if pyenv is not installed Now only emits a warning. Fixes #10 --- tox_pyenv.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tox_pyenv.py b/tox_pyenv.py index 6109103..15e3720 100644 --- a/tox_pyenv.py +++ b/tox_pyenv.py @@ -79,19 +79,22 @@ def tox_get_python_executable(envconfig): ) out, err = pipe.communicate() except OSError: - raise PyenvMissing( + err = '\'pyenv\': command not found' + LOG.warning( "pyenv doesn't seem to be installed, you probably " - "don't want this plugin installed either.") - if pipe.poll() == 0: - return out.strip() + "don't want this plugin installed either." + ) else: - if not envconfig.tox_pyenv_fallback: - raise PyenvWhichFailed(err) - LOG.debug("`%s` failed thru tox-pyenv plugin, falling back. " - "STDERR: \"%s\" | To disable this behavior, set " - "tox_pyenv_fallback=False in your tox.ini or use " - " --tox-pyenv-no-fallback on the command line.", - ' '.join([str(x) for x in cmd]), err) + if pipe.poll() == 0: + return out.strip() + else: + if not envconfig.tox_pyenv_fallback: + raise PyenvWhichFailed(err) + LOG.debug("`%s` failed thru tox-pyenv plugin, falling back. " + "STDERR: \"%s\" | To disable this behavior, set " + "tox_pyenv_fallback=False in your tox.ini or use " + " --tox-pyenv-no-fallback on the command line.", + ' '.join([str(x) for x in cmd]), err) def _setup_no_fallback(parser): From d997ba8e2d4f84cd56199ddfdc8a1da4f56f2d44 Mon Sep 17 00:00:00 2001 From: Sam Stavinoha Date: Sun, 27 Aug 2017 00:09:37 -0500 Subject: [PATCH 2/9] add test for 'dont kill tox run if..' --- setup.py | 6 +++++ test-requirements.txt | 3 +++ test_tox_pyenv.py | 62 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index b96547c..01d1154 100644 --- a/setup.py +++ b/setup.py @@ -41,6 +41,11 @@ 'tox>=2.0' ] +TESTS_REQUIRE = [ + 'mock>=2.0.0', + 'pycodestyle>=2.3.1', + 'pylint>=1.7.2', +] CLASSIFIERS = [ 'Intended Audience :: Developers', @@ -72,6 +77,7 @@ 'license': about['__license__'], 'long_description': LONG_DESCRIPTION, 'name': about['__title__'], + 'tests_require': TESTS_REQUIRE, 'py_modules': ['tox_pyenv'], 'url': about['__url__'], 'version': about['__version__'], diff --git a/test-requirements.txt b/test-requirements.txt index 9eccdff..e3144ca 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1 +1,4 @@ +mock>=2.0.0 nose==1.3.7 +pycodestyle>=2.3.1 +pylint>=1.7.2 diff --git a/test_tox_pyenv.py b/test_tox_pyenv.py index 2b36957..738d9f5 100644 --- a/test_tox_pyenv.py +++ b/test_tox_pyenv.py @@ -1,11 +1,16 @@ from __future__ import print_function +import errno import os import platform import subprocess import sys import unittest +import mock + +import tox_pyenv + try: unicode except NameError: @@ -19,6 +24,55 @@ def touni(s, enc='utf8', err='strict'): return unicode(s or ("" if s is None else s)) +class MockTestenvConfig(object): + def __init__(self, basepython): + self.basepython = basepython + self.tox_pyenv_fallback = True + + +class TestToxPyenvNoPyenv(unittest.TestCase): + + def setUp(self): + def _mock_popen_func(cmd, *args, **kw): + if all(x in cmd for x in ['which', '*TEST*']): + raise OSError(errno.ENOENT, 'No such file or directory') + self.fail('Unexpected call to Popen') + # return self.popen_patcher.temp_original(*args, **kw) + self.popen_patcher = mock.patch.object( + tox_pyenv.subprocess, 'Popen', autospec=True, + side_effect=_mock_popen_func, + ) + self.popen_patcher.start() + self.warning_patcher = mock.patch.object( + tox_pyenv.LOG, 'warning', autospec=True, + ) + self.warning_patcher.start() + + def tearDown(self): + self.popen_patcher.stop() + self.warning_patcher.stop() + + def test_logs_if_no_pyenv_binary(self): + mock_test_env_config = MockTestenvConfig('*TEST*') + tox_pyenv.tox_get_python_executable(mock_test_env_config) + expected_popen = [ + mock.call( + [mock.ANY, 'which', '*TEST*'], + stderr=-1, stdout=-1, + universal_newlines=True + ) + ] + self.assertEqual( + tox_pyenv.subprocess.Popen.call_args_list, + expected_popen + ) + expected_warn = [ + mock.call("pyenv doesn't seem to be installed, you " + "probably don't want this plugin installed either.") + ] + self.assertEqual(tox_pyenv.LOG.warning.call_args_list, expected_warn) + + class TestThings(unittest.TestCase): def test_the_answer(self): @@ -27,12 +81,12 @@ def test_the_answer(self): def test_is_precisely_correct_version(self): - toxenvname = 'TOX_%s' % os.environ['TOX_ENV_NAME'].upper() - expected_string = os.environ[toxenvname] + toxenvname = 'TOX_%s' % os.environ['TOX_ENV_NAME'].upper().strip() + expected_string = os.environ[toxenvname].strip(' "\'') print('\n\nTOX ENV NAME: %s' % toxenvname) if platform.python_implementation() == 'PyPy': - actual_list = [str(_) for _ in sys.pypy_version_info[:3]] - expected_string = expected_string.split('-')[1] + actual_list = [str(_).strip() for _ in sys.pypy_version_info[:3]] + expected_string = expected_string.split('-')[1].strip(' "\'') print('\nExpected version for this tox env: PyPy %s' % expected_string) print('Actual version for this tox env: PyPy %s' From 98e7268ea8fde0525256756cfab073fecf6b64bf Mon Sep 17 00:00:00 2001 From: Sam Stavinoha Date: Sun, 27 Aug 2017 00:10:45 -0500 Subject: [PATCH 3/9] add style checks during tests --- tox.ini | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index d0bfca6..851db69 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py,py26,py27,py32,py33,py34,py35,pypy +envlist = style,py,py26,py27,py32,py33,py34,py35,pypy [testenv] whitelist_externals = env @@ -12,3 +12,11 @@ deps = {py,py26,py27,py33,py34,py35,pypy}: pip commands = python -V env nosetests {posargs} --verbose --nocapture --logging-level=DEBUG + + +[testenv:style] +deps = -r test-requirements.txt +basepython = python2.7 +commands = + pycodestyle tox_pyenv.py test_tox_pyenv.py + pylint tox_pyenv.py From cbfabd99be29521860732f3ec749604041e80f10 Mon Sep 17 00:00:00 2001 From: Sam Stavinoha Date: Sun, 27 Aug 2017 00:11:02 -0500 Subject: [PATCH 4/9] use newer version of python 2.7.x during tests --- circle.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/circle.yml b/circle.yml index f265294..5ba6757 100644 --- a/circle.yml +++ b/circle.yml @@ -1,11 +1,11 @@ machine: python: - version: '2.7.9' + version: '2.7.11' environment: TOX_PYPY: 'pypy-2.5.0' - TOX_PY: '2.7.9' + TOX_PY: '2.7.11' TOX_PY26: '2.6.8' - TOX_PY27: '2.7.10' + TOX_PY27: '2.7.9' TOX_PY32: '3.2.5' TOX_PY33: '3.3.3' TOX_PY34: '3.4.3' From a6dca3cf2e7d400d7b9bcf9a8b2fb0795425a735 Mon Sep 17 00:00:00 2001 From: Sam Stavinoha Date: Sun, 27 Aug 2017 00:11:31 -0500 Subject: [PATCH 5/9] lint --- tox_pyenv.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tox_pyenv.py b/tox_pyenv.py index 15e3720..0c73aae 100644 --- a/tox_pyenv.py +++ b/tox_pyenv.py @@ -67,7 +67,16 @@ class PyenvWhichFailed(ToxPyenvException): @tox_hookimpl def tox_get_python_executable(envconfig): + """Return a python executable for the given python base name. + + The first plugin/hook which returns an executable path will determine it. + + ``envconfig`` is the testenv configuration which contains + per-testenv configuration, notably the ``.envname`` and ``.basepython`` + setting. + """ try: + # pylint: disable=no-member pyenv = (getattr(py.path.local.sysfind('pyenv'), 'strpath', 'pyenv') or 'pyenv') cmd = [pyenv, 'which', envconfig.basepython] @@ -140,4 +149,5 @@ def _pyenv_fallback(testenv_config, value): @tox_hookimpl def tox_addoption(parser): + """Add command line option to the argparse-style parser object.""" _setup_no_fallback(parser) From 5a3a16913bf964cbb7d6e14860bed6c7446aebe2 Mon Sep 17 00:00:00 2001 From: Sam Stavinoha Date: Sun, 27 Aug 2017 00:23:45 -0500 Subject: [PATCH 6/9] remove dependency constraints --- circle.yml | 4 +++- tox.ini | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/circle.yml b/circle.yml index 5ba6757..ff97f0f 100644 --- a/circle.yml +++ b/circle.yml @@ -14,7 +14,9 @@ machine: dependencies: override: - pip -V - - pip install -U 'pip<8.0' 'virtualenv<14.0' ipdb tox . + - pip install -U pip + - pip install -U tox + - pip install -U . - pyenv local $TOX_PY35 $TOX_PY34 $TOX_PY33 $TOX_PY32 $TOX_PY27 $TOX_PY26 $TOX_PYPY test: diff --git a/tox.ini b/tox.ini index 851db69..6bf8743 100644 --- a/tox.ini +++ b/tox.ini @@ -6,8 +6,7 @@ whitelist_externals = env install_command = pip install -U {opts} {packages} setenv= TOX_ENV_NAME={envname} passenv = TOX_* -deps = {py,py26,py27,py33,py34,py35,pypy}: pip - -r{toxinidir}/requirements.txt +deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = python -V env @@ -15,7 +14,8 @@ commands = python -V [testenv:style] -deps = -r test-requirements.txt +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt basepython = python2.7 commands = pycodestyle tox_pyenv.py test_tox_pyenv.py From 959da594c7eea31bd6eaca490e9dea8ecb0f9d9c Mon Sep 17 00:00:00 2001 From: Sam Stavinoha Date: Sun, 27 Aug 2017 01:07:32 -0500 Subject: [PATCH 7/9] update README --- README.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b651a4..2a608ca 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ dependencies: - pyenv local 2.7.9 3.4.3 3.5.0 ``` -The versions passed to `pyenv local` must be [installed](https://github.com/yyuu/pyenv/blob/master/COMMANDS.md#pyenv-install) for this to work. Check out the list of python versions that are pre-installed in the CircleCI build environment: https://circleci.com/docs/environment#python +The versions passed to `pyenv local` must be [installed](https://github.com/yyuu/pyenv/blob/master/COMMANDS.md#pyenv-install) for this to work. See [CircleCI Preinstalled Python Versions] for a list. #### Corresponding [tox.ini](https://tox.readthedocs.org/en/latest/config.html) @@ -29,3 +29,50 @@ The result of the setup above means running `tox` will run tests against python #### notes If you want tox to _exclusively_ use `pyenv which` to find executables, you will need use the `--tox-pyenv-no-fallback` command line option, or set `tox_pyenv_fallback=False` in your tox.ini. By default, if `tox-pyenv` fails to find a python executable it will fallback to tox's built-in strategy. + +#### CircleCI Preinstalled Python Versions + +Here is the list of python versions that are *pre-installed* in the CircleCI build environment (as of 09/27/2017): + +``` +$ pyenv versions + system + 2.6.6 + 2.6.8 + 2.7 + 2.7.10 + 2.7.11 + 2.7.3 + 2.7.4 + 2.7.5 + 2.7.6 + 2.7.7 + 2.7.8 +* 2.7.9 (set by /home/ubuntu/.pyenv/version) + 3.1.5 + 3.2 + 3.2.5 + 3.3.0 + 3.3.2 + 3.3.3 + 3.4.0 + 3.4.1 + 3.4.2 + 3.4.3 + 3.5.0 + pypy-2.2.1 + pypy-2.3.1 + pypy-2.4.0 + pypy-2.5.0 +``` + +If the version you need isn't in the list, such as Python `3.6-dev` include an `install` step: + +``` +dependencies: + override: + - pip install tox tox-pyenv + - pyenv install --skip-existing 3.6-dev + - pyenv local 3.6-dev +``` + From e3c71e2da974801acb2b709413f8582d6cd8e54d Mon Sep 17 00:00:00 2001 From: Sam Stavinoha Date: Sun, 27 Aug 2017 01:19:15 -0500 Subject: [PATCH 8/9] remove official support for python 3.2 --- circle.yml | 3 +-- setup.py | 1 - tox.ini | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/circle.yml b/circle.yml index ff97f0f..20c244c 100644 --- a/circle.yml +++ b/circle.yml @@ -6,7 +6,6 @@ machine: TOX_PY: '2.7.11' TOX_PY26: '2.6.8' TOX_PY27: '2.7.9' - TOX_PY32: '3.2.5' TOX_PY33: '3.3.3' TOX_PY34: '3.4.3' TOX_PY35: '3.5.0' @@ -17,7 +16,7 @@ dependencies: - pip install -U pip - pip install -U tox - pip install -U . - - pyenv local $TOX_PY35 $TOX_PY34 $TOX_PY33 $TOX_PY32 $TOX_PY27 $TOX_PY26 $TOX_PYPY + - pyenv local $TOX_PY35 $TOX_PY34 $TOX_PY33 $TOX_PY27 $TOX_PY26 $TOX_PYPY test: override: diff --git a/setup.py b/setup.py index 01d1154..775fa7c 100644 --- a/setup.py +++ b/setup.py @@ -57,7 +57,6 @@ 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', diff --git a/tox.ini b/tox.ini index 6bf8743..b50cd22 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = style,py,py26,py27,py32,py33,py34,py35,pypy +envlist = style,py,py26,py27,py33,py34,py35,pypy [testenv] whitelist_externals = env From 214b88e29f7e5c6dd474846192002146223b4aab Mon Sep 17 00:00:00 2001 From: Sam Stavinoha Date: Sun, 27 Aug 2017 01:34:01 -0500 Subject: [PATCH 9/9] Fix link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a608ca..974c2b6 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ dependencies: - pyenv local 2.7.9 3.4.3 3.5.0 ``` -The versions passed to `pyenv local` must be [installed](https://github.com/yyuu/pyenv/blob/master/COMMANDS.md#pyenv-install) for this to work. See [CircleCI Preinstalled Python Versions] for a list. +The versions passed to `pyenv local` must be [installed](https://github.com/yyuu/pyenv/blob/master/COMMANDS.md#pyenv-install) for this to work. See [CircleCI Preinstalled Python Versions](#circleci-preinstalled-python-versions) for a list. #### Corresponding [tox.ini](https://tox.readthedocs.org/en/latest/config.html)