diff --git a/README.rst b/README.rst index 0f49390..560a5b7 100644 --- a/README.rst +++ b/README.rst @@ -208,15 +208,13 @@ forcefully killing it before it finished, uninstalling the plugin, and running ``tox``), you will get undefined results (such as installing packages from PyPI into your current environment). -Environment variables are not passed by default -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Environment variables are passed by default +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Although the plugin name suggests that current environment is used for tests, -it means the Python environment, not Shell. -If you want the tests to see environment variables of the calling process, -use the ``TOX_TESTENV_PASSENV`` environment variable. -Read `the documentation for passing environment variables to tox -`_. +Since 0.0.9, all Shell environment variables are passed by default when using +this plugin. The `passenv` tox configuration is set to `*`. +Read `the documentation for more information about passing environment variables to tox +`_. tox provisioning ~~~~~~~~~~~~~~~~ diff --git a/src/tox_current_env/hooks3.py b/src/tox_current_env/hooks3.py index 33b0a9d..eca79f8 100644 --- a/src/tox_current_env/hooks3.py +++ b/src/tox_current_env/hooks3.py @@ -85,6 +85,11 @@ def tox_configure(config): for testenv in config.envconfigs: config.envconfigs[testenv].usedevelop = False _allow_all_externals(config.envconfigs[testenv]) + # Because tox 4 no longer reads $TOX_TESTENV_PASSENV, + # this plugin always passes all environment variables by default, + # even on tox 3. + # Unfortunately at this point the set contains actual values, not globs: + config.envconfigs[testenv].passenv |= set(os.environ.keys()) # When printing dependencies/extras we don't run any commands. # Unfortunately tox_runtest_pre/tox_runtest_post hooks don't use firstresult=True, diff --git a/src/tox_current_env/hooks4.py b/src/tox_current_env/hooks4.py index 972cf03..40a263b 100644 --- a/src/tox_current_env/hooks4.py +++ b/src/tox_current_env/hooks4.py @@ -87,11 +87,11 @@ def tox_add_core_config(core_conf, state): def tox_add_env_config(env_conf, state): opt = state.conf.options # This allows all external commands. - # All of them are extenal for us. - # passenv is here because `TOX_TESTENV_PASSENV` - # no longer works in tox 4. + # All of them are external for us. + # Because tox 4 no longer reads $TOX_TESTENV_PASSENV, + # this plugin always passes all environment variables by default. if opt.current_env: - allow_external_cmds = MemoryLoader(allowlist_externals=["*"], passenv=["*"]) + allow_external_cmds = MemoryLoader(allowlist_externals=["*"], pass_env=["*"]) env_conf.loaders.insert(0, allow_external_cmds) # For print-deps-to and print-extras-to, use empty # list of commands so the tox does nothing. diff --git a/tests/test_integration_tox3.py b/tests/test_integration_tox3.py index 406c795..0f5eb35 100644 --- a/tests/test_integration_tox3.py +++ b/tests/test_integration_tox3.py @@ -564,3 +564,17 @@ def test_self_is_installed_with_regular_tox(projdir, usedevelop): config["testenv"]["usedevelop"] = str(usedevelop) result = tox("-e", NATIVE_TOXENV, quiet=False) assert "test==0.0.0" in result.stdout or "test @ file://" in result.stdout + + +@pytest.mark.parametrize("passenv", [None, "different list", "__var", "*"]) +def test_passenv(projdir, passenv): + with modify_config(projdir / "tox.ini") as config: + config["testenv"]["commands"] = """python -c 'import os; print(os.getenv("__var"))'""" + if passenv is not None: + existing = config["testenv"].get("passenv", "") + " " + config["testenv"]["passenv"] = existing + passenv + env = {"__var": "assertme"} + result = tox("-e", NATIVE_TOXENV, "--current-env", env=env, quiet=False) + assert result.returncode == 0 + assert "\nassertme\n" in result.stdout + assert "\nNone\n" not in result.stdout diff --git a/tests/test_integration_tox4.py b/tests/test_integration_tox4.py index 1aee1e4..3ab9fbd 100644 --- a/tests/test_integration_tox4.py +++ b/tests/test_integration_tox4.py @@ -395,3 +395,30 @@ def test_self_is_installed_with_regular_tox(projdir, usedevelop): assert "test-0.0.0" in result.stdout if usedevelop: assert "test-0.0.0-0.editable" in result.stdout + + +@pytest.mark.parametrize("passenv", [None, "different list", "__var", "*"]) +def test_passenv(projdir, passenv): + with modify_config(projdir / "tox.ini") as config: + config["testenv"]["commands"] = """python -c 'import os; print(os.getenv("__var"))'""" + if passenv is not None: + existing = config["testenv"].get("passenv", "") + " " + config["testenv"]["passenv"] = existing + passenv + env = {"__var": "assertme"} + result = tox("-e", NATIVE_TOXENV, "--current-env", env=env, quiet=False) + assert result.returncode == 0 + assert "\nassertme\n" in result.stdout + assert "\nNone\n" not in result.stdout + + +@pytest.mark.parametrize("pass_env", [None, "different\nlist", "__var", "*"]) +def test_pass_env(projdir, pass_env): + with modify_config(projdir / "tox.ini") as config: + config["testenv"]["commands"] = """python -c 'import os; print(os.getenv("__var"))'""" + if pass_env is not None: + config["testenv"]["pass_env"] = pass_env + env = {"__var": "assertme"} + result = tox("-e", NATIVE_TOXENV, "--current-env", env=env, quiet=False) + assert result.returncode == 0 + assert "\nassertme\n" in result.stdout + assert "\nNone\n" not in result.stdout diff --git a/tests/utils.py b/tests/utils.py index ea180f4..377b2b3 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -39,7 +39,7 @@ def tox(*args, quiet=True, **kwargs): q = ("-q",) if quiet else () env = dict(os.environ) env.pop("TOX_WORK_DIR", None) - kwargs.setdefault("env", env) + kwargs["env"] = {**env, **kwargs.get("env", {})} try: print("current", os.getcwd(), "running in", kwargs["cwd"]) cp = subprocess.run((sys.executable, "-m", "tox") + q + args, **kwargs)