예제 #1
0
def _lint_pre_commit(session, rcfile, flags, paths):
    if "VIRTUAL_ENV" not in os.environ:
        session.error(
            "This should be running from within a virtualenv and "
            "'VIRTUAL_ENV' was not found as an environment variable."
        )
    if "pre-commit" not in os.environ["VIRTUAL_ENV"]:
        session.error(
            "This should be running from within a pre-commit virtualenv and "
            "'VIRTUAL_ENV'({}) does not appear to be a pre-commit virtualenv.".format(
                os.environ["VIRTUAL_ENV"]
            )
        )
    from nox.virtualenv import VirtualEnv

    # Let's patch nox to make it run inside the pre-commit virtualenv
    try:
        session._runner.venv = VirtualEnv(  # pylint: disable=unexpected-keyword-arg
            os.environ["VIRTUAL_ENV"],
            interpreter=session._runner.func.python,
            reuse_existing=True,
            venv=True,
        )
    except TypeError:
        # This is still nox-py2
        session._runner.venv = VirtualEnv(
            os.environ["VIRTUAL_ENV"],
            interpreter=session._runner.func.python,
            reuse_existing=True,
        )
    _lint(session, rcfile, flags, paths, tee_output=False)
예제 #2
0
def invoke_pre_commit(session):
    """
    DO NOT CALL THIS NOX SESSION DIRECTLY

    This session is called from a pre-commit hook
    """
    if "VIRTUAL_ENV" not in os.environ:
        session.error(
            "This should be running from within a virtualenv and "
            "'VIRTUAL_ENV' was not found as an environment variable.")
    if "pre-commit" not in os.environ["VIRTUAL_ENV"]:
        session.error(
            "This should be running from within a pre-commit virtualenv and "
            "'VIRTUAL_ENV'({}) does not appear to be a pre-commit virtualenv.".
            format(os.environ["VIRTUAL_ENV"]))
    from nox.virtualenv import VirtualEnv

    # Let's patch nox to make it run inside the pre-commit virtualenv
    try:
        session._runner.venv = VirtualEnv(  # pylint: disable=unexpected-keyword-arg
            os.environ["VIRTUAL_ENV"],
            interpreter=session._runner.func.python,
            reuse_existing=True,
            venv=True,
        )
    except TypeError:
        # This is still nox-py2
        session._runner.venv = VirtualEnv(
            os.environ["VIRTUAL_ENV"],
            interpreter=session._runner.func.python,
            reuse_existing=True,
        )
    _invoke(session)
예제 #3
0
 def _create_venv(self):
     self.venv = VirtualEnv(
         os.path.join(self.global_config.envdir, self.name),
         interpreter=self.config.interpreter,
         reuse_existing=(self.config.reuse_existing_virtualenv
                         or self.global_config.reuse_existing_virtualenvs))
     self.venv.create()
예제 #4
0
파일: sessions.py 프로젝트: tswast/nox
    def _create_venv(self):
        if self.func.python is False:
            self.venv = ProcessEnv()
            return

        path = _normalize_path(self.global_config.envdir, self.friendly_name)
        reuse_existing = (self.func.reuse_venv
                          or self.global_config.reuse_existing_virtualenvs)
        self.venv = VirtualEnv(path,
                               interpreter=self.func.python,
                               reuse_existing=reuse_existing)
        self.venv.create()
예제 #5
0
    def _create_venv(self):
        if not self.config.virtualenv:
            self.venv = ProcessEnv()
            self._should_install_deps = False
            return

        self.venv = VirtualEnv(
            _normalize_path(self.global_config.envdir, self.signature
                            or self.name),
            interpreter=self.config.interpreter,
            reuse_existing=(self.config.reuse_existing_virtualenv
                            or self.global_config.reuse_existing_virtualenvs))
        self._should_install_deps = self.venv.create()
예제 #6
0
파일: sessions.py 프로젝트: jonparrott/nox
    def _create_venv(self):
        if self.func.python is False:
            self.venv = ProcessEnv()
            return

        path = _normalize_path(self.global_config.envdir, self.friendly_name)
        reuse_existing = (
            self.func.reuse_venv or self.global_config.reuse_existing_virtualenvs
        )
        self.venv = VirtualEnv(
            path, interpreter=self.func.python, reuse_existing=reuse_existing
        )
        self.venv.create()
