summaryrefslogtreecommitdiff
path: root/src/tox/tox_env
diff options
context:
space:
mode:
authorBernát Gábor <gaborjbernat@gmail.com>2022-12-04 10:21:20 -0800
committerGitHub <noreply@github.com>2022-12-04 10:21:20 -0800
commit279b2472abc473c1412f96a2694231a707f1326b (patch)
treed2f239d31de6a1ec689e969a37154c4fd77993e1 /src/tox/tox_env
parent932bb3e608694bee0017846b5e3f9856667ce476 (diff)
downloadtox-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.py30
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()