Example #1
0
def cleanup_for_venv(venv):
    within_parallel = PARALLEL_ENV_VAR_KEY in os.environ
    # if the directory exists and it doesn't look like a virtualenv, produce
    # an error
    if venv.path.exists():
        dir_items = set(os.listdir(str(venv.path))) - {".lock", "log"}
        dir_items = {p for p in dir_items if not p.startswith(".tox-")}
    else:
        dir_items = set()

    if not (
            # doesn't exist => OK
            not venv.path.exists()
            # does exist, but it's empty => OK
            or not dir_items
            # it exists and we're on windows with Lib and Scripts => OK
            or (INFO.IS_WIN and dir_items > {"Scripts", "Lib"})
            # non-windows, with lib and bin => OK
            or dir_items > {"bin", "lib"}):
        venv.status = "error"
        reporter.error(
            "cowardly refusing to delete `envdir` (it does not look like a virtualenv): "
            "{}".format(venv.path))
        raise SystemExit(2)

    if within_parallel:
        if venv.path.exists():
            # do not delete the log folder as that's used by parent
            for content in venv.path.listdir():
                if not content.basename == "log":
                    content.remove(rec=1, ignore_errors=True)
    else:
        ensure_empty_dir(venv.path)
Example #2
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
Example #3
0
def get_build_info(folder):
    toml_file = folder.join("pyproject.toml")

    # as per https://www.python.org/dev/peps/pep-0517/

    def abort(message):
        reporter.error("{} inside {}".format(message, toml_file))
        raise SystemExit(1)

    if not toml_file.exists():
        reporter.error("missing {}".format(toml_file))
        raise SystemExit(1)

    config_data = get_py_project_toml(toml_file)

    if "build-system" not in config_data:
        abort("build-system section missing")

    build_system = config_data["build-system"]

    if "requires" not in build_system:
        abort("missing requires key at build-system section")
    if "build-backend" not in build_system:
        abort("missing build-backend key at build-system section")

    requires = build_system["requires"]
    if not isinstance(requires, list) or not all(
            isinstance(i, six.text_type) for i in requires):
        abort("requires key at build-system section must be a list of string")

    backend = build_system["build-backend"]
    if not isinstance(backend, six.text_type):
        abort("build-backend key at build-system section must be a string")

    args = backend.split(":")
    module = args[0]
    obj = args[1] if len(args) > 1 else ""

    backend_paths = build_system.get("backend-path", [])
    if not isinstance(backend_paths, list):
        abort(
            "backend-path key at build-system section must be a list, if specified"
        )
    backend_paths = [folder.join(p) for p in backend_paths]

    normalized_folder = os.path.normcase(str(folder.realpath()))
    normalized_paths = (os.path.normcase(str(path.realpath()))
                        for path in backend_paths)

    if not all(
            os.path.commonprefix((normalized_folder,
                                  path)) == normalized_folder
            for path in normalized_paths):
        abort("backend-path must exist in the project root")

    return BuildInfo(requires, module, obj, backend_paths)
Example #4
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
Example #5
0
 def run_system_cmd(cmd):
     """Helper to report running command and also to actually run the command"""
     reporter.line("external_build: running command: {}".format(cmd))
     p_cmd = Popen(cmd, shell=True, stderr=STDOUT)
     stdout, _ = p_cmd.communicate()
     if p_cmd.returncode != 0:
         reporter.error(
             "external_build returned: {} stdout+stderr: {}".format(
                 p_cmd.returncode, stdout))
         raise ExternalBuildNonZeroReturn(
             "'{}' exited with return code: {}".format(
                 cmd, p_cmd.returncode))
