Skip to content

Commit 55af14a

Browse files
authored
Allow disabling plugins on a one-off (#3560)
Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
1 parent 57b5dc6 commit 55af14a

File tree

21 files changed

+171
-83
lines changed

21 files changed

+171
-83
lines changed

.github/workflows/check.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ jobs:
3030
- "3.10"
3131
- "3.9"
3232
os:
33-
- ubuntu-latest
34-
- windows-latest
35-
- macos-latest
33+
- ubuntu-24.04
34+
- windows-2025
35+
- macos-15
3636
steps:
3737
- uses: actions/checkout@v4
3838
with:
@@ -70,8 +70,8 @@ jobs:
7070
- docs
7171
- pkg_meta
7272
os:
73-
- ubuntu-latest
74-
- windows-latest
73+
- ubuntu-24.04
74+
- windows-2025
7575
exclude:
7676
- { os: windows-latest, tox_env: docs }
7777
steps:

.github/workflows/release.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ env:
99

1010
jobs:
1111
build:
12-
runs-on: ubuntu-latest
12+
runs-on: ubuntu-24.04
1313
steps:
1414
- uses: actions/checkout@v4
1515
with:
@@ -31,7 +31,7 @@ jobs:
3131
release:
3232
needs:
3333
- build
34-
runs-on: ubuntu-latest
34+
runs-on: ubuntu-24.04
3535
environment:
3636
name: release
3737
url: https://pypi.org/project/tox/${{ github.ref_name }}

docs/changelog/3468.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow disabling tox plugins via the ``TOX_DISABLED_EXTERNAL_PLUGINS`` environment variable - by :user:`gaborbernat`.

docs/plugins.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ installed. For example:
2727
2828
For more information, refer to :ref:`the user guide <auto-provisioning>`.
2929

30+
Plugins can be disabled via the ``TOX_DISABLED_EXTERNAL_PLUGINS`` environment variable. This variable can be set to a
31+
comma separated list of plugin names, e.g.:
32+
33+
```bash
34+
env TOX_DISABLED_EXTERNAL_PLUGINS=tox-uv,tox-extra tox --version
35+
```
36+
3037
Developing your own plugin
3138
--------------------------
3239

pyproject.toml

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[build-system]
22
build-backend = "hatchling.build"
33
requires = [
4-
"hatch-vcs>=0.4",
4+
"hatch-vcs>=0.5",
55
"hatchling>=1.27",
66
]
77

@@ -50,22 +50,17 @@ dynamic = [
5050
"version",
5151
]
5252
dependencies = [
53-
"cachetools>=5.5.1",
53+
"cachetools>=6.1",
5454
"chardet>=5.2",
5555
"colorama>=0.4.6",
56-
"filelock>=3.16.1",
57-
"packaging>=24.2",
58-
"platformdirs>=4.3.6",
59-
"pluggy>=1.5",
60-
"pyproject-api>=1.8",
56+
"filelock>=3.18",
57+
"packaging>=25",
58+
"platformdirs>=4.3.8",
59+
"pluggy>=1.6",
60+
"pyproject-api>=1.9.1",
6161
"tomli>=2.2.1; python_version<'3.11'",
62-
"typing-extensions>=4.12.2; python_version<'3.11'",
63-
"virtualenv>=20.31",
64-
]
65-
optional-dependencies.test = [
66-
"devpi-process>=1.0.2",
67-
"pytest>=8.3.4",
68-
"pytest-mock>=3.14",
62+
"typing-extensions>=4.14.1; python_version<'3.11'",
63+
"virtualenv>=20.31.2",
6964
]
7065
urls.Documentation = "https://tox.wiki"
7166
urls.Homepage = "http://tox.readthedocs.org"
@@ -83,35 +78,35 @@ dev = [
8378
test = [
8479
"build[virtualenv]>=1.2.2.post1",
8580
"covdefaults>=2.3",
86-
"coverage>=7.9.1",
81+
"coverage>=7.9.2",
8782
"detect-test-pollution>=1.2",
8883
"devpi-process>=1.0.2",
89-
"diff-cover>=9.2",
90-
"distlib>=0.3.9",
84+
"diff-cover>=9.6",
85+
"distlib>=0.4",
9186
"flaky>=3.8.1",
92-
"hatch-vcs>=0.4",
87+
"hatch-vcs>=0.5",
9388
"hatchling>=1.27",
94-
"psutil>=6.1.1",
95-
"pytest>=8.3.4",
96-
"pytest-cov>=5",
97-
"pytest-mock>=3.14",
98-
"pytest-xdist>=3.6.1",
89+
"psutil>=7",
90+
"pytest>=8.4.1",
91+
"pytest-cov>=6.2.1",
92+
"pytest-mock>=3.14.1",
93+
"pytest-xdist>=3.8",
9994
"re-assert>=1.1",
100-
"setuptools>=75.8",
101-
"time-machine>=2.15; implementation_name!='pypy'",
95+
"setuptools>=80.9",
96+
"time-machine>=2.16; implementation_name!='pypy'",
10297
"wheel>=0.45.1",
10398
]
10499
type = [
105-
"mypy==1.15",
106-
"types-cachetools>=5.5.0.20240820",
100+
"mypy==1.17",
101+
"types-cachetools>=6.1.0.20250717",
107102
"types-chardet>=5.0.4.6",
108103
{ include-group = "test" },
109104
]
110105
docs = [
111-
"furo>=2024.8.6",
112-
"sphinx>=8.1.3",
106+
"furo>=2025.7.19",
107+
"sphinx>=8.2.3",
113108
"sphinx-argparse-cli>=1.19",
114-
"sphinx-autodoc-typehints>=3.0.1",
109+
"sphinx-autodoc-typehints>=3.2",
115110
"sphinx-copybutton>=0.5.2",
116111
"sphinx-inline-tabs>=2023.4.21",
117112
"sphinxcontrib-towncrier>=0.2.1a0",
@@ -121,13 +116,13 @@ fix = [
121116
"pre-commit-uv>=4.1.4",
122117
]
123118
pkg-meta = [
124-
"check-wheel-contents>=0.6.1",
119+
"check-wheel-contents>=0.6.2",
125120
"twine>=6.1",
126-
"uv>=0.5.29",
121+
"uv>=0.8",
127122
]
128123
release = [
129124
"gitpython>=3.1.44",
130-
"packaging>=24.2",
125+
"packaging>=25",
131126
"towncrier>=24.8",
132127
]
133128

@@ -201,8 +196,13 @@ max_supported_python = "3.14"
201196
testpaths = [
202197
"tests",
203198
]
204-
addopts = "--tb=auto -ra --showlocals --no-success-flaky-report"
205-
# Keep temporary directories only for failed or errored tests.
199+
addopts = "--no-success-flaky-report"
200+
verbosity_assertions = 2
201+
filterwarnings = [
202+
"error",
203+
"ignore:unclosed database in <sqlite3.Connection object at:ResourceWarning",
204+
"ignore:unclosed file <_io.TextIOWrapper:ResourceWarning",
205+
]
206206
tmp_path_retention_policy = "failed"
207207

208208
[tool.coverage]

src/tox/config/cli/parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def add_argument_group(self, *args: Any, **kwargs: Any) -> Any:
263263

264264
def add_mutually_exclusive_group(**e_kwargs: Any) -> Any:
265265
def add_argument(*a_args: str, of_type: type[Any] | None = None, **a_kwargs: Any) -> Action:
266-
res_args: Action = prev_add_arg(*a_args, **a_kwargs) # type: ignore[has-type]
266+
res_args: Action = prev_add_arg(*a_args, **a_kwargs)
267267
arguments.append((a_args, of_type, a_kwargs))
268268
return res_args
269269

src/tox/config/loader/api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,13 @@ def load(
151151
converted_override = _STR_CONVERT.to(override.value, of_type, factory)
152152
if override.append and converted is not None:
153153
if isinstance(converted, list) and isinstance(converted_override, list):
154-
converted += converted_override
154+
converted += converted_override # type: ignore[assignment]
155155
elif isinstance(converted, dict) and isinstance(converted_override, dict):
156156
converted.update(converted_override)
157157
elif isinstance(converted, SetEnv) and isinstance(converted_override, SetEnv):
158158
converted.update(converted_override, override=True)
159159
elif isinstance(converted, PythonDeps) and isinstance(converted_override, PythonDeps):
160-
converted += converted_override
160+
converted += converted_override # type: ignore[operator]
161161
else:
162162
msg = "Only able to append to lists and dicts"
163163
raise ValueError(msg)

src/tox/config/loader/convert.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def to(self, raw: T, of_type: type[V], factory: Factory[V]) -> V: # noqa: PLR09
4747
return list(self.to_list(raw, of_type=of_type)) # type: ignore[return-value]
4848
if isinstance(raw, of_type): # already target type no need to transform it
4949
# do it this late to allow normalization - e.g. string strip
50-
return raw # type: ignore[no-any-return]
50+
return raw
5151
if factory:
5252
return factory(raw)
5353
return of_type(raw) # type: ignore[no-any-return]

src/tox/plugin/manager.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from __future__ import annotations
44

5+
import os
56
from typing import TYPE_CHECKING, Any
67

78
import pluggy
@@ -49,7 +50,7 @@ def _register_plugins(self, inline: ModuleType | None) -> None:
4950

5051
if inline is not None:
5152
self.manager.register(inline)
52-
self.manager.load_setuptools_entrypoints(NAME)
53+
self._load_external_plugins()
5354
internal_plugins = (
5455
loader_api,
5556
provision,
@@ -74,6 +75,11 @@ def _register_plugins(self, inline: ModuleType | None) -> None:
7475
self.manager.register(state)
7576
self.manager.check_pending()
7677

78+
def _load_external_plugins(self) -> None:
79+
for name in os.environ.get("TOX_DISABLED_EXTERNAL_PLUGINS", "").split(","):
80+
self.manager.set_blocked(name)
81+
self.manager.load_setuptools_entrypoints(NAME)
82+
7783
def tox_add_option(self, parser: ToxParser) -> None:
7884
self.manager.hook.tox_add_option(parser=parser)
7985

src/tox/pytest.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ def _load_inline(path: Path) -> ModuleType | None: # register only on first run
8282
@contextmanager
8383
def check_os_environ() -> Iterator[None]:
8484
old = os.environ.copy()
85-
to_clean = {k: os.environ.pop(k, None) for k in (ENV_VAR_KEY, "TOX_WORK_DIR", "PYTHONPATH", "COV_CORE_CONTEXT")}
85+
to_clean = {
86+
k: os.environ.pop(k, None)
87+
for k in (ENV_VAR_KEY, "TOX_WORK_DIR", "PYTHONPATH", "COV_CORE_CONTEXT", "TOX_DISABLED_EXTERNAL_PLUGINS")
88+
}
8689

8790
yield
8891

@@ -93,6 +96,7 @@ def check_os_environ() -> Iterator[None]:
9396
new = os.environ
9497
extra = {k: new[k] for k in set(new) - set(old)}
9598
extra.pop("PLAT", None)
99+
extra.pop("TOX_DISABLED_EXTERNAL_PLUGINS", None)
96100
miss = {k: old[k] for k in set(old) - set(new)}
97101
diff = {
98102
f"{k} = {old[k]} vs {new[k]}" for k in set(old) & set(new) if old[k] != new[k] and not k.startswith("PYTEST_")

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy