Skip to content

Commit 593017f

Browse files
authoredFeb 15, 2023
Add support for NOXPYTHON, NOXEXTRAPYTHON and NOXFORCEPYTHON (#688)
1 parent 36202af commit 593017f

File tree

5 files changed

+109
-32
lines changed

5 files changed

+109
-32
lines changed
 

‎docs/conf.py

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"sphinx.ext.autodoc",
4343
"sphinx.ext.napoleon",
4444
"myst_parser",
45+
"sphinx_tabs.tabs",
4546
]
4647

4748
# Add any paths that contain templates here, relative to this directory.
@@ -316,3 +317,6 @@
316317

317318
# If true, do not generate a @detailmenu in the "Top" node's menu.
318319
# texinfo_no_detailmenu = False
320+
321+
# Disable tab closing by selecting the open tab
322+
sphinx_tabs_disable_tab_closing = True

‎docs/usage.rst

+57-19
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,35 @@ Specifying one or more sessions
5252

5353
By default Nox will run all sessions defined in the Noxfile. However, you can choose to run a particular set of them using ``--session``, ``-s``, or ``-e``:
5454

55-
.. code-block:: console
55+
.. tabs::
5656

57-
nox --session tests
58-
nox -s lint tests
59-
nox -e lint
57+
.. code-tab:: console CLI options
6058

61-
You can also use the ``NOXSESSION`` environment variable:
59+
nox --session tests
60+
nox -s lint tests
61+
nox -e lint
6262

63-
.. code-block:: console
63+
.. code-tab:: console Environment variables
6464

65-
NOXSESSION=lint nox
66-
NOXSESSION=lint,tests nox
65+
NOXSESSION=tests nox
66+
NOXSESSION=lint nox
67+
NOXSESSION=lint,tests nox
6768

6869
Nox will run these sessions in the same order they are specified.
6970

7071
If you have a :ref:`configured session's virtualenv <virtualenv config>`, you can choose to run only sessions with given Python versions:
7172

72-
.. code-block:: console
73+
.. tabs::
74+
75+
.. code-tab:: console CLI options
76+
77+
nox --python 3.8
78+
nox -p 3.7 3.8
79+
80+
.. code-tab:: console Environment variables
7381

74-
nox --python 3.8
75-
nox -p 3.7 3.8
82+
NOXPYTHON=3.8 nox
83+
NOXPYTHON=3.7,3.8 nox
7684

7785
You can also use `pytest-style keywords`_ using ``-k`` or ``--keywords``, and
7886
tags using ``-t`` or ``--tags`` to filter test sessions:
@@ -184,25 +192,55 @@ Running additional Python versions
184192

185193
In addition to Nox supporting executing single sessions, it also supports running Python versions that aren't specified using ``--extra-pythons``.
186194

187-
.. code-block:: console
195+
.. tabs::
196+
197+
.. code-tab:: console CLI options
198+
199+
nox --extra-pythons 3.8 3.9 3.10
200+
201+
.. code-tab:: console Environment variables
202+
203+
NOXEXTRAPYTHON=3.8,3.9,3.10 nox
188204

189-
nox --extra-pythons 3.8 3.9 3.10
190205

191206
This will, in addition to specified Python versions in the Noxfile, also create sessions for the specified versions.
192207

193-
This option can be combined with ``--python`` to replace, instead of appending, the Python interpreter for a given session::
208+
This option can be combined with ``--python`` to replace, instead of appending, the Python interpreter for a given session:
194209

195-
nox --python 3.11 --extra-python 3.11 -s lint
210+
.. tabs::
196211

197-
Instead of passing both options, you can use the ``--force-python`` shorthand::
212+
.. code-tab:: console CLI options
198213

199-
nox --force-python 3.11 -s lint
214+
nox --python 3.11 --extra-python 3.11 -s lint
215+
216+
.. code-tab:: console Environment variables
217+
218+
NOXPYTHON=3.11 NOXEXTRAPYTHON=3.11 NOXSESSION=lint nox
219+
220+
Instead of passing both options, you can use the ``--force-python`` shorthand:
221+
222+
.. tabs::
223+
224+
.. code-tab:: console CLI options
225+
226+
nox --force-python 3.11 -s lint
227+
228+
.. code-tab:: console Environment variables
229+
230+
NOXFORCEPYTHON=3.11 NOXSESSION=lint nox
200231

201232
Also, you can specify ``python`` in place of a specific version. This will run the session
202-
using the ``python`` specified for the current ``PATH``::
233+
using the ``python`` specified for the current ``PATH``:
234+
235+
.. tabs::
236+
237+
.. code-tab:: console CLI options
238+
239+
nox --force-python python -s lint
203240

204-
nox --force-python python -s lint
241+
.. code-tab:: console Environment variables
205242

243+
NOXFORCEPYTHON=python NOXSESSION=lint nox
206244

207245
.. _opt-stop-on-first-error:
208246

‎nox/_options.py

+20-7
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import functools
1919
import os
2020
import sys
21-
from typing import Any, Sequence
21+
from typing import Any, Callable, Sequence
2222