Example #6
0
 def setupenv(self):
     if self.envconfig._missing_subs:
         self.status = (
             "unresolvable substitution(s):\n    {}\n"
             "Environment variables are missing or defined recursively.".format(
                 "\n    ".join(
                     [
                         "{}: '{}'".format(section_key, exc.name)
                         for section_key, exc in sorted(self.envconfig._missing_subs.items())
                     ],
                 ),
             )
         )
         return
     if not self.matching_platform():
         self.status = "platform mismatch"
         return  # we simply omit non-matching platforms
     with self.new_action("getenv", self.envconfig.envdir) as action:
         self.status = 0
         default_ret_code = 1
         envlog = self.env_log
         try:
             status = self.update(action=action)
         except IOError as e:
             if e.args[0] != 2:
                 raise
             status = (
                 "Error creating virtualenv. Note that spaces in paths are "
                 "not supported by virtualenv. Error details: {!r}".format(e)
             )
         except tox.exception.InvocationError as e:
             status = e
         except tox.exception.InterpreterNotFound as e:
             status = e
             if self.envconfig.config.option.skip_missing_interpreters == "true":
                 default_ret_code = 0
         except KeyboardInterrupt:
             self.status = "keyboardinterrupt"
             raise
         if status:
             str_status = str(status)
             command_log = envlog.get_commandlog("setup")
             command_log.add_command(["setup virtualenv"], str_status, default_ret_code)
             self.status = status
             if default_ret_code == 0:
                 reporter.skip(str_status)
             else:
                 reporter.error(str_status)
             return False
         command_path = self.getcommandpath("python")
         envlog.set_python_info(command_path)
         return True
Example #7
0
 def getvenv(self, name):
     if name in self.existing_venvs:
         return self.existing_venvs[name]
     env_config = self.config.envconfigs.get(name, None)
     if env_config is None:
         reporter.error("unknown environment {!r}".format(name))
         raise LookupError(name)
     elif env_config.envdir == self.config.toxinidir:
         reporter.error("venv {!r} in {} would delete project".format(name, env_config.envdir))
         raise tox.exception.ConfigError("envdir must not equal toxinidir")
     env_log = self.resultlog.get_envlog(name)
     venv = VirtualEnv(envconfig=env_config, popen=self.popen, env_log=env_log)
     self.existing_venvs[name] = venv
     return venv
Example #8
0
 def evaluate_cmd(self, input_file_handler, process, redirect):
     try:
         if self.generate_tox_log and not redirect:
             if process.stderr is not None:
                 # prevent deadlock
                 raise ValueError("stderr must not be piped here")
             # we read binary from the process and must write using a binary stream
             buf = getattr(sys.stdout, "buffer", sys.stdout)
             last_time = time.time()
             while True:
                 # we have to read one byte at a time, otherwise there
                 # might be no output for a long time with slow tests
                 data = input_file_handler.read(1)
                 if data:
                     buf.write(data)
                     if b"\n" in data or (time.time() - last_time) > 1:
                         # we flush on newlines or after 1 second to
                         # provide quick enough feedback to the user
                         # when printing a dot per test
                         buf.flush()
                         last_time = time.time()
                 elif process.poll() is not None:
                     if process.stdout is not None:
                         process.stdout.close()
                     break
                 else:
                     time.sleep(0.1)
                     # the seek updates internal read buffers
                     input_file_handler.seek(0, 1)
             input_file_handler.close()
         out, _ = process.communicate()  # wait to finish
     except KeyboardInterrupt as exception:
         reporter.error("got KeyboardInterrupt signal")
         main_thread = is_main_thread()
         while True:
             try:
                 if main_thread:
                     # spin up a new thread to disable further interrupt on main thread
                     stopper = Thread(target=self.handle_interrupt,
                                      args=(process, ))
                     stopper.start()
                     stopper.join()
                 else:
                     self.handle_interrupt(process)
             except KeyboardInterrupt:
                 continue
             break
         raise exception
     return out
Example #9
0
 def setupenv(self):
     if self.envconfig.missing_subs:
         self.status = (
             "unresolvable substitution(s): {}. "
             "Environment variables are missing or defined recursively.".
             format(",".join(
                 ["'{}'".format(m) for m in self.envconfig.missing_subs])))
         return
     if not self.matching_platform():
         self.status = "platform mismatch"
         return  # we simply omit non-matching platforms
     with self.new_action("getenv", self.envconfig.envdir) as action:
         self.status = 0
         default_ret_code = 1
         envlog = self.env_log
         try:
             status = self.update(action=action)
         except IOError as e:
             if e.args[0] != 2:
                 raise
             status = (
                 "Error creating virtualenv. Note that spaces in paths are "
                 "not supported by virtualenv. Error details: {!r}".format(
                     e))
         except tox.exception.InvocationError as e:
             status = (
                 "Error creating virtualenv. Note that some special characters (e.g. ':' and "
                 "unicode symbols) in paths are not supported by virtualenv. Error details: "
                 "{!r}".format(e))
         except tox.exception.InterpreterNotFound as e:
             status = e
             if self.envconfig.config.option.skip_missing_interpreters == "true":
                 default_ret_code = 0
         if status:
             str_status = str(status)
             command_log = envlog.get_commandlog("setup")
             command_log.add_command(["setup virtualenv"], str_status,
                                     default_ret_code)
             self.status = status
             if default_ret_code == 0:
                 reporter.skip(str_status)
             else:
                 reporter.error(str_status)
             return False
         command_path = self.getcommandpath("python")
         envlog.set_python_info(command_path)
         return True