예제 #7
0
파일: tasks.py 프로젝트: teejaz/scrapd
def flame_graph(c):
    c.run(f'nox --install-only -s profiling')
    location = Path('.nox/profiling')
    venv = VirtualEnv(location.resolve())
    venv_bin = Path(venv.bin)
    scrapd = venv_bin / 'scrapd'
    c.run(f'sudo py-spy -d 20 --flame profile.svg -- {scrapd.resolve()} -v --pages 5')
예제 #8
0
def _patch_session(session):
    if USE_SYSTEM_PYTHON is False:
        session.log("NOT Patching nox to install against the system python")
        return

    session.log("Patching nox to install against the system python")
    # Let's get sys.prefix
    old_install_only_value = session._runner.global_config.install_only
    try:
        # Force install only to be false for the following chunk of code
        # For additional information as to why see:
        #   https://github.com/theacodes/nox/pull/181
        session._runner.global_config.install_only = False
        sys_prefix = session.run(
            "python",
            "-c"
            'import sys; sys.stdout.write("{}".format(sys.prefix))',
            silent=True,
            log=False,
        )
        # Let's patch nox to make it run and in particular, install, to the system python
        session._runner.venv = VirtualEnv(
            sys_prefix,
            interpreter=session._runner.func.python,
            reuse_existing=True)
    finally:
        session._runner.global_config.install_only = old_install_only_value
예제 #9
0
def mkdocs_bin():
    """Find mkdocs binary in default venv."""
    location = Path(DEFAULT_VENV_NAME)
    venv = VirtualEnv(location.resolve())
    venv_bin = Path(venv.bin)
    mkdocs = venv_bin / 'mkdocs'
    return mkdocs
예제 #10
0
    def _create_venv(self):
        if self.func.python is False:
            self.venv = ProcessEnv()
            return

        path = _normalize_path(self.global_config.envdir, self.friendly_name)
        reuse_existing = (self.func.reuse_venv
                          or self.global_config.reuse_existing_virtualenvs)

        if not self.func.venv_backend or self.func.venv_backend == "virtualenv":
            self.venv = VirtualEnv(path,
                                   interpreter=self.func.python,
                                   reuse_existing=reuse_existing)
        elif self.func.venv_backend == "conda":
            self.venv = CondaEnv(path,
                                 interpreter=self.func.python,
                                 reuse_existing=reuse_existing)
        elif self.func.venv_backend == "venv":
            self.venv = VirtualEnv(
                path,
                interpreter=self.func.python,
                reuse_existing=reuse_existing,
                venv=True,
            )
        else:
            raise ValueError(
                "Expected venv_backend one of ('virtualenv', 'conda', 'venv'), but got '{}'."
                .format(self.func.venv_backend))

        self.venv.create()
예제 #11
0
def get_venv(venv):
    """
    Return `Path` objects from the venv.
    :param str venv: venv name
    :return: the venv `Path`, the `bin` folder `Path` within the venv, and if specified, the `Path` object of the
        activate script within the venv.
    :rtype: a tuple of 3 `Path` objects.
    """
    location = Path(venv)
    venv = VirtualEnv(location.resolve())
    venv_bin = Path(venv.bin)
    activate = venv_bin / 'activate'
    return venv, venv_bin, activate
예제 #12
0
def _lint_pre_commit(session, rcfile, flags, paths):
    if "VIRTUAL_ENV" not in os.environ:
        session.error(
            "This should be running from within a virtualenv and "
            "'VIRTUAL_ENV' was not found as an environment variable.")
    if "pre-commit" not in os.environ["VIRTUAL_ENV"]:
        session.error(
            "This should be running from within a pre-commit virtualenv and "
            "'VIRTUAL_ENV'({}) does not appear to be a pre-commit virtualenv.".
            format(os.environ["VIRTUAL_ENV"]))

    # Let's patch nox to make it run inside the pre-commit virtualenv
    session._runner.venv = VirtualEnv(
        os.environ["VIRTUAL_ENV"],
        interpreter=session._runner.func.python,
        reuse_existing=True,
        venv=True,
    )
    _lint(session, rcfile, flags, paths, tee_output=False)