2323
from nox import _option_set
2424
from nox.tasks import discover_manifest, filter_manifest, load_nox_module
@@ -142,11 +142,21 @@ def _envdir_merge_func(
142142
return command_args.envdir or noxfile_args.envdir or ".nox"
143143

144144

145-
def _sessions_default() -> list[str] | None:
146-
"""Looks at the NOXSESSION env var to set the default value for sessions."""
147-
nox_env = os.environ.get("NOXSESSION")
148-
env_sessions = nox_env.split(",") if nox_env else None
149-
return env_sessions
145+
def default_env_var_list_factory(env_var: str) -> Callable[[], list[str] | None]:
146+
"""Looks at the env var to set the default value for a list of env vars.
147+
148+
Args:
149+
env_var (str): The name of the environment variable to look up.
150+
151+
Returns:
152+
A callback that retrieves a list from a comma-delimited environment variable.
153+
"""
154+
155+
def _default_list() -> list[str] | None:
156+
env_value = os.environ.get(env_var)
157+
return env_value.split(",") if env_value else None
158+
159+
return _default_list
150160

151161

152162
def _color_finalizer(value: bool, args: argparse.Namespace) -> bool:
@@ -264,7 +274,7 @@ def _session_completer(
264274
noxfile=True,
265275
merge_func=functools.partial(_sessions_and_keywords_merge_func, "sessions"),
266276
nargs="*",
267-
default=_sessions_default,
277+
default=default_env_var_list_factory("NOXSESSION"),
268278
help="Which sessions to run. By default, all sessions will run.",
269279
completer=_session_completer,
270280
),
@@ -276,6 +286,7 @@ def _session_completer(
276286
group=options.groups["python"],
277287
noxfile=True,
278288
nargs="*",
289+
default=default_env_var_list_factory("NOXPYTHON"),
279290
help="Only run sessions that use the given python interpreter versions.",
280291
),
281292
_option_set.Option(
@@ -406,6 +417,7 @@ def _session_completer(
406417
"--extra-python",
407418
group=options.groups["python"],
408419
nargs="*",
420+
default=default_env_var_list_factory("NOXEXTRAPYTHON"),
409421
help="Additionally, run sessions using the given python interpreter versions.",
410422
),
411423
_option_set.Option(
@@ -414,6 +426,7 @@ def _session_completer(
414426
"--force-python",
415427
group=options.groups["python"],
416428
nargs="*",
429+
default=default_env_var_list_factory("NOXFORCEPYTHON"),
417430
help=(
418431
"Run sessions with the given interpreters instead of those listed in the"
419432
" Noxfile. This is a shorthand for ``--python=X.Y --extra-python=X.Y``."

‎requirements-test.txt

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ pytest>=6.0
44
pytest-cov
55
sphinx>=3.0
66
sphinx-autobuild
7+
sphinx-tabs
78
witchhazel

‎tests/test_main.py

+27-6
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,30 @@ def test_main_explicit_sessions_with_spaces_in_names(monkeypatch):
217217

218218

219219
@pytest.mark.parametrize(
220-
"env,sessions", [("foo", ["foo"]), ("foo,bar", ["foo", "bar"])]
220+
"var,option,env,values",
221+
[
222+
("NOXSESSION", "sessions", "foo", ["foo"]),
223+
("NOXSESSION", "sessions", "foo,bar", ["foo", "bar"]),
224+
("NOXPYTHON", "pythons", "3.9", ["3.9"]),
225+
("NOXPYTHON", "pythons", "3.9,3.10", ["3.9", "3.10"]),
226+
("NOXEXTRAPYTHON", "extra_pythons", "3.9", ["3.9"]),
227+
("NOXEXTRAPYTHON", "extra_pythons", "3.9,3.10", ["3.9", "3.10"]),
228+
("NOXFORCEPYTHON", "force_pythons", "3.9", ["3.9"]),
229+
("NOXFORCEPYTHON", "force_pythons", "3.9,3.10", ["3.9", "3.10"]),
230+
],
231+
ids=[
232+
"single_session",
233+
"multiple_sessions",
234+
"single_python",
235+
"multiple_pythons",
236+
"single_extra_python",
237+
"multiple_extra_pythons",
238+
"single_force_python",
239+
"multiple_force_pythons",
240+
],
221241
)
222-
def test_main_session_from_nox_env_var(monkeypatch, env, sessions):
223-
monkeypatch.setenv("NOXSESSION", env)
242+
def test_main_list_option_from_nox_env_var(monkeypatch, var, option, env, values):
243+
monkeypatch.setenv(var, env)
224244
monkeypatch.setattr(sys, "argv", [sys.executable])
225245

226246
with mock.patch("nox.workflow.execute") as execute:
@@ -234,9 +254,10 @@ def test_main_session_from_nox_env_var(monkeypatch, env, sessions):
234254

235255
# Verify that the sessions from the env var are listed in the config.
236256
config = execute.call_args[1]["global_config"]
237-
assert len(config.sessions) == len(sessions)
238-
for session in sessions:
239-
assert session in config.sessions
257+
config_values = getattr(config, option)
258+
assert len(config_values) == len(values)
259+
for value in values:
260+
assert value in config_values
240261

241262

242263
def test_main_positional_args(capsys, monkeypatch):

0 commit comments

Comments
 (0)
Please sign in to comment.