Esempio n. 1
0
def tox_testenv_create(venv, action):
    """
    Python is already installed, we just need to handle dependency installs, there are two major phases, we take
    care of 1 here:

    1. extend base image -> create env image
       1. install pip/setuptools/wheel
       2. install dependencies
       3. develop -> copy folder - install via -e
          non-develop -> copy sdist - install
    2. run:
        1. start container from env image and mount {toxinidir} under
        2. install package (either develop or sdist)
        3. run commands one by one
        4. stop and remove container
    """
    with safe_package_view(venv) as context:
        cwd = os.getcwd()
        os.chdir(context)
        try:
            image_id = build_image(venv, context, action)
        except Exception as exception:
            reporter.error(f"could not build image {exception}")  # pragma: no cover
            raise  # pragma: no cover
        finally:
            os.chdir(cwd)

    image = set_docker_image_tag(image_id, venv)
    if venv.envconfig.image is not None:  # already had a previous image (e.g. different python)
        try:
            CLIENT.images.remove(image=venv.envconfig.image.id, force=True)
        except Exception as exception:  # pragma: no cover
            reporter.warning(f"could not delete image {exception}")  # pragma: no cover
    venv.envconfig.image = image
    return True
Esempio n. 2
0
def get_latest_version_of_package(package_spec):
    if not os.path.isabs(str(package_spec)):
        return package_spec
    p = py.path.local(package_spec)
    if p.check():
        return p
    if not p.dirpath().check(dir=1):
        raise tox.exception.MissingDirectory(p.dirpath())
    reporter.info("determining {}".format(p))
    candidates = p.dirpath().listdir(p.basename)
    if len(candidates) == 0:
        raise MissingDependency(package_spec)
    if len(candidates) > 1:
        version_package = []
        for filename in candidates:
            version = get_version_from_filename(filename.basename)
            if version is not None:
                version_package.append((version, filename))
            else:
                reporter.warning("could not determine version of: {}".format(
                    str(filename)))
        if not version_package:
            raise tox.exception.MissingDependency(package_spec)
        version_package.sort()
        _, package_with_largest_version = version_package[-1]
        return package_with_largest_version
    else:
        return candidates[0]
Esempio n. 3
0
    def ensure_pip_os_environ_ok(self, env):
        for key in (
                "PIP_RESPECT_VIRTUALENV",
                "PIP_REQUIRE_VIRTUALENV",
                "__PYVENV_LAUNCHER__",
        ):
            env.pop(key, None)
        if all("PYTHONPATH" not in i
               for i in (self.envconfig.passenv, self.envconfig.setenv)):
            # If PYTHONPATH not explicitly asked for, remove it.
            if "PYTHONPATH" in env:
                if sys.version_info < (3, 4) or bool(env["PYTHONPATH"]):
                    # https://docs.python.org/3/whatsnew/3.4.html#changes-in-python-command-behavior
                    # In a posix shell, setting the PATH environment variable to an empty value is
                    # equivalent to not setting it at all.
                    reporter.warning(
                        "Discarding $PYTHONPATH from environment, to override "
                        "specify PYTHONPATH in 'passenv' in your configuration.",
                    )
                env.pop("PYTHONPATH")

        # installing packages at user level may mean we're not installing inside the venv
        env["PIP_USER"] = "******"

        # installing without dependencies may lead to broken packages
        env["PIP_NO_DEPS"] = "0"
Esempio n. 4
0
 def _check_external_allowed_and_warn(self, path):
     if not self.is_allowed_external(path):
         reporter.warning(
             "test command found but not installed in testenv\n"
             "  cmd: {}\n"
             "  env: {}\n"
             "Maybe you forgot to specify a dependency? "
             "See also the whitelist_externals envconfig setting.\n\n"
             "DEPRECATION WARNING: this will be an error in tox 4 and above!"
             .format(path, self.envconfig.envdir))