Example #10
0
def make_sdist(config, session):
    setup = config.setupdir.join("setup.py")
    pyproject = config.setupdir.join("pyproject.toml")
    setup_check = setup.check()
    if not setup_check and not pyproject.check():
        reporter.error(
            "No pyproject.toml or setup.py file found. The expected locations are:\n"
            "  {pyproject} or {setup}\n"
            "You can\n"
            "  1. Create one:\n"
            "     https://tox.readthedocs.io/en/latest/example/package.html\n"
            "  2. Configure tox to avoid running sdist:\n"
            "     https://tox.readthedocs.io/en/latest/example/general.html\n"
            "  3. Configure tox to use an isolated_build".format(
                pyproject=pyproject, setup=setup), )
        raise SystemExit(1)
    if not setup_check:
        reporter.error(
            "pyproject.toml file found.\n"
            "To use a PEP 517 build-backend you are required to "
            "configure tox to use an isolated_build:\n"
            "https://tox.readthedocs.io/en/latest/example/package.html\n", )
        raise SystemExit(1)
    with session.newaction("GLOB", "packaging") as action:
        action.setactivity("sdist-make", setup)
        ensure_empty_dir(config.distdir)
        build_log = action.popen(
            [
                sys.executable,
                setup,
                "sdist",
                "--formats=zip",
                "--dist-dir",
                config.distdir,
            ],
            cwd=config.setupdir,
            returnout=True,
        )
        reporter.verbosity2(build_log)
        try:
            return config.distdir.listdir()[0]
        except py.error.ENOENT:
            # check if empty or comment only
            data = []
            with open(str(setup)) as fp:
                for line in fp:
                    if line and line[0] == "#":
                        continue
                    data.append(line)
            if not "".join(data).strip():
                reporter.error("setup.py is empty")
                raise SystemExit(1)
            reporter.error(
                "No dist directory found. Please check setup.py, e.g with:\n"
                "     python setup.py sdist", )
            raise SystemExit(1)
Example #11
0
    def _build_venvs(self):
        try:
            need_to_run = OrderedDict((v, self.getvenv(v)) for v in self._evaluated_env_list)
            try:
                venv_order = stable_topological_sort(
                    OrderedDict((name, v.envconfig.depends) for name, v in need_to_run.items()),
                )

                venvs = OrderedDict((v, need_to_run[v]) for v in venv_order)
                return venvs
            except ValueError as exception:
                reporter.error("circular dependency detected: {}".format(exception))
        except LookupError:
            pass
        except tox.exception.ConfigError as exception:
            reporter.error(str(exception))
        raise SystemExit(1)
Example #12
0
def wheel_build_legacy(config, session, venv):
    setup = config.setupdir.join("setup.py")
    if not setup.check():
        reporter.error(
            "No setup.py file found. The expected location is: {}".format(
                setup))
        raise SystemExit(1)
    with session.newaction(venv.name, "packaging") as action:
        with patch(venv, "is_allowed_external",
                   partial(wheel_is_allowed_external, venv=venv)):
            venv.update(action=action)
            if not (session.config.option.wheel_dirty
                    or venv.envconfig.wheel_dirty):
                action.setactivity("wheel-make",
                                   "cleaning up build directory ...")
                ensure_empty_dir(config.setupdir.join("build"))
            ensure_empty_dir(config.distdir)
            venv.test(
                name="wheel-make",
                commands=[[
                    "python", setup, "bdist_wheel", "--dist-dir",
                    config.distdir
                ]],
                redirect=False,
                ignore_outcome=False,
                ignore_errors=False,
                display_hash_seed=False,
            )
        try:
            dists = config.distdir.listdir()
        except py.error.ENOENT:
            # check if empty or comment only
            data = []
            with open(str(setup)) as fp:
                for line in fp:
                    if line and line[0] == "#":
                        continue
                    data.append(line)
            if not "".join(data).strip():
                reporter.error("setup.py is empty")
                raise SystemExit(1)
            reporter.error(
                "No dist directory found. Please check setup.py, e.g with:\n"
                "     python setup.py bdist_wheel")
            raise SystemExit(1)
        else:
            if not dists:
                reporter.error(
                    "No distributions found in the dist directory found. Please check setup.py, e.g with:\n"
                    "     python setup.py bdist_wheel")
                raise SystemExit(1)
            return dists[0]
