Example #1
0
def test_iteration():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)

    # There should be two sessions in the queue.
    assert len(manifest._queue) == 2
    assert len(manifest._consumed) == 0

    # The first item should be our "foo" session.
    foo = next(manifest)
    assert foo.func == sessions["foo"]
    assert foo in manifest._consumed
    assert foo not in manifest._queue
    assert len(manifest._consumed) == 1
    assert len(manifest._queue) == 1

    # The .next() or .__next__() methods can be called directly according
    # to Python's data model.
    bar = manifest.next()
    assert bar.func == sessions["bar"]
    assert bar in manifest._consumed
    assert bar not in manifest._queue
    assert len(manifest._consumed) == 2
    assert len(manifest._queue) == 0

    # Continuing past the end raises StopIteration.
    with pytest.raises(StopIteration):
        manifest.__next__()
Example #2
0
def test_run_manifest():
    # Set up a valid manifest.
    config = argparse.Namespace(stop_on_first_error=False)
    sessions_ = [
        mock.Mock(spec=sessions.SessionRunner),
        mock.Mock(spec=sessions.SessionRunner),
    ]
    manifest = Manifest({}, config)
    manifest._queue = copy.copy(sessions_)

    # Ensure each of the mocks returns a successful result
    for mock_session in sessions_:
        mock_session.execute.return_value = sessions.Result(
            session=mock_session, status=sessions.Status.SUCCESS
        )

    # Run the manifest.
    results = tasks.run_manifest(manifest, global_config=config)

    # Verify the results look correct.
    assert len(results) == 2
    assert results[0].session == sessions_[0]
    assert results[1].session == sessions_[1]
    for result in results:
        assert isinstance(result, sessions.Result)
        assert result.status == sessions.Status.SUCCESS
Example #3
0
def test_run_manifest_abort_on_first_failure():
    # Set up a valid manifest.
    config = argparse.Namespace(stop_on_first_error=True)
    sessions_ = [
        mock.Mock(spec=sessions.SessionRunner),
        mock.Mock(spec=sessions.SessionRunner),
    ]
    manifest = Manifest({}, config)
    manifest._queue = copy.copy(sessions_)

    # Ensure each of the mocks returns a successful result.
    for mock_session in sessions_:
        mock_session.execute.return_value = sessions.Result(
            session=mock_session, status=sessions.Status.FAILED
        )

    # Run the manifest.
    results = tasks.run_manifest(manifest, global_config=config)

    # Verify the results look correct.
    assert len(results) == 1
    assert isinstance(results[0], sessions.Result)
    assert results[0].session == sessions_[0]
    assert results[0].status == sessions.Status.FAILED

    # Verify that only the first session was called.
    assert sessions_[0].execute.called
    assert not sessions_[1].execute.called
Example #4
0
def test_add_session_idempotent():
    manifest = Manifest({}, mock.sentinel.CONFIG)
    session_func = mock.Mock(spec=(), python=None)
    for session in manifest.make_session("my_session", session_func):
        manifest.add_session(session)
        manifest.add_session(session)
    assert len(manifest) == 1
Example #5
0
def test_filter_by_keyword():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)
    assert len(manifest) == 2
    manifest.filter_by_keywords("foo or bar")
    assert len(manifest) == 2
    manifest.filter_by_keywords("foo")
    assert len(manifest) == 1
Example #6
0
def test_add_session_multiple_pythons():
    manifest = Manifest({}, mock.sentinel.CONFIG)

    def session_func():
        pass

    session_func.python = ["3.5", "3.6"]

    for session in manifest.make_session("my_session", session_func):
        manifest.add_session(session)

    assert len(manifest) == 2
Example #7
0
def test_add_session_parametrized_multiple_pythons():
    manifest = Manifest({}, mock.sentinel.CONFIG)

    # Define a session with parameters.
    @nox.parametrize("param", ("a", "b"))
    def my_session(session, param):
        pass

    my_session.python = ["2.7", "3.6"]

    # Add the session to the manifest.
    for session in manifest.make_session("my_session", my_session):
        manifest.add_session(session)
    assert len(manifest) == 4
Example #8
0
def test_add_session_parametrized_noop():
    manifest = Manifest({}, mock.sentinel.CONFIG)

    # Define a session without any parameters.
    @nox.parametrize("param", ())
    def my_session(session, param):
        pass

    my_session.python = None

    # Add the session to the manifest.
    for session in manifest.make_session("my_session", my_session):
        manifest.add_session(session)
    assert len(manifest) == 1

    session = manifest["my_session"]

    assert session.func == _null_session_func
