Skip to content

Commit d448d82

Browse files
committed
Fix list/depends cmd creates package env as run env
This happens if you declare configuration for a packaging environment. Signed-off-by: Bernát Gábor <[email protected]> Signed-off-by: Bernát Gábor <[email protected]>
1 parent a44eca3 commit d448d82

File tree

15 files changed

+81
-60
lines changed

15 files changed

+81
-60
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ repos:
1212
- id: end-of-file-fixer
1313
- id: trailing-whitespace
1414
- repo: https://github.com/asottile/pyupgrade
15-
rev: v2.26.0
15+
rev: v2.27.0
1616
hooks:
1717
- id: pyupgrade
1818
args: ["--py36-plus"]

docs/changelog/2234.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix list/depends commands can create tox package environment as runtime environment and display an error message
2+
- by :user:`gaborbernat`.

src/tox/execute/local_sub_process/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ def interrupt(self) -> None:
6363
msg = "requested interrupt of %d from %d, activate in %.2f"
6464
logging.warning(msg, to_pid, host_pid, self.options.suicide_timeout)
6565
if self.wait(self.options.suicide_timeout) is None: # still alive -> INT
66-
if sys.platform != "win32": # on Windows everyone in the same process group, so they got the message
66+
# on Windows everyone in the same process group, so they got the message
67+
if sys.platform != "win32": # pragma: win32 cover
6768
msg = "send signal %s to %d from %d with timeout %.2f"
6869
logging.warning(msg, f"SIGINT({SIG_INTERRUPT})", to_pid, host_pid, self.options.interrupt_timeout)
6970
self._process.send_signal(SIG_INTERRUPT)

src/tox/session/cmd/depends.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,14 @@ def tox_add_option(parser: ToxParser) -> None:
1717

1818

1919
def depends(state: State) -> int:
20-
to_run_list = list(state.conf.env_list(everything=True))
20+
to_run_list = list(state.all_run_envs(with_skip=False))
2121
order, todo = run_order(state, to_run_list)
2222
print(f"Execution order: {', '.join(order)}")
2323

2424
deps: Dict[str, List[str]] = {k: [o for o in order if o in v] for k, v in todo.items()}
2525
deps["ALL"] = to_run_list
2626

2727
def _handle(at: int, env: str) -> None:
28-
if env not in order and env != "ALL": # skipped envs
29-
return
3028
print(" " * at, end="")
3129
print(env, end="")
3230
if env != "ALL":

src/tox/session/cmd/list_env.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,33 @@ def list_env(state: State) -> int:
1818
option = state.options
1919

2020
default = core["env_list"] # this should be something not affected by env-vars :-|
21-
ignore = {core["provision_tox_env"]}.union(default)
2221

23-
extra = [] if option.list_default_only else [e for e in state.conf.env_list(everything=True) if e not in ignore]
22+
extra = [] if option.list_default_only else [e for e in state.all_run_envs(with_skip=True) if e not in default]
2423

2524
if not option.list_no_description and default:
2625
print("default environments:")
2726
max_length = max((len(env) for env in (default.envs + extra)), default=0)
2827

2928
def report_env(name: str) -> None:
3029
if not option.list_no_description:
31-
text = state.tox_env(name).conf["description"]
30+
tox_env = state.tox_env(name)
31+
text = tox_env.conf["description"]
3232
if not text.strip():
3333
text = "[no description]"
3434
text = text.replace("\n", " ")
35-
msg = f"{e.ljust(max_length)} -> {text}".strip()
35+
msg = f"{env.ljust(max_length)} -> {text}".strip()
3636
else:
37-
msg = e
37+
msg = env
3838
print(msg)
3939

40-
for e in default:
41-
report_env(e)
40+
for env in default:
41+
report_env(env)
42+
4243
if not option.list_default_only and extra:
4344
if not option.list_no_description:
4445
if default:
4546
print("")
4647
print("additional environments:")
47-
for e in extra:
48-
report_env(e)
48+
for env in extra:
49+
report_env(env)
4950
return 0