예제 #13
0
    def _create_venv(self) -> None:
        backend = (
            self.global_config.force_venv_backend
            or self.func.venv_backend
            or self.global_config.default_venv_backend
        )

        if backend == "none" or self.func.python is False:
            self.venv = PassthroughEnv()
            return

        reuse_existing = (
            self.func.reuse_venv or self.global_config.reuse_existing_virtualenvs
        )

        if backend is None or backend == "virtualenv":
            self.venv = VirtualEnv(
                self.envdir,
                interpreter=self.func.python,  # type: ignore
                reuse_existing=reuse_existing,
                venv_params=self.func.venv_params,
            )
        elif backend == "conda":
            self.venv = CondaEnv(
                self.envdir,
                interpreter=self.func.python,  # type: ignore
                reuse_existing=reuse_existing,
                venv_params=self.func.venv_params,
            )
        elif backend == "venv":
            self.venv = VirtualEnv(
                self.envdir,
                interpreter=self.func.python,  # type: ignore
                reuse_existing=reuse_existing,
                venv=True,
                venv_params=self.func.venv_params,
            )
        else:
            raise ValueError(
                "Expected venv_backend one of ('virtualenv', 'conda', 'venv'), but got '{}'.".format(
                    backend
                )
            )

        self.venv.create()
예제 #14
0
파일: sessions.py 프로젝트: stsewd/nox
class SessionRunner(object):
    def __init__(self, name, signature, func, global_config, manifest=None):
        self.name = name
        self.signature = signature
        self.func = func
        self.global_config = global_config
        self.manifest = manifest
        self.venv = None

    def __str__(self):
        return self.signature or self.name

    def _create_venv(self):
        if self.func.python is False:
            self.venv = ProcessEnv()
            return

        name = self.signature or self.name
        path = _normalize_path(self.global_config.envdir, name)
        reuse_existing = (self.func.reuse_venv
                          or self.global_config.reuse_existing_virtualenvs)
        self.venv = VirtualEnv(path,
                               interpreter=self.func.python,
                               reuse_existing=reuse_existing)
        self.venv.create()

    def execute(self):
        session_friendly_name = self.signature or self.name
        logger.warning('Running session {}'.format(session_friendly_name))

        try:
            # By default, nox should quietly change to the directory where
            # the nox.py file is located.
            cwd = py.path.local(
                os.path.realpath(os.path.dirname(
                    self.global_config.noxfile))).as_cwd()

            with cwd:
                self._create_venv()
                session = Session(self)
                self.func(session)

            # Nothing went wrong; return a success.
            return Result(self, Status.SUCCESS)

        except _SessionQuit:
            return Result(self, Status.ABORTED)

        except _SessionSkip:
            return Result(self, Status.SKIPPED)

        except nox.command.CommandFailed:
            return Result(self, Status.FAILED)

        except KeyboardInterrupt:
            logger.error('Session {} interrupted.'.format(self))
            raise

        except Exception as exc:
            logger.exception('Session {} raised exception {!r}'.format(
                self, exc))
            return Result(self, Status.FAILED)
예제 #15
0
class Session(object):
    def __init__(self, name, signature, func, global_config):
        self.name = name
        self.signature = signature
        self.func = func
        self.global_config = global_config
        self._should_install_deps = True

    def _create_config(self):
        self.config = SessionConfig(posargs=self.global_config.posargs)

        # By default, nox should quietly change to the directory where
        # the nox.py file is located.
        cwd = os.path.realpath(os.path.dirname(self.global_config.noxfile))
        self.config.chdir(cwd, debug=True)

        # Run the actual session function, passing it the newly-created
        # SessionConfig object.
        try:
            self.func(self.config)
            return True
        except _SessionQuit:
            return False

    def _create_venv(self):
        if not self.config.virtualenv:
            self.venv = ProcessEnv()
            self._should_install_deps = False
            return

        virtualenv_name = (self.config.virtualenv_dirname or self.signature
                           or self.name)
        self.venv = VirtualEnv(
            _normalize_path(self.global_config.envdir, virtualenv_name),
            interpreter=self.config.interpreter,
            reuse_existing=(self.config.reuse_existing_virtualenv
                            or self.global_config.reuse_existing_virtualenvs))
        self._should_install_deps = self.venv.create()

    def _run_commands(self):
        env = self.venv.env.copy()
        env.update(self.config.env)

        for command in self.config._commands:
            if isinstance(command, Command):
                command(path_override=self.venv.bin, env_fallback=env)
            elif isinstance(command, InstallCommand):
                if not self._should_install_deps:
                    logger.debug(
                        'Skipping installation of "{}".'.format(command))
                    continue
                else:
                    command(self.venv)
            else:
                command()

    def execute(self):
        session_friendly_name = self.signature or self.name
        logger.warning('Running session {}'.format(session_friendly_name))

        try:
            if not self._create_config():
                logger.error(
                    'Session {} aborted.'.format(session_friendly_name))
                return False

            self._create_venv()

            cwd = py.path.local(os.getcwd()).as_cwd()
            with cwd:
                self._run_commands()

            logger.success(
                'Session {} successful. :)'.format(session_friendly_name))
            return True

        except CommandFailed:
            logger.error('Session {} failed. :('.format(session_friendly_name))
            return False

        except KeyboardInterrupt:
            logger.error(
                'Session {} interrupted.'.format(session_friendly_name))
            raise