Example #9
0
def test_getitem():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)

    # Establish that each session is present, and a made-up session
    # is not.
    assert manifest['foo'].func is sessions['foo']
    assert manifest['bar'].func is sessions['bar']
    with pytest.raises(KeyError):
        manifest['baz']

    # Establish that the sessions are still present even after being
    # consumed by iteration.
    for session in manifest:
        pass
    assert manifest['foo'].func is sessions['foo']
    assert manifest['bar'].func is sessions['bar']
Example #10
0
def test_getitem():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, create_mock_config())

    # Establish that each session is present, and a made-up session
    # is not.
    assert manifest["foo"].func is sessions["foo"]
    assert manifest["bar"].func is sessions["bar"]
    with pytest.raises(KeyError):
        manifest["baz"]

    # Establish that the sessions are still present even after being
    # consumed by iteration.
    for session in manifest:
        pass
    assert manifest["foo"].func is sessions["foo"]
    assert manifest["bar"].func is sessions["bar"]
Example #11
0
def discover_manifest(module, global_config):
    """Discover all session functions in the noxfile module.

    Args:
        module (module): The Noxfile module.
        global_config (~nox.main.GlobalConfig): The global configuration.

    Returns:
        ~.Manifest: A manifest of session functions.
    """
    # Find any function added to the session registry (meaning it was
    # decorated with @nox.session); do not sort these, as they are being
    # sorted by decorator call time.
    functions = registry.get()

    # Return the final dictionary of session functions.
    return Manifest(functions, global_config)
Example #12
0
def test_contains():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)

    # Establish that contains works pre-iteration.
    assert "foo" in manifest
    assert "bar" in manifest
    assert "baz" not in manifest

    # Establish that __contains__ works post-iteration.
    for session in manifest:
        pass
    assert "foo" in manifest
    assert "bar" in manifest
    assert "baz" not in manifest

    # Establish that sessions themselves work.
    assert manifest["foo"] in manifest
Example #13
0
def test_notify_noop():
    manifest = Manifest({}, mock.sentinel.CONFIG)

    # Define a session and add it to the manifest.
    def my_session(session):
        pass

    my_session.python = None

    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
Example #14
0
def test_notify_noop():
    manifest = Manifest({}, create_mock_config())

    # Define a session and add it to the manifest.
    def my_session(session):
        pass

    my_session.python = None
    my_session.venv_backend = None

    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
Example #15
0
def discover_manifest(module: types.ModuleType | int,
                      global_config: Namespace) -> Manifest:
    """Discover all session functions in the Noxfile module.

    Args:
        module (module): The Noxfile module.
        global_config (~nox.main.GlobalConfig): The global configuration.

    Returns:
        ~.Manifest: A manifest of session functions.
    """
    # Find any function added to the session registry (meaning it was
    # decorated with @nox.session); do not sort these, as they are being
    # sorted by decorator call time.
    functions = registry.get()

    # Get the docstring from the Noxfile
    module_docstring = module.__doc__

    # Return the final dictionary of session functions.
    return Manifest(functions, global_config, module_docstring)
Example #16
0
def filter_manifest(
    manifest: Manifest, global_config: Namespace
) -> Union[Manifest, int]:
    """Filter the manifest according to the provided configuration.

    Args:
        manifest (~.Manifest): The manifest of sessions to be run.
        global_config (~nox.main.GlobalConfig): The global configuration.

    Returns:
        Union[~.Manifest,int]: ``3`` if a specified session is not found,
            the manifest otherwise (to be sent to the next task).

    """
    # Filter by the name of any explicit sessions.
    # This can raise KeyError if a specified session does not exist;
    # log this if it happens.
    if global_config.sessions:
        try:
            manifest.filter_by_name(global_config.sessions)
        except KeyError as exc:
            logger.error("Error while collecting sessions.")
            logger.error(exc.args[0])
            return 3

    # Filter by python interpreter versions.
    # This function never errors, but may cause an empty list of sessions
    # (which is an error condition later).
    if global_config.pythons:
        manifest.filter_by_python_interpreter(global_config.pythons)

    # Filter by keywords.
    if global_config.keywords:
        try:
            ast.parse(global_config.keywords, mode="eval")
        except SyntaxError:
            logger.error(
                "Error while collecting sessions: keywords argument must be a Python expression."
            )
            return 3

        # This function never errors, but may cause an empty list of sessions
        # (which is an error condition later).
        manifest.filter_by_keywords(global_config.keywords)

    # Return the modified manifest.
    return manifest
