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 Session.run_always(). #331

Merged
merged 6 commits into from
Jun 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Projects that use Nox

Nox is lucky to have several wonderful projects that use it and provide feedback and contributions.

- `Bezier <https://github.com/dhermes/bezier>`__
- `Bézier <https://github.com/dhermes/bezier>`__
- `gapic-generator-python <https://github.com/googleapis/gapic-generator-python>`__
- `gdbgui <https://github.com/cs01/gdbgui>`__
- `Google Assistant SDK <https://github.com/googlesamples/assistant-sdk-python>`__
Expand Down
24 changes: 24 additions & 0 deletions docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,30 @@ If your project is a Python package and you want to install it:
session.install(".")
...

In some cases such as Python binary extensions, your package may depend on
code compiled outside of the Python ecosystem. To make sure a low-level
dependency (e.g. ``libfoo``) is available during installation

.. code-block:: python

@nox.session
def tests(session):
...
session.run_always(
"cmake", "-DCMAKE_BUILD_TYPE=Debug",
"-S", libfoo_src_dir,
"-B", build_dir,
external=True,
)
session.run_always(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this called run_always?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we nailed it with the docstring: https://nox.thea.codes/en/stable/config.html#nox.sessions.Session.run_always

Run a command always.

This is a variant of run() that runs in all cases, including in the presence of --install-only.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about session.custom_install_command(...) ?

Seems to be much closer to the intention.
I was now even aware of --install-only.

"cmake",
"--build", build_dir,
"--config", "Debug",
"--target", "install",
external=True,
)
session.install(".")
...
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rendered:
Screen Shot 2020-06-07 at 2 45 16 PM


Running commands
----------------
Expand Down
28 changes: 28 additions & 0 deletions nox/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,34 @@ def run(

return self._run(*args, env=env, **kwargs)

def run_always(
self, *args: str, env: Mapping[str, str] = None, **kwargs: Any
) -> Optional[Any]:
"""Run a command **always**.

This is a variant of :meth:`run` that runs in all cases, including in
the presence of ``--install-only``.

:param env: A dictionary of environment variables to expose to the
command. By default, all environment variables are passed.
:type env: dict or None
:param bool silent: Silence command output, unless the command fails.
``False`` by default.
:param success_codes: A list of return codes that are considered
successful. By default, only ``0`` is considered success.
:type success_codes: list, tuple, or None
:param external: If False (the default) then programs not in the
virtualenv path will cause a warning. If True, no warning will be
emitted. These warnings can be turned into errors using
``--error-on-external-run``. This has no effect for sessions that
do not have a virtualenv.
:type external: bool
"""
if not args:
raise ValueError("At least one argument required to run_always().")

return self._run(*args, env=env, **kwargs)

def _run(self, *args: str, env: Mapping[str, str] = None, **kwargs: Any) -> Any:
"""Like run(), except that it runs even if --install-only is provided."""
# Legacy support - run a function given.
Expand Down
25 changes: 23 additions & 2 deletions tests/test_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import argparse
import logging
import operator
import os
import sys
import tempfile
Expand Down Expand Up @@ -151,7 +152,7 @@ def test_run_bad_args(self):
def test_run_with_func(self):
session, _ = self.make_session_and_runner()

assert session.run(lambda a, b: a + b, 1, 2) == 3
assert session.run(operator.add, 1, 2) == 3

def test_run_with_func_error(self):
session, _ = self.make_session_and_runner()
Expand All @@ -168,7 +169,7 @@ def test_run_install_only(self, caplog):
runner.global_config.install_only = True

with mock.patch.object(nox.command, "run") as run:
session.run("spam", "eggs")
assert session.run("spam", "eggs") is None

run.assert_not_called()

Expand Down Expand Up @@ -262,6 +263,26 @@ def test_run_external_with_error_on_external_run_condaenv(self):
with pytest.raises(nox.command.CommandFailed, match="External"):
session.run(sys.executable, "--version")

def test_run_always_bad_args(self):
session, _ = self.make_session_and_runner()

with pytest.raises(ValueError) as exc_info:
session.run_always()

exc_args = exc_info.value.args
assert exc_args == ("At least one argument required to run_always().",)

def test_run_always_success(self):
session, _ = self.make_session_and_runner()

assert session.run_always(operator.add, 1300, 37) == 1337

def test_run_always_install_only(self, caplog):
session, runner = self.make_session_and_runner()
runner.global_config.install_only = True

assert session.run_always(operator.add, 23, 19) == 42

def test_conda_install_bad_args(self):
session, runner = self.make_session_and_runner()
runner.venv = mock.create_autospec(nox.virtualenv.CondaEnv)
Expand Down