예제 #16
0
class SessionRunner:
    def __init__(
        self,
        name: str,
        signatures: List[str],
        func: Func,
        global_config: argparse.Namespace,
        manifest: "Optional[Manifest]" = None,
    ) -> None:
        self.name = name
        self.signatures = signatures
        self.func = func
        self.global_config = global_config
        self.manifest = manifest
        self.venv = None  # type: Optional[ProcessEnv]

    @property
    def description(self) -> Optional[str]:
        doc = self.func.__doc__
        if doc:
            first_line = doc.strip().split("\n")[0]
            return first_line
        return None

    def __str__(self) -> str:
        sigs = ", ".join(self.signatures)
        return "Session(name={}, signatures={})".format(self.name, sigs)

    @property
    def friendly_name(self) -> str:
        return self.signatures[0] if self.signatures else self.name

    def _create_venv(self) -> None:
        if self.func.python is False:
            self.venv = ProcessEnv()
            return

        path = _normalize_path(self.global_config.envdir, self.friendly_name)
        reuse_existing = (self.func.reuse_venv
                          or self.global_config.reuse_existing_virtualenvs)

        if not self.func.venv_backend or self.func.venv_backend == "virtualenv":
            self.venv = VirtualEnv(
                path,
                interpreter=self.func.python,  # type: ignore
                reuse_existing=reuse_existing,
                venv_params=self.func.venv_params,
            )
        elif self.func.venv_backend == "conda":
            self.venv = CondaEnv(
                path,
                interpreter=self.func.python,  # type: ignore
                reuse_existing=reuse_existing,
                venv_params=self.func.venv_params,
            )
        elif self.func.venv_backend == "venv":
            self.venv = VirtualEnv(
                path,
                interpreter=self.func.python,  # type: ignore
                reuse_existing=reuse_existing,
                venv=True,
                venv_params=self.func.venv_params,
            )
        else:
            raise ValueError(
                "Expected venv_backend one of ('virtualenv', 'conda', 'venv'), but got '{}'."
                .format(self.func.venv_backend))

        self.venv.create()  # type: ignore

    def execute(self) -> "Result":
        logger.warning("Running session {}".format(self.friendly_name))

        try:
            # By default, nox should quietly change to the directory where
            # the noxfile.py file is located.
            cwd = py.path.local(
                os.path.realpath(os.path.dirname(
                    self.global_config.noxfile))).as_cwd()

            with cwd:
                self._create_venv()
                session = Session(self)
                self.func(session)

            # Nothing went wrong; return a success.
            return Result(self, Status.SUCCESS)

        except nox.virtualenv.InterpreterNotFound as exc:
            if self.global_config.error_on_missing_interpreters:
                return Result(self, Status.FAILED, reason=str(exc))
            else:
                return Result(self, Status.SKIPPED, reason=str(exc))

        except _SessionQuit as exc:
            return Result(self, Status.ABORTED, reason=str(exc))

        except _SessionSkip as exc:
            return Result(self, Status.SKIPPED, reason=str(exc))

        except nox.command.CommandFailed:
            return Result(self, Status.FAILED)

        except KeyboardInterrupt:
            logger.error("Session {} interrupted.".format(self.friendly_name))
            raise

        except Exception as exc:
            logger.exception("Session {} raised exception {!r}".format(
                self.friendly_name, exc))
            return Result(self, Status.FAILED)
예제 #17
0
파일: sessions.py 프로젝트: jonparrott/nox
class SessionRunner:
    def __init__(self, name, signatures, func, global_config, manifest=None):
        self.name = name
        self.signatures = signatures
        self.func = func
        self.global_config = global_config
        self.manifest = manifest
        self.venv = None

    @property
    def description(self):
        doc = self.func.__doc__
        if doc:
            first_line = doc.strip().split("\n")[0]
            return first_line
        return None

    def __str__(self):
        sigs = ", ".join(self.signatures)
        return "Session(name={}, signatures={})".format(self.name, sigs)

    @property
    def friendly_name(self):
        return self.signatures[0] if self.signatures else self.name

    def _create_venv(self):
        if self.func.python is False:
            self.venv = ProcessEnv()
            return

        path = _normalize_path(self.global_config.envdir, self.friendly_name)
        reuse_existing = (
            self.func.reuse_venv or self.global_config.reuse_existing_virtualenvs
        )
        self.venv = VirtualEnv(
            path, interpreter=self.func.python, reuse_existing=reuse_existing
        )
        self.venv.create()

    def execute(self):
        logger.warning("Running session {}".format(self.friendly_name))

        try:
            # By default, nox should quietly change to the directory where
            # the noxfile.py file is located.
            cwd = py.path.local(
                os.path.realpath(os.path.dirname(self.global_config.noxfile))
            ).as_cwd()

            with cwd:
                self._create_venv()
                session = Session(self)
                self.func(session)

            # Nothing went wrong; return a success.
            return Result(self, Status.SUCCESS)

        except nox.virtualenv.InterpreterNotFound as exc:
            if self.global_config.error_on_missing_interpreters:
                return Result(self, Status.FAILED, reason=str(exc))
            else:
                return Result(self, Status.SKIPPED, reason=str(exc))

        except _SessionQuit as exc:
            return Result(self, Status.ABORTED, reason=str(exc))

        except _SessionSkip as exc:
            return Result(self, Status.SKIPPED, reason=str(exc))

        except nox.command.CommandFailed:
            return Result(self, Status.FAILED)

        except KeyboardInterrupt:
            logger.error("Session {} interrupted.".format(self.friendly_name))
            raise

        except Exception as exc:
            logger.exception(
                "Session {} raised exception {!r}".format(self.friendly_name, exc)
            )
            return Result(self, Status.FAILED)
예제 #18
0
class Session(object):
    def __init__(self, name, signature, func, global_config, manifest=None):
        self.name = name
        self.signature = signature
        self.func = func
        self.global_config = global_config
        self.manifest = manifest
        self._should_install_deps = True

    def __str__(self):
        return utils.coerce_str(self.signature or self.name)

    def _create_config(self):
        self.config = SessionConfig(posargs=self.global_config.posargs)

        # By default, nox should quietly change to the directory where
        # the nox.py file is located.
        cwd = os.path.realpath(os.path.dirname(self.global_config.noxfile))
        self.config.chdir(cwd, debug=True)

        # Run the actual session function, passing it the newly-created
        # SessionConfig object.
        self.func(self.config)

    def _create_venv(self):
        if not self.config.virtualenv:
            self.venv = ProcessEnv()
            self._should_install_deps = False
            return

        virtualenv_name = (
            self.config.virtualenv_dirname or self.signature or self.name)
        self.venv = VirtualEnv(
            _normalize_path(
                self.global_config.envdir, virtualenv_name),
            interpreter=self.config.interpreter,
            reuse_existing=(
                self.config.reuse_existing_virtualenv or
                self.global_config.reuse_existing_virtualenvs))
        self._should_install_deps = self.venv.create()

    def _run_commands(self):
        env = self.venv.env.copy()
        env.update(self.config.env)

        for command in self.config._commands:
            if isinstance(command, Command):
                command(
                    env_fallback=env,
                    path_override=self.venv.bin,
                    session=self,
                )
            elif isinstance(command, InstallCommand):
                if not self._should_install_deps:
                    logger.debug(
                        'Skipping installation of "{}".'.format(command))
                    continue
                else:
                    command(self.venv)
            else:
                command()

    def execute(self):
        session_friendly_name = self.signature or self.name
        logger.warning('Running session {}'.format(session_friendly_name))

        try:
            # Set up the SessionConfig object (which session functions refer
            # to as `session`) and then the virtualenv.
            self._create_config()
            self._create_venv()

            # Run the actual commands prescribed by the session.
            cwd = py.path.local(os.getcwd()).as_cwd()
            with cwd:
                self._run_commands()

            # Nothing went wrong; return a success.
            return Result(self, Status.SUCCESS)

        except _SessionQuit:
            return Result(self, Status.ABORTED)

        except _SessionSkip:
            return Result(self, Status.SKIPPED)

        except CommandFailed:
            return Result(self, Status.FAILED)

        except KeyboardInterrupt:
            logger.error('Session {} interrupted.'.format(self))
            raise
예제 #19
0
class Session(object):
    def __init__(self, name, signature, func, global_config):
        self.name = name
        self.signature = signature
        self.func = func
        self.global_config = global_config

    def _create_config(self):
        self.config = SessionConfig(posargs=self.global_config.posargs)
        self.func(self.config)

    def _create_venv(self):
        self.venv = VirtualEnv(
            os.path.join(self.global_config.envdir, self.name),
            interpreter=self.config.interpreter,
            reuse_existing=(self.config.reuse_existing_virtualenv
                            or self.global_config.reuse_existing_virtualenvs))
        self.venv.create()

    def _install_dependencies(self):
        for dep in self.config._dependencies:
            self.venv.install(*dep)

    def _run_commands(self):
        env = self.venv.env.copy()
        env.update(self.config.env)

        for command in self.config._commands:
            if isinstance(command, Command):
                command.path = self.venv.bin
                command.env = env
                command()
            else:
                command()

    def execute(self):
        logger.warning('Running session {}'.format(self.signature
                                                   or self.name))

        try:
            self._create_config()
            self._create_venv()
            self._install_dependencies()

            if self.config._dir != '.':
                logger.info('Changing directory to {}'.format(
                    self.config._dir))

            cwd = py.path.local(self.config._dir).as_cwd()
            with cwd:
                self._run_commands()

            logger.success('Session {} successful. :)'.format(self.name))
            return True

        except CommandFailed:
            logger.error('Session {} failed. :('.format(self.name))
            return False

        except KeyboardInterrupt:
            logger.error('Session {} interrupted.'.format(self.name))
            raise
예제 #20
0
class SessionRunner:
    def __init__(self, name, signatures, func, global_config, manifest=None):
        self.name = name
        self.signatures = signatures
        self.func = func
        self.global_config = global_config
        self.manifest = manifest
        self.venv = None

    @property
    def description(self):
        doc = self.func.__doc__
        if doc:
            first_line = doc.strip().split("\n")[0]
            return first_line
        return None

    def __str__(self):
        sigs = ", ".join(self.signatures)
        return "Session(name={}, signatures={})".format(self.name, sigs)

    @property
    def friendly_name(self):
        return self.signatures[0] if self.signatures else self.name

    def _create_venv(self):
        if self.func.python is False:
            self.venv = ProcessEnv()
            return

        path = _normalize_path(self.global_config.envdir, self.friendly_name)
        reuse_existing = (
            self.func.reuse_venv or self.global_config.reuse_existing_virtualenvs
        )
        self.venv = VirtualEnv(
            path, interpreter=self.func.python, reuse_existing=reuse_existing
        )
        self.venv.create()

    def execute(self):
        logger.warning("Running session {}".format(self.friendly_name))

        try:
            # By default, nox should quietly change to the directory where
            # the noxfile.py file is located.
            cwd = py.path.local(
                os.path.realpath(os.path.dirname(self.global_config.noxfile))
            ).as_cwd()

            with cwd:
                self._create_venv()
                session = Session(self)
                self.func(session)

            # Nothing went wrong; return a success.
            return Result(self, Status.SUCCESS)

        except nox.virtualenv.InterpreterNotFound as exc:
            if self.global_config.error_on_missing_interpreters:
                return Result(self, Status.FAILED, reason=str(exc))
            else:
                return Result(self, Status.SKIPPED, reason=str(exc))

        except _SessionQuit as exc:
            return Result(self, Status.ABORTED, reason=str(exc))

        except _SessionSkip as exc:
            return Result(self, Status.SKIPPED, reason=str(exc))

        except nox.command.CommandFailed:
            return Result(self, Status.FAILED)

        except KeyboardInterrupt:
            logger.error("Session {} interrupted.".format(self.friendly_name))
            raise

        except Exception as exc:
            logger.exception(
                "Session {} raised exception {!r}".format(self.friendly_name, exc)
            )
            return Result(self, Status.FAILED)
