Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for NOXPYTHON, NOXEXTRAPYTHON and NOXFORCEPYTHON #688

Merged
merged 7 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/PyCQA/isort
rev: 5.10.1
rev: 5.12.0
edgarrmondragon marked this conversation as resolved.
Show resolved Hide resolved
hooks:
- id: isort
args: ["-a", "from __future__ import annotations"]
Expand Down
4 changes: 4 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
"myst_parser",
"sphinx_tabs.tabs",
]

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

# If true, do not generate a @detailmenu in the "Top" node's menu.
# texinfo_no_detailmenu = False

# Disable tab closing by selecting the open tab
sphinx_tabs_disable_tab_closing = True
76 changes: 57 additions & 19 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,27 +52,35 @@ Specifying one or more sessions

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``:

.. code-block:: console
.. tabs::

nox --session tests
nox -s lint tests
nox -e lint
.. code-tab:: console CLI options

You can also use the ``NOXSESSION`` environment variable:
nox --session tests
nox -s lint tests
nox -e lint

.. code-block:: console
.. code-tab:: console Environment variables

NOXSESSION=lint nox
NOXSESSION=lint,tests nox
NOXSESSION=tests nox
NOXSESSION=lint nox
NOXSESSION=lint,tests nox

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

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

.. code-block:: console
.. tabs::

.. code-tab:: console CLI options

nox --python 3.8
nox -p 3.7 3.8

.. code-tab:: console Environment variables

nox --python 3.8
nox -p 3.7 3.8
NOXPYTHON=3.8 nox
NOXPYTHON=3.7,3.8 nox

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

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

.. code-block:: console
.. tabs::

.. code-tab:: console CLI options

nox --extra-pythons 3.8 3.9 3.10

.. code-tab:: console Environment variables

NOXEXTRAPYTHON=3.8,3.9,3.10 nox

nox --extra-pythons 3.8 3.9 3.10

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

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

nox --python 3.11 --extra-python 3.11 -s lint
.. tabs::

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

nox --force-python 3.11 -s lint
nox --python 3.11 --extra-python 3.11 -s lint

.. code-tab:: console Environment variables

NOXPYTHON=3.11 NOXEXTRAPYTHON=3.11 NOXSESSION=lint nox

Instead of passing both options, you can use the ``--force-python`` shorthand:

.. tabs::

.. code-tab:: console CLI options

nox --force-python 3.11 -s lint

.. code-tab:: console Environment variables

NOXFORCEPYTHON=3.11 NOXSESSION=lint nox

Also, you can specify ``python`` in place of a specific version. This will run the session
using the ``python`` specified for the current ``PATH``::
using the ``python`` specified for the current ``PATH``:

.. tabs::

.. code-tab:: console CLI options

nox --force-python python -s lint

nox --force-python python -s lint
.. code-tab:: console Environment variables

NOXFORCEPYTHON=python NOXSESSION=lint nox

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

Expand Down
24 changes: 17 additions & 7 deletions nox/_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import functools
import os
import sys
from typing import Any, Sequence
from typing import Any, Callable, Sequence

from nox import _option_set
from nox.tasks import discover_manifest, filter_manifest, load_nox_module
Expand Down Expand Up @@ -140,11 +140,18 @@ def _envdir_merge_func(
return command_args.envdir or noxfile_args.envdir or ".nox"


def _sessions_default() -> list[str] | None:
"""Looks at the NOXSESSION env var to set the default value for sessions."""
nox_env = os.environ.get("NOXSESSION")
env_sessions = nox_env.split(",") if nox_env else None
return env_sessions
def default_env_var_list_factory(env_var: str) -> Callable[[], list[str] | None]:
"""Looks at the env var to set the default value for a list of env vars.

Args:
env_var (str): The name of the environment variable to look up.
"""
FollowTheProcess marked this conversation as resolved.
Show resolved Hide resolved

def _default_list() -> list[str] | None:
env_value = os.environ.get(env_var)
return env_value.split(",") if env_value else None

return _default_list


def _color_finalizer(value: bool, args: argparse.Namespace) -> bool:
Expand Down Expand Up @@ -262,7 +269,7 @@ def _session_completer(
noxfile=True,
merge_func=functools.partial(_sessions_and_keywords_merge_func, "sessions"),
nargs="*",
default=_sessions_default,
default=default_env_var_list_factory("NOXSESSION"),
help="Which sessions to run. By default, all sessions will run.",
completer=_session_completer,
),
Expand All @@ -274,6 +281,7 @@ def _session_completer(
group=options.groups["python"],
noxfile=True,
nargs="*",
default=default_env_var_list_factory("NOXPYTHON"),
help="Only run sessions that use the given python interpreter versions.",
),
_option_set.Option(
Expand Down Expand Up @@ -404,6 +412,7 @@ def _session_completer(
"--extra-python",
group=options.groups["python"],
nargs="*",
default=default_env_var_list_factory("NOXEXTRAPYTHON"),
help="Additionally, run sessions using the given python interpreter versions.",
),
_option_set.Option(
Expand All @@ -412,6 +421,7 @@ def _session_completer(
"--force-python",
group=options.groups["python"],
nargs="*",
default=default_env_var_list_factory("NOXFORCEPYTHON"),
help=(
"Run sessions with the given interpreters instead of those listed in the"
" Noxfile. This is a shorthand for ``--python=X.Y --extra-python=X.Y``."
Expand Down
1 change: 1 addition & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ pytest>=6.0
pytest-cov
sphinx>=3.0
sphinx-autobuild
sphinx-tabs
witchhazel
33 changes: 27 additions & 6 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,30 @@ def test_main_explicit_sessions_with_spaces_in_names(monkeypatch):


@pytest.mark.parametrize(
"env,sessions", [("foo", ["foo"]), ("foo,bar", ["foo", "bar"])]
"var,option,env,values",
[
("NOXSESSION", "sessions", "foo", ["foo"]),
("NOXSESSION", "sessions", "foo,bar", ["foo", "bar"]),
("NOXPYTHON", "pythons", "3.9", ["3.9"]),
("NOXPYTHON", "pythons", "3.9,3.10", ["3.9", "3.10"]),
("NOXEXTRAPYTHON", "extra_pythons", "3.9", ["3.9"]),
("NOXEXTRAPYTHON", "extra_pythons", "3.9,3.10", ["3.9", "3.10"]),
("NOXFORCEPYTHON", "force_pythons", "3.9", ["3.9"]),
("NOXFORCEPYTHON", "force_pythons", "3.9,3.10", ["3.9", "3.10"]),
],
ids=[
"single_session",
"multiple_sessions",
"single_python",
"multiple_pythons",
"single_extra_python",
"multiple_extra_pythons",
"single_force_python",
"multiple_force_pythons",
],
)
def test_main_session_from_nox_env_var(monkeypatch, env, sessions):
monkeypatch.setenv("NOXSESSION", env)
def test_main_list_option_from_nox_env_var(monkeypatch, var, option, env, values):
monkeypatch.setenv(var, env)
monkeypatch.setattr(sys, "argv", [sys.executable])

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

# Verify that the sessions from the env var are listed in the config.
config = execute.call_args[1]["global_config"]
assert len(config.sessions) == len(sessions)
for session in sessions:
assert session in config.sessions
config_values = getattr(config, option)
assert len(config_values) == len(values)
for value in values:
assert value in config_values


def test_main_positional_args(capsys, monkeypatch):
Expand Down