1
1
from __future__ import annotations
2
2
3
+ import logging
4
+ import re
3
5
from argparse import ArgumentParser
4
6
from collections import Counter
5
7
from dataclasses import dataclass
21
23
from tox .session .state import State
22
24
23
25
26
+ LOGGER = logging .getLogger (__name__ )
27
+
28
+
24
29
class CliEnv :
25
30
"""CLI tox env selection"""
26
31
@@ -88,6 +93,8 @@ def register_env_select_flags(
88
93
add_to .add_argument ("-m" , dest = "labels" , metavar = "label" , help = help_msg , default = [], type = str , nargs = "+" )
89
94
help_msg = "factors to evaluate"
90
95
add_to .add_argument ("-f" , dest = "factors" , metavar = "factor" , help = help_msg , default = [], type = str , nargs = "+" )
96
+ help_msg = "exclude all environments selected that match this regular expression"
97
+ add_to .add_argument ("--skip-env" , dest = "skip_env" , metavar = "re" , help = help_msg , default = "" , type = str )
91
98
return add_to
92
99
93
100
@@ -106,6 +113,7 @@ def __init__(self, state: State) -> None:
106
113
# to load the package environments of a run environments we need the run environment builder
107
114
# to load labels we need core + the run environment
108
115
self .on_empty_fallback_py = True
116
+ self ._warned_about : set [str ] = set () #: shared set of skipped environments that were already warned about
109
117
self ._state = state
110
118
self ._cli_envs : CliEnv | None = getattr (self ._state .conf .options , "env" , None )
111
119
self ._defined_envs_ : None | dict [str , _ToxEnvInfo ] = None
@@ -118,6 +126,8 @@ def __init__(self, state: State) -> None:
118
126
self ._provision : None | tuple [bool , str , MemoryLoader ] = None
119
127
120
128
self ._state .conf .core .add_config ("labels" , Dict [str , EnvList ], {}, "core labels" )
129
+ tox_env_filter_regex = getattr (state .conf .options , "skip_env" , "" ).strip ()
130
+ self ._filter_re = re .compile (tox_env_filter_regex ) if tox_env_filter_regex else None
121
131
122
132
def _collect_names (self ) -> Iterator [tuple [Iterable [str ], bool ]]:
123
133
""":return: sources of tox environments defined with name and if is marked as target to run"""
@@ -320,14 +330,17 @@ def iter(
320
330
321
331
:return: an iteration of tox environments
322
332
"""
323
- ignore_envs : set [str ] = set ()
324
333
for name , env_info in self ._defined_envs .items ():
325
334
if only_active and not env_info .is_active :
326
335
continue
327
336
if not package and not isinstance (env_info .env , RunToxEnv ):
328
337
continue
338
+ if self ._filter_re is not None and self ._filter_re .match (name ):
339
+ if name not in self ._warned_about :
340
+ self ._warned_about .add (name )
341
+ LOGGER .warning ("skip environment %s, matches filter %r" , name , self ._filter_re .pattern )
342
+ continue
329
343
yield name
330
- ignore_envs .add (name )
331
344
332
345
def ensure_only_run_env_is_active (self ) -> None :
333
346
envs , active = self ._defined_envs , self ._env_name_to_active ()
0 commit comments