From b38964389b2df20c166df11906d77a3f7d56ab76 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 21 Apr 2015 11:51:10 +0200 Subject: trying out isolating env variables --- CHANGELOG | 20 +++++++++++++++----- doc/config.txt | 14 ++++++++++++++ doc/example/basic.txt | 16 ++++++++++++++++ setup.cfg | 2 ++ setup.py | 2 +- tests/test_config.py | 37 +++++++++++++++++++++++++++++++++++++ tests/test_venv.py | 11 ++++++++--- tox/__init__.py | 2 +- tox/_config.py | 12 ++++++++++++ tox/_venv.py | 5 ++++- 10 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 setup.cfg diff --git a/CHANGELOG b/CHANGELOG index 7865ef7..f537931 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,11 +1,21 @@ -2.0.dev1 +2.0.0.dev1 ----------- -- introduce a way to specify on which platform a testenvironment is to - execute: the new per-environment "platform" setting allows to specify +- (new) introduce environment variable isolation: + tox now only passes the PATH variable from the tox + invocation environment to the test environment and on Windows + also ``SYSTEMROOT`` and ``PATHEXT``. If you need to pass through further + environment variables you can use the new ``passenv`` setting, + a space-separated list of environment variable names. Each name + can make use of fnmatch-style glob patterns. All environment + variables which exist in the tox-invocation environment will be copied + to the test environment. + +- (new) introduce a way to specify on which platform a testenvironment is to + execute: the new per-venv "platform" setting allows to specify a regular expression which is matched against sys.platform. - If platform is set and doesn't match the test environment the - test environment is ignored, no setup or tests are attempted. + If platform is set and doesn't match the platform spec in the test + environment the test environment is ignored, no setup or tests are attempted. 1.9.2 diff --git a/doc/config.txt b/doc/config.txt index a7702ac..04f1678 100644 --- a/doc/config.txt +++ b/doc/config.txt @@ -169,6 +169,20 @@ Complete list of settings that you can put into ``testenv*`` sections: will be used for all test command invocations as well as for installing the sdist package into a virtual environment. +.. confval:: passenv=SPACE-SEPARATED-GLOBNAMES + + .. versionadded:: 2.0 + + A list of wildcard environment variable names which + shall be copied from the tox invocation environment to the test + environment. If a specified environment variable doesn't exist in the tox + invocation environment it is ignored. You can use ``*`` and ``?`` to + match multiple environment variables with one name. + + Note that the ``PATH`` variable is unconditionally passed down and on + Windows ``SYSTEMROOT`` and ``PATHEXT`` will be passed down as well. + You can override these variables with the ``setenv`` option. + .. confval:: recreate=True|False(default) Always recreate virtual environment if this option is True. diff --git a/doc/example/basic.txt b/doc/example/basic.txt index b88b28c..f4df233 100644 --- a/doc/example/basic.txt +++ b/doc/example/basic.txt @@ -173,6 +173,22 @@ To force tox to recreate a (particular) virtual environment:: would trigger a complete reinstallation of the existing py27 environment (or create it afresh if it doesn't exist). +passing down environment variables +------------------------------------------- + +.. versionadded:: 2.0 + +By default tox will only pass the ``PATH`` environment variable (and on +windows ``SYSTEMROOT`` and ``PATHEXT``) from the tox invocation to the +test environments. If you want to pass down additional environment +variables you can use the ``passenv`` option:: + + [testenv] + passenv = LANG + +When your test commands execute they will execute with +the same LANG setting as the one with which tox was invoked. + setting environment variables ------------------------------------------- diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..3c6e79c --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal=1 diff --git a/setup.py b/setup.py index ec27f73..82c45db 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ def main(): description='virtualenv-based automation of test activities', long_description=open("README.rst").read(), url='http://tox.testrun.org/', - version='1.9.3.dev1', + version='2.0.0.dev1', license='http://opensource.org/licenses/MIT', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], author='holger krekel', diff --git a/tests/test_config.py b/tests/test_config.py index 758db48..122cbc5 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -642,6 +642,43 @@ class TestConfigTestEnv: assert envconfig.setenv['PYTHONPATH'] == 'something' assert envconfig.setenv['ANOTHER_VAL'] == 'else' + @pytest.mark.parametrize("plat", ["win32", "linux2"]) + def test_passenv(self, tmpdir, newconfig, monkeypatch, plat): + monkeypatch.setattr(sys, "platform", plat) + monkeypatch.setenv("A123A", "a") + monkeypatch.setenv("A123B", "b") + monkeypatch.setenv("BX23", "0") + config = newconfig(""" + [testenv] + passenv = A123* B?23 + """) + assert len(config.envconfigs) == 1 + envconfig = config.envconfigs['python'] + if plat == "win32": + assert "PATHEXT" in envconfig.passenv + assert "SYSTEMROOT" in envconfig.passenv + assert "PATH" in envconfig.passenv + assert "A123A" in envconfig.passenv + assert "A123B" in envconfig.passenv + + def test_passenv_with_factor(self, tmpdir, newconfig, monkeypatch): + monkeypatch.setenv("A123A", "a") + monkeypatch.setenv("A123B", "b") + monkeypatch.setenv("BX23", "0") + config = newconfig(""" + [tox] + envlist = {x1,x2} + [testenv] + passenv = + x1: A123A + x2: A123B + """) + assert len(config.envconfigs) == 2 + assert "A123A" in config.envconfigs["x1"].passenv + assert "A123B" not in config.envconfigs["x1"].passenv + assert "A123B" in config.envconfigs["x2"].passenv + assert "A123A" not in config.envconfigs["x2"].passenv + def test_changedir_override(self, tmpdir, newconfig): config = newconfig(""" [testenv] diff --git a/tests/test_venv.py b/tests/test_venv.py index 3faa16b..3a3689c 100644 --- a/tests/test_venv.py +++ b/tests/test_venv.py @@ -517,11 +517,13 @@ class TestVenvTest: assert 'PIP_REQUIRE_VIRTUALENV' not in os.environ assert '__PYVENV_LAUNCHER__' not in os.environ -def test_setenv_added_to_pcall(tmpdir, mocksession, newconfig): +def test_env_variables_added_to_pcall(tmpdir, mocksession, newconfig, monkeypatch): pkg = tmpdir.ensure("package.tar.gz") + monkeypatch.setenv("X123", "123") config = newconfig([], """ [testenv:python] commands=python -V + passenv = X123 setenv = ENV_VAR = value """) @@ -540,9 +542,12 @@ def test_setenv_added_to_pcall(tmpdir, mocksession, newconfig): assert 'ENV_VAR' in env assert env['ENV_VAR'] == 'value' assert env['VIRTUAL_ENV'] == str(venv.path) + assert env['X123'] == "123" - for e in os.environ: - assert e in env + assert set(env) == set(["ENV_VAR", "VIRTUAL_ENV", "PYTHONHASHSEED", + "X123", "PATH"]) + #for e in os.environ: + # assert e in env def test_installpkg_no_upgrade(tmpdir, newmocksession): pkg = tmpdir.ensure("package.tar.gz") diff --git a/tox/__init__.py b/tox/__init__.py index c206441..95f2dfb 100644 --- a/tox/__init__.py +++ b/tox/__init__.py @@ -1,5 +1,5 @@ # -__version__ = '1.9.3.dev1' +__version__ = '2.0.0.dev1' class exception: class Error(Exception): diff --git a/tox/_config.py b/tox/_config.py index b9ffc62..2fae46a 100644 --- a/tox/_config.py +++ b/tox/_config.py @@ -1,6 +1,7 @@ import argparse import os import random +from fnmatch import fnmatchcase import sys import re import shlex @@ -366,6 +367,17 @@ class parseini: if config.hashseed is not None: setenv['PYTHONHASHSEED'] = config.hashseed setenv.update(reader.getdict(section, 'setenv')) + + # read passenv + vc.passenv = set(["PATH"]) + if sys.platform == "win32": + vc.passenv.add("SYSTEMROOT") # needed for python's crypto module + vc.passenv.add("PATHEXT") # needed for discovering executables + for spec in reader.getlist(section, "passenv", sep=" "): + for name in os.environ: + if fnmatchcase(name, spec): + vc.passenv.add(name) + vc.setenv = setenv if not vc.setenv: vc.setenv = None diff --git a/tox/_venv.py b/tox/_venv.py index eff932d..8666785 100644 --- a/tox/_venv.py +++ b/tox/_venv.py @@ -326,7 +326,10 @@ class VirtualEnv(object): action=action, extraenv=extraenv) def _getenv(self, extraenv={}): - env = os.environ.copy() + env = {} + for envname in self.envconfig.passenv: + if envname in os.environ: + env[envname] = os.environ[envname] setenv = self.envconfig.setenv if setenv: env.update(setenv) -- cgit v1.2.1