Skip to content

Commit 4cb6d03

Browse files
committed
Use _TOX_PARALLEL_ENV environment variable to control the behavior
...but keep the TOX_PARALLEL_ENV variable for others to consume. The problem with using environment variables to let tox know it's being run as a parallel worker is the following: Either you don't pass the environment variable, but the test frameworks and test suites are unaware that tox is running in parallel. This makes it hard for cases like pytest-django: tox-dev#1139 Or you pass the environment variable, but it makes tox invoked within tox think it is a parallel worker even when it isn't. This makes it hard to test various tox plugins that invoke tox in their integration test suite: Fixes tox-dev#1444 By introducing two variables we can use one ("private", _TOX_PARALLEL_ENV) to control the behavior of tox (and don't pass it) and another ("public", TOX_PARALLEL_ENV) to let the tests and test frameworks know tox is running in parallel (and pass it by default).
1 parent 1883946 commit 4cb6d03

File tree

8 files changed

+33
-16
lines changed

8 files changed

+33
-16
lines changed

docs/changelog/1444.bugfix.rst

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fix nested tox execution in the parallel mode by separating the environment
2+
variable that let's tox know it is invoked in the parallel mode
3+
(``_TOX_PARALLEL_ENV``) from the variable that informs the tests that tox is
4+
running in parallel mode (``TOX_PARALLEL_ENV``).
5+
— by :user:`hroncok`

src/tox/_pytestplugin.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
import tox.session
1818
from tox import venv
1919
from tox.config import parseconfig
20-
from tox.config.parallel import ENV_VAR_KEY as PARALLEL_ENV_VAR_KEY
20+
from tox.config.parallel import ENV_VAR_KEY_PRIVATE as PARALLEL_ENV_VAR_KEY_PRIVATE
21+
from tox.config.parallel import ENV_VAR_KEY_PUBLIC as PARALLEL_ENV_VAR_KEY_PUBLIC
2122
from tox.reporter import update_default_reporter
2223
from tox.venv import CreationConfig, VirtualEnv, getdigest
2324

@@ -66,7 +67,12 @@ def check_os_environ_stable():
6667

6768
to_clean = {
6869
k: os.environ.pop(k, None)
69-
for k in {PARALLEL_ENV_VAR_KEY, str("TOX_WORK_DIR"), str("PYTHONPATH")}
70+
for k in {
71+
PARALLEL_ENV_VAR_KEY_PRIVATE,
72+
PARALLEL_ENV_VAR_KEY_PUBLIC,
73+
str("TOX_WORK_DIR"),
74+
str("PYTHONPATH"),
75+
}
7076
}
7177

7278
yield

src/tox/config/__init__.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
from tox.util.path import ensure_empty_dir
3636
from tox.util.stdlib import importlib_metadata
3737

38-
from .parallel import ENV_VAR_KEY as PARALLEL_ENV_VAR_KEY
38+
from .parallel import ENV_VAR_KEY_PRIVATE as PARALLEL_ENV_VAR_KEY_PRIVATE
39+
from .parallel import ENV_VAR_KEY_PUBLIC as PARALLEL_ENV_VAR_KEY_PUBLIC
3940
from .parallel import add_parallel_config, add_parallel_flags
4041
from .reporter import add_verbosity_commands
4142

@@ -670,7 +671,7 @@ def passenv(testenv_config, value):
670671
"LD_LIBRARY_PATH",
671672
"TOX_WORK_DIR",
672673
str(REPORTER_TIMESTAMP_ON_ENV),
673-
str(PARALLEL_ENV_VAR_KEY),
674+
str(PARALLEL_ENV_VAR_KEY_PUBLIC),
674675
}
675676

676677
# read in global passenv settings
@@ -1030,7 +1031,7 @@ def line_of_default_to_zero(section, name=None):
10301031
config.sdistsrc = reader.getpath("sdistsrc", None)
10311032
config.setupdir = reader.getpath("setupdir", "{toxinidir}")
10321033
config.logdir = config.toxworkdir.join("log")
1033-
within_parallel = PARALLEL_ENV_VAR_KEY in os.environ
1034+
within_parallel = PARALLEL_ENV_VAR_KEY_PRIVATE in os.environ
10341035
if not within_parallel and not WITHIN_PROVISION:
10351036
ensure_empty_dir(config.logdir)
10361037