Example #17
0
def _produce_listing(manifest: Manifest, global_config: Namespace) -> None:
    # If the user just asked for a list of sessions, print that
    # and any docstring specified in noxfile.py and be done. This
    # can also be called if Noxfile sessions is an empty list.

    if manifest.module_docstring:
        print(manifest.module_docstring.strip(), end="\n\n")

    print(f"Sessions defined in {global_config.noxfile}:\n")

    reset = parse_colors("reset") if global_config.color else ""
    selected_color = parse_colors("cyan") if global_config.color else ""
    skipped_color = parse_colors("white") if global_config.color else ""

    for session, selected in manifest.list_all_sessions():
        output = "{marker} {color}{session}{reset}"

        if selected:
            marker = "*"
            color = selected_color
        else:
            marker = "-"
            color = skipped_color

        if session.description is not None:
            output += " -> {description}"

        print(
            output.format(
                color=color,
                reset=reset,
                session=session.friendly_name,
                description=session.description,
                marker=marker,
            ))

    print(
        f"\nsessions marked with {selected_color}*{reset} are selected, sessions marked"
        f" with {skipped_color}-{reset} are skipped.")
Example #18
0
def test_notify_noop():
    manifest = Manifest({}, mock.sentinel.CONFIG)

    # Define a session and add it to the manifest.
    def my_session(session):
        pass

    my_session.python = None

    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
Example #19
0
def test_filter_manifest_not_found():
    config = argparse.Namespace(sessions=("baz",), keywords=())
    manifest = Manifest({"foo": session_func, "bar": session_func}, config)
    return_value = tasks.filter_manifest(manifest, config)
    assert return_value == 3
Example #20
0
def test_filter_by_name():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, create_mock_config())
    manifest.filter_by_name(("foo",))
    assert "foo" in manifest
    assert "bar" not in manifest
Example #21
0
def filter_manifest(manifest: Manifest,
                    global_config: Namespace) -> Manifest | int:
    """Filter the manifest according to the provided configuration.

    Args:
        manifest (~.Manifest): The manifest of sessions to be run.
        global_config (~nox.main.GlobalConfig): The global configuration.

    Returns:
        Union[~.Manifest,int]: ``3`` if a specified session is not found,
            the manifest otherwise (to be sent to the next task).

    """
    # Shouldn't happen unless the Noxfile is empty
    if not manifest:
        logger.error(f"No sessions found in {global_config.noxfile}.")
        return 3

    # Filter by the name of any explicit sessions.
    # This can raise KeyError if a specified session does not exist;
    # log this if it happens. The sessions does not come from the Noxfile
    # if keywords is not empty.
    if global_config.sessions is not None:
        try:
            manifest.filter_by_name(global_config.sessions)
        except KeyError as exc:
            logger.error("Error while collecting sessions.")
            logger.error(exc.args[0])
            return 3
    if not manifest and not global_config.list_sessions:
        print(
            "No sessions selected. Please select a session with -s <session name>.\n"
        )
        _produce_listing(manifest, global_config)
        return 0

    # Filter by python interpreter versions.
    if global_config.pythons:
        manifest.filter_by_python_interpreter(global_config.pythons)
        if not manifest and not global_config.list_sessions:
            logger.error(
                "Python version selection caused no sessions to be selected.")
            return 3

    # Filter by tags.
    if global_config.tags is not None:
        manifest.filter_by_tags(global_config.tags)
        if not manifest and not global_config.list_sessions:
            logger.error("Tag selection caused no sessions to be selected.")
            return 3

    # Filter by keywords.
    if global_config.keywords:
        try:
            ast.parse(global_config.keywords, mode="eval")
        except SyntaxError:
            logger.error(
                "Error while collecting sessions: keywords argument must be a Python"
                " expression.")
            return 3

        # This function never errors, but may cause an empty list of sessions
        # (which is an error condition later).
        manifest.filter_by_keywords(global_config.keywords)

    if not manifest and not global_config.list_sessions:
        logger.error("No sessions selected after filtering by keyword.")
        return 3

    # Return the modified manifest.
    return manifest
Example #22
0
def test_notify():
    manifest = Manifest({}, mock.sentinel.CONFIG)

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

    my_session.python = None

    def notified(session):
        pass

    notified.python = None

    # 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