Esempio n. 5
0
def wheel_build_package(config, session, venv):
    if config.isolated_build:
        reporter.warning(
            "Disabling isolated_build, not supported with wheels.")
    pep517 = venv.envconfig.wheel_pep517
    if pep517:
        wheel_package = wheel_build_pep517(config, session, venv)
    else:
        wheel_package = wheel_build_legacy(config, session, venv)
    return wheel_package
Esempio n. 6
0
def tox_runtest(venv, redirect):
    _init_pipenv_environ()
    pipfile_path = _clone_pipfile(venv)

    action = venv.new_action("runtests")

    with wrap_pipenv_environment(venv, pipfile_path):
        action.setactivity(
            "runtests", "PYTHONHASHSEED=%r" % os.environ.get("PYTHONHASHSEED")
        )
        for i, argv in enumerate(venv.envconfig.commands):
            # have to make strings as _pcall changes argv[0] to a local()
            # happens if the same environment is invoked twice
            cwd = venv.envconfig.changedir
            message = "commands[%s] | %s" % (i, " ".join([str(x) for x in argv]))
            action.setactivity("runtests", message)
            # check to see if we need to ignore the return code
            # if so, we need to alter the command line arguments
            if argv[0].startswith("-"):
                ignore_ret = True
                if argv[0] == "-":
                    del argv[0]
                else:
                    argv[0] = argv[0].lstrip("-")
            else:
                ignore_ret = False
            args = [sys.executable, "-m", "pipenv", "run"] + argv
            try:
                venv._pcall(
                    args,
                    venv=False,
                    cwd=cwd,
                    action=action,
                    redirect=redirect,
                    ignore_ret=ignore_ret
                )
            except tox.exception.InvocationError as err:
                if venv.envconfig.ignore_outcome:
                    reporter.warning(
                        "command failed but result from testenv is ignored\n"
                        "  cmd: %s" % (str(err),)
                    )
                    venv.status = "ignored failed command"
                    continue  # keep processing commands

                reporter.error(str(err))
                venv.status = "commands failed"
                if not venv.envconfig.ignore_errors:
                    break  # Don't process remaining commands
            except KeyboardInterrupt:
                venv.status = "keyboardinterrupt"
                reporter.error(venv.status)
                raise

    return True
Esempio n. 7
0
def tox_configure(config: config.Config):
    """
	Parse the command line and ini options.
	"""

    args: List[List[str]] = [[]]

    while config.args:
        val: str = config.args.pop(0)
        if val == "--":
            break
        elif val.startswith('-'):
            args.append([val])
        else:
            args[-1].append(val)

    envlist_set = False
    envlist_name_set = False

    # Parse envlists
    ini_config: "IniConfig" = config._cfg
    envlists: Dict[str, List[str]] = {}

    for envlist_name, envlist in ini_config.sections.get("envlists",
                                                         {}).items():
        envlist_elements = DELIMITERS.split(envlist)
        expanded_envlist = list(
            chain.from_iterable(map(braceexpand, envlist_elements)))
        envlists[envlist_name] = list(filter(None, expanded_envlist))

    for idx, arg in enumerate(args):
        if arg and arg[0] in {"-e", "--envlist"}:
            envlist_set = True
        elif arg and arg[0] in option_names:
            envlist_name_set = True

    for idx, arg in enumerate(args):
        if arg and arg[0] in option_names:
            if envlist_name_set and envlist_set:
                reporter.warning(
                    f"Ignoring '{' '.join(args.pop(idx))}' option as '-e / --envlist' option given.",
                )

            elif envlist_name_set and arg[1] in envlists:
                config.envlist = envlists[arg[1]]

            elif envlist_name_set:
                config._parser.argparser.error(
                    f"Unknown envlist {arg[1]!r}. (envlists are {word_join(envlists, use_repr=True)})"
                )

    config.args = list(chain.from_iterable(args))

    return config
