Skip to content

Commit

Permalink
Addition of session.notify (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukesneeringer authored Aug 30, 2017
1 parent cb64e33 commit d6b3a5a
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 5 deletions.
10 changes: 9 additions & 1 deletion nox.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ def default(session):
tests = session.posargs or ['tests/']
session.run(
'py.test', '--cov=nox', '--cov-config', '.coveragerc',
'--cov-report', 'term-missing', *tests)
'--cov-report=', *tests)
session.notify('cover')


@nox.session
Expand All @@ -32,6 +33,13 @@ def interpreters(session, version):
session.interpreter = 'python' + version


@nox.session
def cover(session):
session.install('coverage')
session.run('coverage', 'report', '--fail-under=100', '--show-missing')
session.run('coverage', 'erase')


@nox.session
def lint(session):
session.install('flake8', 'flake8-import-order')
Expand Down
14 changes: 13 additions & 1 deletion nox/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def __init__(self, args, env=None, silent=False, path=None,
self.path = path
self.success_codes = success_codes or [0]

def run(self, path_override=None, env_fallback=None):
def run(self, path_override=None, env_fallback=None, **kwargs):
path = self.path if path_override is None else path_override

env = env_fallback.copy() if env_fallback is not None else None
Expand Down Expand Up @@ -169,3 +169,15 @@ def run(self, venv):

def __str__(self):
return ' '.join(self.deps)


class NotifyCommand(Command):
"""Notify the given session and add it to the queue."""

def __init__(self, target, debug=False):
self.target = target
self.debug = debug

def __call__(self, session, **kwargs):
logger.info('Notifying session: %s' % self.target)
session.manifest.notify(self.target)
31 changes: 31 additions & 0 deletions nox/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,37 @@ def make_session(self, name, func):
def next(self):
return self.__next__()

def notify(self, session):
"""Enqueue the specified session in the queue.
If the session is already in the queue, or has been run already,
then this is a no-op.
Args:
session (Union[str, ~nox.session.Session]): The session to be
enqueued.
Returns:
bool: Whether the session was added to the queue.
Raises:
ValueError: If the session was not found.
"""
# Sanity check: If this session is already in the queue, this is
# a no-op.
if session in self:
return False

# Locate the session in the list of all sessions, and place it at
# the end of the queue.
for s in self._all_sessions:
if s == session or s.name == session or s.signature == session:
self._queue.append(s)
return True

# The session was not found in the list of sessions.
raise ValueError('Session %s not found.' % session)


class KeywordLocals(object):
"""Eval locals using keywords.
Expand Down
26 changes: 23 additions & 3 deletions nox/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@
import six

from nox import utils
from nox.command import (
ChdirCommand, Command, CommandFailed, FunctionCommand, InstallCommand)
from nox.command import ChdirCommand
from nox.command import Command
from nox.command import CommandFailed
from nox.command import FunctionCommand
from nox.command import InstallCommand
from nox.command import NotifyCommand
from nox.logger import logger
from nox.virtualenv import ProcessEnv, VirtualEnv

Expand Down Expand Up @@ -190,6 +194,19 @@ def install(self, *args):
raise ValueError('At least one argument required to install().')
self._commands.append(InstallCommand(args))

def notify(self, target):
"""Place the given session at the end of the queue.
This method is idempotent; multiple notifications to the same session
have no effect.
Args:
target (Union[str, Callable]): The session to be notified. This
may be specified as the appropropriate string or using
the function object.
"""
self._commands.append(NotifyCommand(target))

def log(self, *args, **kwargs):
"""Outputs a log during the session."""
logger.info(*args, **kwargs)
Expand Down Expand Up @@ -255,7 +272,10 @@ def _run_commands(self):
for command in self.config._commands:
if isinstance(command, Command):
command(
path_override=self.venv.bin, env_fallback=env)
env_fallback=env,
path_override=self.venv.bin,
session=self,
)
elif isinstance(command, InstallCommand):
if not self._should_install_deps:
logger.debug(
Expand Down
7 changes: 7 additions & 0 deletions tests/test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,10 @@ def test_function_command_debug(make_one_func):

assert command.run()
mock_func.assert_called_with(1, two=3)


def test_notify_command():
command = nox.command.NotifyCommand('foo')
m = mock.Mock()
command(m)
m.manifest.notify.assert_called_once_with('foo')
46 changes: 46 additions & 0 deletions tests/test_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,52 @@ def my_session(session, param):
assert len(manifest) == 1


def test_notify():
manifest = Manifest({}, mock.sentinel.CONFIG)

# Define a session.
def my_session(session):
pass
def notified(session):
pass

# Add the sessions to the manifest.
for session in manifest.make_session('my_session', my_session):
manifest.add_session(session)
for session in manifest.make_session('notified', notified):
manifest.add_session(session)
assert len(manifest) == 2

# Filter so only the first session is included in the queue.
manifest.filter_by_name(('my_session',))
assert len(manifest) == 1

# Notify the notified session.
manifest.notify('notified')
assert len(manifest) == 2


def test_notify_noop():
manifest = Manifest({}, mock.sentinel.CONFIG)

# Define a session and add it to the manifest.
def my_session(session):
pass
for session in manifest.make_session('my_session', my_session):
manifest.add_session(session)
assert len(manifest) == 1

# Establish idempotency; notifying a session already in the queue no-ops.
manifest.notify('my_session')
assert len(manifest) == 1


def test_notify_error():
manifest = Manifest({}, mock.sentinel.CONFIG)
with pytest.raises(ValueError):
manifest.notify('does_not_exist')


def test_add_session_idempotent():
manifest = Manifest({}, mock.sentinel.CONFIG)
for session in manifest.make_session('my_session', lambda session: None):
Expand Down
7 changes: 7 additions & 0 deletions tests/test_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ def test_config_chdir(make_one_config):
assert str(command) == 'chdir meep'


def test_config_notify(make_one_config):
config = make_one_config()
config.notify('foo')
command = config._commands[0]
assert isinstance(command, nox.command.NotifyCommand)


def test_config_run(make_one_config):
def test_func():
pass
Expand Down

0 comments on commit d6b3a5a

Please sign in to comment.