Example #13
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
Example #14
0
def start_container(image, mount_local=None, mount_to=None):
    try:
        container = CLIENT.containers.create(
            image,
            command=["sleep", "infinity"],
            auto_remove=False,
            detach=True,
            network_mode="host",
            volumes={mount_local: {"bind": str(mount_to), "mode": "Z"}}
            if mount_to and mount_local
            else None,
        )
    except Exception as exception:
        reporter.error(repr(exception))
        raise
    reporter.verbosity1(
        f"start container via {container.short_id} ({container.attrs['Name']}) based on {image}"
    )
    container.start()
    return container
Example #15
0
def main(args):
    setup_reporter(args)
    try:
        config = load_config(args)
        update_default_reporter(config.option.quiet_level,
                                config.option.verbose_level)
        reporter.using("tox.ini: {}".format(config.toxinipath))
        config.logdir.ensure(dir=1)
        ensure_empty_dir(config.logdir)
        with set_os_env_var("TOX_WORK_DIR", config.toxworkdir):
            retcode = build_session(config).runcommand()
        if retcode is None:
            retcode = 0
        raise SystemExit(retcode)
    except KeyboardInterrupt:
        raise SystemExit(2)
    except (tox.exception.MinVersionError,
            tox.exception.MissingRequirement) as exception:
        reporter.error(str(exception))
        raise SystemExit(1)
Example #16
0
File: plugin.py Project: gavz/sn4ke
def wheel_build_pep517(config, session, venv):
    pyproject = config.setupdir.join("pyproject.toml")
    if not pyproject.check():
        reporter.error(
            "No pyproject.toml file found. The expected location is: {}".
            format(pyproject))
        raise SystemExit(1)
    with session.newaction(venv.name, "packaging") as action:
        venv.update(action=action)
        ensure_empty_dir(config.distdir)
        venv.test(
            name="wheel-make",
            commands=[[
                "pip", "wheel", config.setupdir, "--no-deps", "--use-pep517",
                "--wheel-dir", config.distdir
            ]],
            redirect=False,
            ignore_outcome=False,
            ignore_errors=False,
            display_hash_seed=False,
        )
        try:
            dists = config.distdir.listdir()
        except py.error.ENOENT:
            reporter.error(
                "No dist directory found. Please check pyproject.toml, e.g with:\n"
                "     pip wheel . --use-pep517")
            raise SystemExit(1)
        else:
            if not dists:
                reporter.error(
                    "No distributions found in the dist directory found. Please check pyproject.toml, e.g with:\n"
                    "     pip wheel . --use-pep517")
                raise SystemExit(1)
            return dists[0]
Example #17
0
def get_build_info(folder):
    toml_file = folder.join("pyproject.toml")

    # as per https://www.python.org/dev/peps/pep-0517/

    def abort(message):
        reporter.error("{} inside {}".format(message, toml_file))
        raise SystemExit(1)

    if not toml_file.exists():
        reporter.error("missing {}".format(toml_file))
        raise SystemExit(1)

    config_data = get_py_project_toml(toml_file)

    if "build-system" not in config_data:
        abort("build-system section missing")

    build_system = config_data["build-system"]

    if "requires" not in build_system:
        abort("missing requires key at build-system section")
    if "build-backend" not in build_system:
        abort("missing build-backend key at build-system section")

    requires = build_system["requires"]
    if not isinstance(requires, list) or not all(
        isinstance(i, six.text_type) for i in requires
    ):
        abort("requires key at build-system section must be a list of string")

    backend = build_system["build-backend"]
    if not isinstance(backend, six.text_type):
        abort("build-backend key at build-system section must be a string")

    args = backend.split(":")
    module = args[0]
    obj = args[1] if len(args) > 1 else ""

    return BuildInfo(requires, module, obj)