Esempio n. 8
0
    def _pcall(
        self,
        args,
        cwd,
        venv=True,
        is_test_command=False,
        action=None,
        redirect=True,
        ignore_ret=False,
        returnout=False,
        env=None,
        capture_err=True,
    ):
        if env is None:
            env = self._get_os_environ(is_test_command=is_test_command)

        # construct environment variables
        env.pop("VIRTUALENV_PYTHON", None)
        bin_dir = str(self.envconfig.envbindir)
        path = self.envconfig.setenv.get("PATH") or os.environ["PATH"]
        env["PATH"] = os.pathsep.join([bin_dir, path])
        reporter.verbosity2("setting PATH={}".format(env["PATH"]))

        # get command
        try:
            args[0] = self.getcommandpath(args[0], venv, cwd)
        except tox.exception.InvocationError:
            if ignore_ret:
                self.status = getattr(self, "status", 0)
                msg = "command not found but explicitly ignored"
                reporter.warning("{}\ncmd: {}".format(msg, args[0]))
                return ""  # in case it's returnout
            else:
                raise

        if sys.platform != "win32" and "TOX_LIMITED_SHEBANG" in os.environ:
            args = prepend_shebang_interpreter(args)

        cwd.ensure(dir=1)  # ensure the cwd exists
        return action.popen(
            args,
            cwd=cwd,
            env=env,
            redirect=redirect,
            ignore_ret=ignore_ret,
            returnout=returnout,
            report_fail=not is_test_command,
            capture_err=capture_err,
        )
Esempio n. 9
0
    def ensure_pip_os_environ_ok(self):
        for key in ("PIP_RESPECT_VIRTUALENV", "PIP_REQUIRE_VIRTUALENV",
                    "__PYVENV_LAUNCHER__"):
            os.environ.pop(key, None)
        if "PYTHONPATH" not in self.envconfig.passenv:
            # If PYTHONPATH not explicitly asked for, remove it.
            if "PYTHONPATH" in os.environ:
                reporter.warning(
                    "Discarding $PYTHONPATH from environment, to override "
                    "specify PYTHONPATH in 'passenv' in your configuration.")
                os.environ.pop("PYTHONPATH")

        # installing packages at user level may mean we're not installing inside the venv
        os.environ["PIP_USER"] = "******"

        # installing without dependencies may lead to broken packages
        os.environ["PIP_NO_DEPS"] = "0"
Esempio n. 10
0
def show_deprecation_warning_for_old_style_pypy_config(version):
    # type: (str) -> None
    if version not in {"pypy2", "pypy3"}:
        return
    warning(
        """PendingDeprecationWarning
Support of old-style PyPy config keys will be removed in tox-gh-actions v3.
Please use "pypy-2" and "pypy-3" instead of "pypy2" and "pypy3".

Example of tox.ini:
[gh-actions]
python =
    pypy-2: pypy2
    pypy-3: pypy3
    # The followings won't work with tox-gh-actions v3
    # pypy2: pypy2
    # pypy3: pypy3
    """
    )
Esempio n. 11
0
def acquire_package(config, session):
    """acquire a source distribution (either by loading a local file or triggering a build)"""
    if not config.option.sdistonly and (config.sdistsrc or config.option.installpkg):
        path = get_local_package(config)
    else:
        try:
            path = build_package(config, session)
        except tox.exception.InvocationError as exception:
            error("FAIL could not package project - v = {!r}".format(exception))
            return None
        sdist_file = config.distshare.join(path.basename)
        if sdist_file != path:
            info("copying new sdistfile to {!r}".format(str(sdist_file)))
            try:
                sdist_file.dirpath().ensure(dir=1)
            except py.error.Error:
                warning("could not copy distfile to {}".format(sdist_file.dirpath()))
            else:
                path.copy(sdist_file)
    return path
