Example #1
0
def test_add_session_multiple_pythons():
    manifest = Manifest({}, create_mock_config())

    def session_func():
        pass

    func = Func(session_func, python=["3.5", "3.6"])
    for session in manifest.make_session("my_session", func):
        manifest.add_session(session)

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

    def session_func():
        pass

    func = Func(session_func, python=["3.5", "3.6"])
    for session in manifest.make_session("my_session", func):
        manifest.add_session(session)

    assert len(manifest) == 2
Example #3
0
def test_notify_with_posargs():
    cfg = create_mock_config()
    manifest = Manifest({}, cfg)

    session = manifest.make_session("my_session", Func(lambda session: None))[0]
    manifest.add_session(session)

    # delete my_session from the queue
    manifest.filter_by_name(())

    assert session.posargs == cfg.posargs
    assert manifest.notify("my_session", posargs=["--an-arg"])
    assert session.posargs == ["--an-arg"]
Example #4
0
def test_add_session_parametrized_multiple_pythons():
    manifest = Manifest({}, create_mock_config())

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

    func = Func(my_session, python=["2.7", "3.6"])

    # Add the session to the manifest.
    for session in manifest.make_session("my_session", func):
        manifest.add_session(session)
    assert len(manifest) == 4
Example #5
0
def test_extra_pythons(python, extra_pythons, expected):
    cfg = create_mock_config()
    cfg.extra_pythons = extra_pythons

    manifest = Manifest({}, cfg)

    def session_func():
        pass

    func = Func(session_func, python=python)
    for session in manifest.make_session("my_session", func):
        manifest.add_session(session)

    assert expected == [session.func.python for session in manifest._all_sessions]
Example #6
0
def test_add_session_parametrized():
    manifest = Manifest({}, mock.sentinel.CONFIG)

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

    func = Func(my_session, python=None)

    # Add the session to the manifest.
    for session in manifest.make_session("my_session", func):
        manifest.add_session(session)
    assert len(manifest) == 3
Example #7
0
def test_extra_pythons(python, extra_pythons, expected):
    cfg = mock.sentinel.CONFIG
    cfg.force_venv_backend = None
    cfg.default_venv_backend = None
    cfg.extra_pythons = extra_pythons

    manifest = Manifest({}, cfg)

    def session_func():
        pass

    func = Func(session_func, python=python)
    for session in manifest.make_session("my_session", func):
        manifest.add_session(session)

    assert expected == [
        session.func.python for session in manifest._all_sessions
    ]
Example #8
0
    def make_session(self,
                     name: str,
                     func: Func,
                     multi: bool = False) -> list[SessionRunner]:
        """Create a session object from the session function.

        Args:
            name (str): The name of the session.
            func (function): The session function.
            multi (bool): Whether the function is a member of a set of sessions
                with different interpreters.

        Returns:
            Sequence[~nox.session.Session]: A sequence of Session objects
                bound to this manifest and configuration.
        """
        sessions = []

        # If the backend is "none", we won't parametrize `python`.
        backend = (self._config.force_venv_backend or func.venv_backend
                   or self._config.default_venv_backend)
        if backend == "none" and isinstance(func.python, (list, tuple, set)):
            # we can not log a warning here since the session is maybe deselected.
            # instead let's set a flag, to warn later when session is actually run.
            func.should_warn[WARN_PYTHONS_IGNORED] = func.python
            func.python = False

        if self._config.extra_pythons:
            # If extra python is provided, expand the func.python list to
            # include additional python interpreters
            extra_pythons: list[str] = self._config.extra_pythons
            if isinstance(func.python, (list, tuple, set)):
                func.python = _unique_list(*func.python, *extra_pythons)
            elif not multi and func.python:
                # If this is multi, but there is only a single interpreter, it
                # is the reentrant case. The extra_python interpreter shouldn't
                # be added in that case. If func.python is False, the session
                # has no backend; if None, it uses the same interpreter as Nox.
                # Otherwise, add the extra specified python.
                assert isinstance(func.python, str)
                func.python = _unique_list(func.python, *extra_pythons)

        # If the func has the python attribute set to a list, we'll need
        # to expand them.
        if isinstance(func.python, (list, tuple, set)):

            for python in func.python:
                single_func = func.copy()
                single_func.python = python
                sessions.extend(
                    self.make_session(name, single_func, multi=True))

            return sessions

        # Simple case: If this function is not parametrized, then make
        # a simple session.
        if not hasattr(func, "parametrize"):
            long_names = []
            if not multi:
                long_names.append(name)
            if func.python:
                long_names.append(f"{name}-{func.python}")

            return [SessionRunner(name, long_names, func, self._config, self)]

        # Since this function is parametrized, we need to add a distinct
        # session for each permutation.
        parametrize = func.parametrize  # type: ignore[attr-defined]
        calls = Call.generate_calls(func, parametrize)
        for call in calls:
            long_names = []
            if not multi:
                long_names.append(f"{name}{call.session_signature}")
            if func.python:
                long_names.append(
                    f"{name}-{func.python}{call.session_signature}")
                # Ensure that specifying session-python will run all parameterizations.
                long_names.append(f"{name}-{func.python}")

            sessions.append(
                SessionRunner(name, long_names, call, self._config, self))

        # Edge case: If the parameters made it such that there were no valid
        # calls, add an empty, do-nothing session.
        if not calls:
            sessions.append(
                SessionRunner(name, [], _null_session_func, self._config,
                              self))

        # Return the list of sessions.
        return sessions
Example #9
0
    return eval(expression, {}, locals)


def _null_session_func_(session: Session) -> None:
    """A no-op session for patemetrized sessions with no available params."""
    session.skip("This session had no parameters available.")


def _normalized_session_match(session_name: str,
                              session: SessionRunner) -> bool:
    """Checks if session_name matches session."""
    if session_name == session.name or session_name in session.signatures:
        return True
    for name in session.signatures:
        equal_rep = _normalize_arg(session_name) == _normalize_arg(name)
        if equal_rep:
            return True
    # Exhausted
    return False


def _normalize_arg(arg: str) -> str:
    """Normalize arg for comparison."""
    try:
        return str(ast.dump(ast.parse(arg)))
    except (TypeError, SyntaxError):
        return arg


_null_session_func = Func(_null_session_func_, python=False)