src/tox/session/cmd/run/common.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from tox.session.cmd.run.single import ToxEnvRunResult, run_one
1818
from tox.session.state import State
1919
from tox.tox_env.api import ToxEnv
20-
from tox.tox_env.errors import Skip
2120
from tox.tox_env.runner import RunToxEnv
2221
from tox.util.graph import stable_topological_sort
2322
from tox.util.spinner import MISS_DURATION, Spinner
@@ -213,9 +212,9 @@ def execute(state: State, max_workers: Optional[int], has_spinner: bool, live: b
213212
done.wait()
214213
# workaround for https://bugs.python.org/issue45274
215214
lock = getattr(thread, "_tstate_lock", None)
216-
if lock is not None and lock.locked():
217-
lock.release()
218-
thread._stop() # type: ignore # we must call this private method to fix the thread state
215+
if lock is not None and lock.locked(): # pragma: no branch
216+
lock.release() # pragma: no cover
217+
thread._stop() # type: ignore # pragma: no cover # calling private method to fix thread state
219218
thread.join()
220219
finally:
221220
ordered_results: List[ToxEnvRunResult] = []
@@ -319,7 +318,7 @@ def _run(tox_env: RunToxEnv) -> ToxEnvRunResult:
319318
finally:
320319
try:
321320
# call teardown - configuration only environments for example could not be finished
322-
for _, tox_env in state.run_envs():
321+
for _, tox_env in state.created_run_envs():
323322
tox_env.teardown()
324323
finally:
325324
done.set()
@@ -368,10 +367,7 @@ def run_order(state: State, to_run: List[str]) -> Tuple[List[str], Dict[str, Set
368367
to_run_set = set(to_run)
369368
todo: Dict[str, Set[str]] = {}
370369
for env in to_run:
371-
try:
372-
run_env = state.tox_env(env)
373-
except Skip:
374-
continue
370+
run_env = state.tox_env(env)
375371
depends = set(cast(EnvList, run_env.conf["depends"]).envs)
376372
todo[env] = to_run_set & depends
377373
order = stable_topological_sort(todo)

src/tox/session/state.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from itertools import chain
12
from typing import TYPE_CHECKING, Dict, Iterator, Sequence, Set, Tuple, cast
23

34
from tox.config.main import Config
@@ -6,6 +7,7 @@
67
from tox.plugin import impl
78
from tox.report import HandledError, ToxHandler
89
from tox.tox_env.api import ToxEnvCreateArgs
10+
from tox.tox_env.errors import Skip
911
from tox.tox_env.package import PackageToxEnv
1012
from tox.tox_env.runner import RunToxEnv
1113

@@ -102,9 +104,26 @@ def _get_package_env(self, packager: str, name: str) -> PackageToxEnv:
102104
self._pkg_env[name] = packager, pkg_tox_env
103105
return pkg_tox_env
104106

105-
def run_envs(self) -> Iterator[Tuple[str, RunToxEnv]]:
107+
def created_run_envs(self) -> Iterator[Tuple[str, RunToxEnv]]:
106108
yield from self._run_env.items()
107109

110+
def all_run_envs(self, *, with_skip: bool = True) -> Iterator[str]:
111+
default_env_list = self.conf.core["env_list"]
112+
ignore = {self.conf.core["provision_tox_env"]}
113+
for env in chain(default_env_list.envs, self.conf.env_list(everything=True)):
114+
if env in ignore:
115+
continue
116+
ignore.add(env) # ignore self
117+
skip = False
118+
try:
119+
tox_env = self.tox_env(env)
120+
except Skip:
121+
skip = True
122+
tox_env = self.tox_env(env)
123+
ignore.update(i.name for i in tox_env.package_envs) # ignore package environments
124+
if not skip or with_skip:
125+
yield env
126+
108127

109128
@impl
110129
def tox_add_option(parser: "ToxParser") -> None:
@@ -114,6 +133,6 @@ def tox_add_option(parser: "ToxParser") -> None:
114133
"--runner",
115134
dest="default_runner",
116135
help="the tox run engine to use when not explicitly stated in tox env configuration",
117-
default=REGISTER.default_run_env,
118-
choices=list(REGISTER.run_envs),
136+
default=REGISTER.default_env_runner,
137+
choices=list(REGISTER.env_runners),
119138
)

src/tox/tox_env/python/runner.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def _register_package_conf(self) -> bool:
6666
if develop_mode:
6767
self.conf.add_constant(["package"], desc, "dev-legacy")
6868
else:
69-
self.conf.add_config(keys="package", of_type=str, default="sdist", desc=desc)
69+
self.conf.add_config(keys="package", of_type=str, default=self.default_pkg_type, desc=desc)
7070
pkg_type = self.pkg_type
7171

7272
if pkg_type == "skip":
@@ -109,6 +109,10 @@ def default_wheel_tag(conf: "Config", env_name: Optional[str]) -> str:
109109
)
110110
return True
111111

112+
@property
113+
def default_pkg_type(self) -> str:
114+
return "sdist"
115+
112116
@property
113117
def pkg_type(self) -> str:
114118
pkg_type: str = self.conf["package"]

src/tox/tox_env/python/virtual_env/runner.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@ def _default_package_tox_env_type(self) -> str:
2222
return "virtualenv-pep-517"
2323

2424
@property
25-
def has_package_by_default(self) -> bool:
25+
def default_pkg_type(self) -> str:
2626
tox_root: Path = self.core["tox_root"]
27-
return (
28-
getattr(self.options, "install_pkg", None) is not None
29-
or (tox_root / "pyproject.toml").exists()
30-
or (tox_root / "setup.py").exists()
31-
)
27+
if not (
28+
any((tox_root / i).exists() for i in ("pyproject.toml", "setup.py", "setup.cfg"))
29+
or getattr(self.options, "install_pkg", None) is not None
30+
):
31+
return "skip"
32+
return super().default_pkg_type
3233

3334

3435
@impl

src/tox/tox_env/register.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,17 @@ def add_package_env(self, of_type: Type[PackageToxEnv]) -> None:
4040
self._package_envs[of_type.id()] = of_type
4141

4242
@property
43-
def run_envs(self) -> Iterable[str]:
43+
def env_runners(self) -> Iterable[str]:
4444
""":returns: run environment types currently defined"""
4545
return self._run_envs.keys()
4646

4747
@property
48-
def default_run_env(self) -> str:
48+
def default_env_runner(self) -> str:
4949
""":returns: the default run environment type"""
5050
return self._default_run_env
5151

52-
@default_run_env.setter
53-
def default_run_env(self, value: str) -> None:
52+
@default_env_runner.setter
53+
def default_env_runner(self, value: str) -> None:
5454
"""
5555
Change the default run environment type.
5656

0 commit comments

Comments
 (0)