diff options
author | Bernát Gábor <gaborjbernat@gmail.com> | 2022-12-04 10:21:20 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-04 10:21:20 -0800 |
commit | 279b2472abc473c1412f96a2694231a707f1326b (patch) | |
tree | d2f239d31de6a1ec689e969a37154c4fd77993e1 /src/tox/tox_env | |
parent | 932bb3e608694bee0017846b5e3f9856667ce476 (diff) | |
download | tox-git-279b2472abc473c1412f96a2694231a707f1326b.tar.gz |
Ensure only one tox environment operates on a packaging environment (#2588)
Resolves https://github.com/tox-dev/tox/issues/2564
Diffstat (limited to 'src/tox/tox_env')
-rw-r--r-- | src/tox/tox_env/package.py | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/src/tox/tox_env/package.py b/src/tox/tox_env/package.py index a697e19f..cbdcbadc 100644 --- a/src/tox/tox_env/package.py +++ b/src/tox/tox_env/package.py @@ -5,8 +5,9 @@ from __future__ import annotations from abc import ABC, abstractmethod from pathlib import Path -from threading import Lock -from typing import TYPE_CHECKING, Generator, Iterator, cast +from threading import RLock +from types import MethodType +from typing import TYPE_CHECKING, Any, Callable, Generator, Iterator, cast from tox.config.main import Config from tox.config.sets import EnvConfigSet @@ -30,11 +31,26 @@ class PathPackage(Package): return str(self.path) +def _lock_method(lock: RLock, meth: Callable[..., Any]) -> Callable[..., Any]: + def _func(*args: Any, **kwargs: Any) -> Any: + with lock: + return meth(*args, **kwargs) + + return _func + + class PackageToxEnv(ToxEnv, ABC): def __init__(self, create_args: ToxEnvCreateArgs) -> None: + self._lock = RLock() super().__init__(create_args) self._envs: set[str] = set() - self._lock = Lock() + + def __getattribute__(self, name: str) -> Any: + # the packaging class might be used by multiple environments in parallel, hold a lock for operations on it + obj = object.__getattribute__(self, name) + if isinstance(obj, MethodType): + obj = _lock_method(self._lock, obj) + return obj def register_config(self) -> None: super().register_config() @@ -62,13 +78,11 @@ class PackageToxEnv(ToxEnv, ABC): yield from () # empty generator by default def mark_active_run_env(self, run_env: RunToxEnv) -> None: - with self._lock: - self._envs.add(run_env.conf.name) + self._envs.add(run_env.conf.name) def teardown_env(self, conf: EnvConfigSet) -> None: - with self._lock: - self._envs.remove(conf.name) - has_envs = bool(self._envs) + self._envs.remove(conf.name) + has_envs = bool(self._envs) if not has_envs: self._teardown() |