예제 #21
0
class SessionRunner:
    def __init__(
        self,
        name: str,
        signatures: list[str],
        func: Func,
        global_config: argparse.Namespace,
        manifest: Manifest,
    ) -> None:
        self.name = name
        self.signatures = signatures
        self.func = func
        self.global_config = global_config
        self.manifest = manifest
        self.venv: ProcessEnv | None = None
        self.posargs: list[str] = global_config.posargs[:]

    @property
    def description(self) -> str | None:
        doc = self.func.__doc__
        if doc:
            first_line = doc.strip().split("\n")[0]
            return first_line
        return None

    def __str__(self) -> str:
        sigs = ", ".join(self.signatures)
        return f"Session(name={self.name}, signatures={sigs})"

    @property
    def friendly_name(self) -> str:
        return self.signatures[0] if self.signatures else self.name

    @property
    def tags(self) -> list[str]:
        return self.func.tags

    @property
    def envdir(self) -> str:
        return _normalize_path(self.global_config.envdir, self.friendly_name)

    def _create_venv(self) -> None:
        backend = (self.global_config.force_venv_backend
                   or self.func.venv_backend
                   or self.global_config.default_venv_backend)

        if backend == "none" or self.func.python is False:
            self.venv = PassthroughEnv()
            return

        reuse_existing = (self.func.reuse_venv
                          or self.global_config.reuse_existing_virtualenvs)

        if backend is None or backend == "virtualenv":
            self.venv = VirtualEnv(
                self.envdir,
                interpreter=self.func.python,  # type: ignore[arg-type]
                reuse_existing=reuse_existing,
                venv_params=self.func.venv_params,
            )
        elif backend in {"conda", "mamba"}:
            self.venv = CondaEnv(
                self.envdir,
                interpreter=self.func.python,  # type: ignore[arg-type]
                reuse_existing=reuse_existing,
                venv_params=self.func.venv_params,
                conda_cmd=backend,
            )
        elif backend == "venv":
            self.venv = VirtualEnv(
                self.envdir,
                interpreter=self.func.python,  # type: ignore[arg-type]
                reuse_existing=reuse_existing,
                venv=True,
                venv_params=self.func.venv_params,
            )
        else:
            raise ValueError(
                "Expected venv_backend one of ('virtualenv', 'conda', 'mamba',"
                f" 'venv'), but got '{backend}'.")

        self.venv.create()

    def execute(self) -> Result:
        logger.warning(f"Running session {self.friendly_name}")

        try:
            # By default, Nox should quietly change to the directory where
            # the noxfile.py file is located.
            cwd = py.path.local(
                os.path.realpath(os.path.dirname(
                    self.global_config.noxfile))).as_cwd()

            with cwd:
                self._create_venv()
                session = Session(self)
                self.func(session)

            # Nothing went wrong; return a success.
            return Result(self, Status.SUCCESS)

        except nox.virtualenv.InterpreterNotFound as exc:
            if self.global_config.error_on_missing_interpreters:
                return Result(self, Status.FAILED, reason=str(exc))
            else:
                logger.warning(
                    "Missing interpreters will error by default on CI systems."
                )
                return Result(self, Status.SKIPPED, reason=str(exc))

        except _SessionQuit as exc:
            return Result(self, Status.ABORTED, reason=str(exc))

        except _SessionSkip as exc:
            return Result(self, Status.SKIPPED, reason=str(exc))

        except nox.command.CommandFailed:
            return Result(self, Status.FAILED)

        except KeyboardInterrupt:
            logger.error(f"Session {self.friendly_name} interrupted.")
            raise

        except Exception as exc:
            logger.exception(
                f"Session {self.friendly_name} raised exception {exc!r}")
            return Result(self, Status.FAILED)