Esempio n. 12
0
    def test(
        self,
        redirect=False,
        name="run-test",
        commands=None,
        ignore_outcome=None,
        ignore_errors=None,
        display_hash_seed=False,
    ):
        if commands is None:
            commands = self.envconfig.commands
        if ignore_outcome is None:
            ignore_outcome = self.envconfig.ignore_outcome
        if ignore_errors is None:
            ignore_errors = self.envconfig.ignore_errors
        with self.new_action(name) as action:
            cwd = self.envconfig.changedir
            if display_hash_seed:
                env = self._get_os_environ(is_test_command=True)
                # Display PYTHONHASHSEED to assist with reproducibility.
                action.setactivity(
                    name,
                    "PYTHONHASHSEED={!r}".format(env.get("PYTHONHASHSEED")))
            for i, argv in enumerate(commands):
                # have to make strings as _pcall changes argv[0] to a local()
                # happens if the same environment is invoked twice
                message = "commands[{}] | {}".format(
                    i, " ".join([pipes.quote(str(x)) for x in argv]))
                action.setactivity(name, message)
                # check to see if we need to ignore the return code
                # if so, we need to alter the command line arguments
                if argv[0].startswith("-"):
                    ignore_ret = True
                    if argv[0] == "-":
                        del argv[0]
                    else:
                        argv[0] = argv[0].lstrip("-")
                else:
                    ignore_ret = False

                try:
                    self._pcall(
                        argv,
                        cwd=cwd,
                        action=action,
                        redirect=redirect,
                        ignore_ret=ignore_ret,
                        is_test_command=True,
                    )
                except tox.exception.InvocationError as err:
                    if ignore_outcome:
                        msg = "command failed but result from testenv is ignored\ncmd:"
                        reporter.warning("{} {}".format(msg, err))
                        self.status = "ignored failed command"
                        continue  # keep processing commands

                    reporter.error(str(err))
                    self.status = "commands failed"
                    if not ignore_errors:
                        break  # Don't process remaining commands
                except KeyboardInterrupt:
                    self.status = "keyboardinterrupt"
                    raise
Esempio n. 13
0
def tox_configure(config):
    """Check for the presence of the added options."""
    if config.option.prepend_archraw_factor:
        from cpuinfo.cpuinfo import DataSource  # noqa

        archraw_factor_name = DataSource.arch_string_raw.replace("-",
                                                                 "_").lower()
        if not config.option.prepend_factor:
            config.option.prepend_factor = [archraw_factor_name]
        else:
            config.option.prepend_factor.insert(0, archraw_factor_name)

    if config.option.prepend_cpuarch_factor:
        from cpuinfo.cpuinfo import _parse_arch, DataSource  # noqa

        try:
            arch, _ = _parse_arch(DataSource.arch_string_raw)
            arch = arch.lower()
            if not config.option.prepend_factor:
                config.option.prepend_factor = [arch]
            else:
                config.option.prepend_factor.insert(0, arch)
        except Exception:
            archraw_factor_name = DataSource.arch_string_raw.replace(
                "-", "_").lower()
            warning('cpuarch not available for archraw "{}"'.format(
                archraw_factor_name))

    if config.option.prepend_ostype_factor:
        from osinfo.osinfo import _get_os_type  # noqa

        if not config.option.prepend_factor:
            config.option.prepend_factor = [_get_os_type().lower()]
        else:
            config.option.prepend_factor.insert(0, _get_os_type().lower())

    if config.option.add_ci_factor and "CI" in os.environ:
        extra_factor = None
        if "APPVEYOR" in os.environ or "TRAVIS" in os.environ:
            config.option.prepend_username_factor = True
        elif "CIRRUS_CI" in os.environ:
            extra_factor = "cirrusci"
        else:
            extra_factor = "ci"

        if extra_factor:
            if not config.option.append_factor:
                config.option.append_factor = [extra_factor]
            else:
                config.option.append_factor.insert(0, extra_factor)

    if config.option.prepend_username_factor:
        import getpass  # noqa

        username = getpass.getuser()
        if username:
            username = username.lower()

        if not config.option.prepend_factor:
            config.option.prepend_factor = [username]
        else:
            config.option.prepend_factor.insert(0, username)

    if config.option.prepend_factor:
        add_factors(config, config.option.prepend_factor, position=BEFORE)
    if config.option.append_factor:
        add_factors(config, config.option.append_factor, position=AFTER)
Esempio n. 14
0
def wheel_build_package(config, session, venv):
    if config.isolated_build:
        reporter.warning("Disabling isolated_build, not supported with wheels.")
    return wheel_build(config, session, venv)