Example #18
0
 def feed_stdin(self, fin, process, redirect):
     try:
         if self.generate_tox_log and not redirect:
             if process.stderr is not None:
                 # prevent deadlock
                 raise ValueError("stderr must not be piped here")
             # we read binary from the process and must write using a binary stream
             buf = getattr(sys.stdout, "buffer", sys.stdout)
             out = None
             last_time = time.time()
             while True:
                 # we have to read one byte at a time, otherwise there
                 # might be no output for a long time with slow tests
                 data = fin.read(1)
                 if data:
                     buf.write(data)
                     if b"\n" in data or (time.time() - last_time) > 1:
                         # we flush on newlines or after 1 second to
                         # provide quick enough feedback to the user
                         # when printing a dot per test
                         buf.flush()
                         last_time = time.time()
                 elif process.poll() is not None:
                     if process.stdout is not None:
                         process.stdout.close()
                     break
                 else:
                     time.sleep(0.1)
                     # the seek updates internal read buffers
                     fin.seek(0, 1)
             fin.close()
         else:
             out, err = process.communicate()
     except KeyboardInterrupt:
         reporter.error("KEYBOARDINTERRUPT")
         process.wait()
         raise
     return out
Example #19
0
def build_image(venv, context, action):
    create_docker_file(context, venv)
    # host -> Linux access local pip
    generator = CLIENT.api.build(path=str(context),
                                 rm=True,
                                 network_mode="host")
    image_id = None
    while True:
        output = None
        try:
            output = next(generator)
            message = ""
            for fragment in output.decode().split("\r\n"):
                if fragment:
                    msg = json.loads(fragment)
                    if "stream" in msg:
                        msg = msg["stream"]
                        match = re.search(
                            r"(^Successfully built |sha256:)([0-9a-f]+)$", msg)
                        if match:
                            image_id = match.group(2)
                    else:
                        msg = fragment
                    message += msg
            message = "".join(message).strip("\n")
            reporter.verbosity1(message)
        except StopIteration:
            reporter.info("Docker image build complete.")
            break
        except ValueError:  # pragma: no cover
            reporter.error(
                "Error parsing output from docker image build: {}".format(
                    output))  # pragma: no cover
    if image_id is None:
        raise InvocationError("docker image build failed")  # pragma: no cover
    _BUILT_IMAGES.add(image_id)
    return image_id
Example #20
0
 def popen(
     self,
     args,
     cwd=None,
     env=None,
     redirect=True,
     returnout=False,
     ignore_ret=False,
     capture_err=True,
 ):
     """this drives an interaction with a subprocess"""
     cmd_args = [str(x) for x in args]
     cmd_args_shell = " ".join(pipes.quote(i) for i in cmd_args)
     stream_getter = self._get_standard_streams(capture_err, cmd_args_shell,
                                                redirect, returnout)
     cwd = os.getcwd() if cwd is None else cwd
     with stream_getter as (fin, out_path, stderr, stdout):
         try:
             args = self._rewrite_args(cwd, args)
             process = self.via_popen(
                 args,
                 stdout=stdout,
                 stderr=stderr,
                 cwd=str(cwd),
                 env=os.environ.copy() if env is None else env,
                 universal_newlines=True,
                 shell=False,
             )
         except OSError as e:
             reporter.error(
                 "invocation failed (errno {:d}), args: {}, cwd: {}".format(
                     e.errno, cmd_args_shell, cwd))
             raise
         reporter.log_popen(cwd, out_path, cmd_args_shell)
         output = self.feed_stdin(fin, process, redirect)
         exit_code = process.wait()
     if exit_code and not ignore_ret:
         invoked = " ".join(map(str, args))
         if out_path:
             reporter.error(
                 "invocation failed (exit code {:d}), logfile: {}".format(
                     exit_code, out_path))
             output = out_path.read()
             reporter.error(output)
             self.command_log.add_command(args, output, exit_code)
             raise InvocationError(invoked, exit_code, out_path)
         else:
             raise InvocationError(invoked, exit_code)
     if not output and out_path:
         output = out_path.read()
     self.command_log.add_command(args, output, exit_code)
     return output