Example #23
0
def test_add_session_plain():
    manifest = Manifest({}, mock.sentinel.CONFIG)
    session_func = mock.Mock(spec=(), python=None)
    for session in manifest.make_session("my_session", session_func):
        manifest.add_session(session)
    assert len(manifest) == 1
Example #24
0
def test_filter_by_name():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)
    manifest.filter_by_name(('foo', ))
    assert 'foo' in manifest
    assert 'bar' not in manifest
Example #25
0
def test_filter_by_name_maintains_order():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)
    manifest.filter_by_name(("bar", "foo"))
    assert [session.name for session in manifest] == ["bar", "foo"]
Example #26
0
def test_filter_by_name_maintains_order():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)
    manifest.filter_by_name(("bar", "foo"))
    assert [session.name for session in manifest] == ["bar", "foo"]
Example #27
0
def test_notify_error():
    manifest = Manifest({}, create_mock_config())
    with pytest.raises(ValueError):
        manifest.notify("does_not_exist")
Example #28
0
def test_add_session_plain():
    manifest = Manifest({}, create_mock_config())
    session_func = mock.Mock(spec=(), python=None, venv_backend=None)
    for session in manifest.make_session("my_session", session_func):
        manifest.add_session(session)
    assert len(manifest) == 1
Example #29
0
def test_filter_by_name_not_found():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, create_mock_config())
    with pytest.raises(KeyError):
        manifest.filter_by_name(("baz",))
Example #30
0
def test_filter_by_name_maintains_order():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, create_mock_config())
    manifest.filter_by_name(("bar", "foo"))
    assert [session.name for session in manifest] == ["bar", "foo"]
Example #31
0
def test_len():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)
    assert len(manifest) == 2
    for session in manifest:
        assert len(manifest) == 2
Example #32
0
def test_verify_manifest_empty():
    config = _options.options.namespace(sessions=(), keywords=())
    manifest = Manifest({}, config)
    return_value = tasks.verify_manifest_nonempty(manifest,
                                                  global_config=config)
    assert return_value == 3
Example #33
0
def test_filter_by_name():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)
    manifest.filter_by_name(("foo", ))
    assert "foo" in manifest
    assert "bar" not in manifest
Example #34
0
def test_verify_manifest_nonempty():
    config = _options.options.namespace(sessions=(), keywords=(), posargs=[])
    manifest = Manifest({"session": session_func}, config)
    return_value = tasks.verify_manifest_nonempty(manifest,
                                                  global_config=config)
    assert return_value == manifest
Example #35
0
def test_filter_by_name_not_found():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)
    with pytest.raises(KeyError):
        manifest.filter_by_name(("baz", ))
Example #36
0
def test_verify_manifest_nonempty():
    config = argparse.Namespace(sessions=(), keywords=())
    manifest = Manifest({"session": session_func}, config)
    return_value = tasks.verify_manifest_nonempty(manifest, global_config=config)
    assert return_value == manifest
Example #37
0
def test_notify():
    manifest = Manifest({}, mock.sentinel.CONFIG)

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

    my_session.python = None

    def notified(session):
        pass

    notified.python = None

    # 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
Example #38
0
def test_add_session_idempotent():
    manifest = Manifest({}, mock.sentinel.CONFIG)
    for session in manifest.make_session('my_session', lambda session: None):
        manifest.add_session(session)
        manifest.add_session(session)
    assert len(manifest) == 1
Example #39
0
def test_notify_error():
    manifest = Manifest({}, mock.sentinel.CONFIG)
    with pytest.raises(ValueError):
        manifest.notify("does_not_exist")
Example #40
0
def test_notify_error():
    manifest = Manifest({}, mock.sentinel.CONFIG)
    with pytest.raises(ValueError):
        manifest.notify("does_not_exist")
Example #41
0
def test_filter_by_name_not_found():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)
    with pytest.raises(KeyError):
        manifest.filter_by_name(("baz",))
Example #42
0
def test_filter_manifest():
    config = argparse.Namespace(sessions=(), keywords=())
    manifest = Manifest({"foo": session_func, "bar": session_func}, config)
    return_value = tasks.filter_manifest(manifest, config)
    assert return_value is manifest
    assert len(manifest) == 2
Example #43
0
def test_filter_by_name():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, mock.sentinel.CONFIG)
    manifest.filter_by_name(("foo",))
    assert "foo" in manifest
    assert "bar" not in manifest
Example #44
0
def test_len():
    sessions = create_mock_sessions()
    manifest = Manifest(sessions, create_mock_config())
    assert len(manifest) == 2
    for session in manifest:
        assert len(manifest) == 2