@@ -1282,7 +1283,7 @@ def _getenvdata(self, reader, config):
12821283
all_envs = self._getallenvs(reader)
12831284
else:
12841285
candidates = (
1285-
(os.environ.get(PARALLEL_ENV_VAR_KEY), True),
1286+
(os.environ.get(PARALLEL_ENV_VAR_KEY_PRIVATE), True),
12861287
(from_option, True),
12871288
(from_environ, True),
12881289
("py" if self.config.option.devenv is not None else None, False),

src/tox/config/parallel.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
from argparse import ArgumentTypeError
44

5-
ENV_VAR_KEY = "TOX_PARALLEL_ENV"
5+
ENV_VAR_KEY_PUBLIC = "TOX_PARALLEL_ENV"
6+
ENV_VAR_KEY_PRIVATE = "_TOX_PARALLEL_ENV"
67
OFF_VALUE = 0
78
DEFAULT_PARALLEL = OFF_VALUE
89

src/tox/session/__init__.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from tox import reporter
2121
from tox.action import Action
2222
from tox.config import parseconfig
23-
from tox.config.parallel import ENV_VAR_KEY as PARALLEL_ENV_VAR_KEY
23+
from tox.config.parallel import ENV_VAR_KEY_PRIVATE as PARALLEL_ENV_VAR_KEY_PRIVATE
2424
from tox.config.parallel import OFF_VALUE as PARALLEL_OFF
2525
from tox.logs.result import ResultLog
2626
from tox.reporter import update_default_reporter
@@ -212,7 +212,7 @@ def subcommand_test(self):
212212
if self.config.option.sdistonly:
213213
return
214214

215-
within_parallel = PARALLEL_ENV_VAR_KEY in os.environ
215+
within_parallel = PARALLEL_ENV_VAR_KEY_PRIVATE in os.environ
216216
try:
217217
if not within_parallel and self.config.option.parallel != PARALLEL_OFF:
218218
run_parallel(self.config, self.venv_dict)
@@ -241,7 +241,7 @@ def _load_parallel_env_report(tox_env):
241241
return data
242242

243243
def _summary(self):
244-
is_parallel_child = PARALLEL_ENV_VAR_KEY in os.environ
244+
is_parallel_child = PARALLEL_ENV_VAR_KEY_PRIVATE in os.environ
245245
if not is_parallel_child:
246246
reporter.separator("_", "summary", reporter.Verbosity.QUIET)
247247
exit_code = 0

src/tox/session/commands/run/parallel.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
from threading import Event, Semaphore, Thread
55

66
from tox import reporter
7-
from tox.config.parallel import ENV_VAR_KEY as PARALLEL_ENV_VAR_KEY
7+
from tox.config.parallel import ENV_VAR_KEY_PRIVATE as PARALLEL_ENV_VAR_KEY_PRIVATE
8+
from tox.config.parallel import ENV_VAR_KEY_PUBLIC as PARALLEL_ENV_VAR_KEY_PUBLIC
89
from tox.exception import InvocationError
910
from tox.util.main import MAIN_FILE
1011
from tox.util.spinner import Spinner
@@ -37,7 +38,8 @@ def run_in_thread(tox_env, os_env, processes):
3738
env_name = tox_env.envconfig.envname
3839
status = "skipped tests" if config.option.notest else None
3940
try:
40-
os_env[str(PARALLEL_ENV_VAR_KEY)] = str(env_name)
41+
os_env[str(PARALLEL_ENV_VAR_KEY_PRIVATE)] = str(env_name)
42+
os_env[str(PARALLEL_ENV_VAR_KEY_PUBLIC)] = str(env_name)
4143
args_sub = list(args)
4244
if hasattr(tox_env, "package"):
4345
args_sub.insert(position, str(tox_env.package))

src/tox/venv.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import tox
1212
from tox import reporter
1313
from tox.action import Action
14-
from tox.config.parallel import ENV_VAR_KEY as PARALLEL_ENV_VAR_KEY
14+
from tox.config.parallel import ENV_VAR_KEY_PRIVATE as PARALLEL_ENV_VAR_KEY_PRIVATE
1515
from tox.constants import INFO, PARALLEL_RESULT_JSON_PREFIX, PARALLEL_RESULT_JSON_SUFFIX
1616
from tox.package.local import resolve_package
1717
from tox.util.lock import get_unique_file
@@ -693,7 +693,7 @@ def tox_testenv_create(venv, action):
693693

694694

695695
def cleanup_for_venv(venv):
696-
within_parallel = PARALLEL_ENV_VAR_KEY in os.environ
696+
within_parallel = PARALLEL_ENV_VAR_KEY_PRIVATE in os.environ
697697
# if the directory exists and it doesn't look like a virtualenv, produce
698698
# an error
699699
if venv.path.exists():

tests/unit/config/test_config.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
is_section_substitution,
2020
parseconfig,
2121
)
22-
from tox.config.parallel import ENV_VAR_KEY as PARALLEL_ENV_VAR_KEY
22+
from tox.config.parallel import ENV_VAR_KEY_PRIVATE as PARALLEL_ENV_VAR_KEY_PRIVATE
23+
from tox.config.parallel import ENV_VAR_KEY_PUBLIC as PARALLEL_ENV_VAR_KEY_PUBLIC
2324

2425

2526
class TestVenvConfig:
@@ -1073,7 +1074,8 @@ def test_passenv_as_multiline_list(self, newconfig, monkeypatch, plat):
10731074
assert "LANG" in envconfig.passenv
10741075
assert "LANGUAGE" in envconfig.passenv
10751076
assert "LD_LIBRARY_PATH" in envconfig.passenv
1076-
assert PARALLEL_ENV_VAR_KEY in envconfig.passenv
1077+
assert PARALLEL_ENV_VAR_KEY_PUBLIC in envconfig.passenv
1078+
assert PARALLEL_ENV_VAR_KEY_PRIVATE not in envconfig.passenv
10771079
assert "A123A" in envconfig.passenv
10781080
assert "A123B" in envconfig.passenv
10791081

0 commit comments

Comments
 (0)