Example #21
0
def make_sdist(config, session):
    setup = config.setupdir.join("setup.py")
    if not setup.check():
        reporter.error(
            "No setup.py file found. The expected location is:\n"
            "  {}\n"
            "You can\n"
            "  1. Create one:\n"
            "     https://packaging.python.org/tutorials/distributing-packages/#setup-py\n"
            "  2. Configure tox to avoid running sdist:\n"
            "     https://tox.readthedocs.io/en/latest/example/general.html"
            "#avoiding-expensive-sdist".format(setup)
        )
        raise SystemExit(1)
    with session.newaction("GLOB", "packaging") as action:
        action.setactivity("sdist-make", setup)
        ensure_empty_dir(config.distdir)
        build_log = action.popen(
            [sys.executable, setup, "sdist", "--formats=zip", "--dist-dir", config.distdir],
            cwd=config.setupdir,
            returnout=True,
        )
        reporter.verbosity2(build_log)
        try:
            return config.distdir.listdir()[0]
        except py.error.ENOENT:
            # check if empty or comment only
            data = []
            with open(str(setup)) as fp:
                for line in fp:
                    if line and line[0] == "#":
                        continue
                    data.append(line)
            if not "".join(data).strip():
                reporter.error("setup.py is empty")
                raise SystemExit(1)
            reporter.error(
                "No dist directory found. Please check setup.py, e.g with:\n"
                "     python setup.py sdist"
            )
            raise SystemExit(1)
Example #22
0
 def popen(
     self,
     args,
     cwd=None,
     env=None,
     redirect=True,
     returnout=False,
     ignore_ret=False,
     capture_err=True,
     callback=None,
     report_fail=True,
 ):
     """this drives an interaction with a subprocess"""
     cwd = py.path.local() if cwd is None else cwd
     cmd_args = [str(x) for x in self._rewrite_args(cwd, args)]
     cmd_args_shell = " ".join(pipes.quote(i) for i in cmd_args)
     stream_getter = self._get_standard_streams(
         capture_err,
         cmd_args_shell,
         redirect,
         returnout,
         cwd,
     )
     exit_code, output = None, None
     with stream_getter as (fin, out_path, stderr, stdout):
         try:
             process = self.via_popen(
                 cmd_args,
                 stdout=stdout,
                 stderr=stderr,
                 cwd=str(cwd),
                 env=os.environ.copy() if env is None else env,
                 universal_newlines=True,
                 shell=False,
                 creationflags=(
                     subprocess.CREATE_NEW_PROCESS_GROUP
                     if sys.platform == "win32" else 0
                     # needed for Windows signal send ability (CTRL+C)
                 ),
             )
         except OSError as exception:
             exit_code = exception.errno
         else:
             if callback is not None:
                 callback(process)
             reporter.log_popen(cwd, out_path, cmd_args_shell, process.pid)
             output = self.evaluate_cmd(fin, process, redirect)
             exit_code = process.returncode
         finally:
             if out_path is not None and out_path.exists():
                 lines = out_path.read_text("UTF-8").split("\n")
                 # first three lines are the action, cwd, and cmd - remove it
                 output = "\n".join(lines[3:])
             try:
                 if exit_code and not ignore_ret:
                     if report_fail:
                         msg = "invocation failed (exit code {:d})".format(
                             exit_code)
                         if out_path is not None:
                             msg += ", logfile: {}".format(out_path)
                             if not out_path.exists():
                                 msg += " warning log file missing"
                         reporter.error(msg)
                         if out_path is not None and out_path.exists():
                             reporter.separator("=", "log start",
                                                Verbosity.QUIET)
                             reporter.quiet(output)
                             reporter.separator("=", "log end",
                                                Verbosity.QUIET)
                     raise InvocationError(cmd_args_shell, exit_code,
                                           output)
             finally:
                 self.command_log.add_command(cmd_args, output, exit_code)
     return output
Example #23
0
 def sigterm_handler(signum, frame):
     reporter.error("Got SIGTERM, handling it as a KeyboardInterrupt")
     raise KeyboardInterrupt()
Example #24
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
 def abort(message):
     reporter.error("{} inside {}".format(message, toml_file))
     raise SystemExit(1)