Ejemplo n.º 1
0
def is_installable_file(path):
    """Determine if a path can potentially be installed"""
    from .vendor.pip_shims.shims import is_installable_dir, is_archive_file
    from .patched.notpip._internal.utils.packaging import specifiers
    from ._compat import Path

    if hasattr(path, "keys") and any(
            key for key in path.keys() if key in ["file", "path"]):
        path = urlparse(path["file"]).path if "file" in path else path["path"]
    if not isinstance(path, six.string_types) or path == "*":
        return False

    # If the string starts with a valid specifier operator, test if it is a valid
    # specifier set before making a path object (to avoid breaking windows)
    if any(path.startswith(spec) for spec in "!=<>~"):
        try:
            specifiers.SpecifierSet(path)
        # If this is not a valid specifier, just move on and try it as a path
        except specifiers.InvalidSpecifier:
            pass
        else:
            return False

    if not os.path.exists(os.path.abspath(path)):
        return False

    lookup_path = Path(path)
    absolute_path = "{0}".format(lookup_path.absolute())
    if lookup_path.is_dir() and is_installable_dir(absolute_path):
        return True

    elif lookup_path.is_file() and is_archive_file(absolute_path):
        return True

    return False
Ejemplo n.º 2
0
def load_path(python):
    from ._compat import Path
    import delegator
    import json
    python = Path(python).as_posix()
    json_dump_commmand = '"import json, sys; print(json.dumps(sys.path));"'
    c = delegator.run('"{0}" -c {1}'.format(python, json_dump_commmand))
    if c.return_code == 0:
        return json.loads(c.out.strip())
    else:
        return []
Ejemplo n.º 3
0
def chdir(path):
    """Context manager to change working directories."""
    from ._compat import Path
    if not path:
        return
    prev_cwd = Path.cwd().as_posix()
    if isinstance(path, Path):
        path = path.as_posix()
    os.chdir(str(path))
    try:
        yield
    finally:
        os.chdir(prev_cwd)
Ejemplo n.º 4
0
def get_workon_home():
    from ._compat import Path

    workon_home = os.environ.get("WORKON_HOME")
    if not workon_home:
        if os.name == "nt":
            workon_home = "~/.virtualenvs"
        else:
            workon_home = os.path.join(
                os.environ.get("XDG_DATA_HOME", "~/.local/share"),
                "virtualenvs")
    # Create directory if it does not already exist
    expanded_path = Path(os.path.expandvars(workon_home)).expanduser()
    mkdir_p(str(expanded_path))
    return expanded_path
Ejemplo n.º 5
0
    def inject_path(self, venv):
        from ._compat import NamedTemporaryFile

        bashrc_path = Path.home().joinpath(".bashrc")
        with NamedTemporaryFile("w+") as rcfile:
            if bashrc_path.is_file():
                base_rc_src = f'source "{bashrc_path.as_posix()}"\n'
                rcfile.write(base_rc_src)

            export_path = 'export PATH="{}:$PATH"\n'.format(":".join(
                self._format_path(python) for python in _iter_python(venv)))
            rcfile.write(export_path)
            rcfile.flush()
            self.args.extend(["--rcfile", rcfile.name])
            yield
Ejemplo n.º 6
0
        def _should_include_hash(ireq):
            from pipenv.vendor.vistir.compat import Path, to_native_string
            from pipenv.vendor.vistir.path import url_to_path

            # We can only hash artifacts.
            try:
                if not ireq.link.is_artifact:
                    return False
            except AttributeError:
                return False

            # But we don't want normal pypi artifcats since the normal resolver
            # handles those
            if is_pypi_url(ireq.link.url):
                return False

            # We also don't want to try to hash directories as this will fail
            # as these are editable deps and are not hashable.
            if (ireq.link.scheme == "file" and Path(
                    to_native_string(url_to_path(ireq.link.url))).is_dir()):
                return False
            return True
Ejemplo n.º 7
0
def venv_resolve_deps(deps,
                      which,
                      project,
                      pre=False,
                      clear=False,
                      allow_global=False,
                      pypi_mirror=None,
                      dev=False,
                      pipfile=None,
                      lockfile=None):
    from .vendor.vistir.misc import fs_str
    from .vendor.vistir.compat import Path, to_native_string, JSONDecodeError
    from .vendor.vistir.path import create_tracked_tempdir
    from . import resolver
    import json

    vcs_deps = []
    vcs_lockfile = {}
    results = []
    pipfile_section = "dev_packages" if dev else "packages"
    lockfile_section = "develop" if dev else "default"
    vcs_section = "vcs_{0}".format(pipfile_section)
    vcs_deps = getattr(project, vcs_section, [])
    if not deps and not vcs_deps:
        return {}

    if not pipfile:
        pipfile = getattr(project, pipfile_section, None)
    if not lockfile:
        lockfile = project._lockfile
    req_dir = create_tracked_tempdir(prefix="pipenv", suffix="requirements")
    if vcs_deps:
        with create_spinner(text=fs_str("Pinning VCS Packages...")) as sp:
            vcs_reqs, vcs_lockfile = get_vcs_deps(
                project,
                which=which,
                clear=clear,
                pre=pre,
                allow_global=allow_global,
                dev=dev,
            )
            vcs_deps = [req.as_line() for req in vcs_reqs if req.editable]
    cmd = [
        which("python", allow_global=allow_global),
        Path(resolver.__file__.rstrip("co")).as_posix()
    ]
    if pre:
        cmd.append("--pre")
    if clear:
        cmd.append("--clear")
    if allow_global:
        cmd.append("--system")
    with temp_environ():
        os.environ = {fs_str(k): fs_str(val) for k, val in os.environ.items()}
        os.environ["PIPENV_PACKAGES"] = str("\n".join(deps))
        if pypi_mirror:
            os.environ["PIPENV_PYPI_MIRROR"] = str(pypi_mirror)
        os.environ["PIPENV_VERBOSITY"] = str(environments.PIPENV_VERBOSITY)
        os.environ["PIPENV_REQ_DIR"] = fs_str(req_dir)
        os.environ["PIP_NO_INPUT"] = fs_str("1")
        with create_spinner(text=fs_str("Locking...")) as sp:
            c = resolve(cmd, sp)
            results = c.out
            if vcs_deps:
                with temp_environ():
                    os.environ["PIPENV_PACKAGES"] = str("\n".join(vcs_deps))
                    sp.text = to_native_string("Locking VCS Dependencies...")
                    vcs_c = resolve(cmd, sp)
                    vcs_results, vcs_err = vcs_c.out, vcs_c.err
            else:
                vcs_results, vcs_err = "", ""
            sp.green.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
    outputs = [results, vcs_results]
    if environments.is_verbose():
        for output in outputs:
            click_echo(output.split("RESULTS:")[0], err=True)
    try:
        results = json.loads(results.split("RESULTS:")[1].strip())
        if vcs_results:
            # For vcs dependencies, treat the initial pass at locking (i.e. checkout)
            # as the pipfile entry because it gets us an actual ref to use
            vcs_results = json.loads(vcs_results.split("RESULTS:")[1].strip())
            vcs_lockfile = prepare_lockfile(vcs_results, vcs_lockfile.copy(),
                                            vcs_lockfile)
        else:
            vcs_results = []

    except (IndexError, JSONDecodeError):
        for out, err in [(c.out, c.err), (vcs_results, vcs_err)]:
            click_echo(out.strip(), err=True)
            click_echo(err.strip(), err=True)
        raise RuntimeError("There was a problem with locking.")
    lockfile[lockfile_section] = prepare_lockfile(results, pipfile,
                                                  lockfile[lockfile_section])
    lockfile[lockfile_section].update(vcs_lockfile)
Ejemplo n.º 8
0
def path_to_url(path):
    from ._compat import Path

    return Path(normalize_drive(os.path.abspath(path))).as_uri()
Ejemplo n.º 9
0
def _iter_python(venv):
    for path in POSSIBLE_ENV_PYTHON:
        full_path = Path(venv, path)
        if full_path.is_file():
            yield full_path
Ejemplo n.º 10
0
        # Handler for terminal resizing events
        # Must be defined here to have the shell process in its context, since
        # we can't pass it as an argument
        def sigwinch_passthrough(sig, data):
            dims = get_terminal_size()
            c.setwinsize(dims.lines, dims.columns)

        signal.signal(signal.SIGWINCH, sigwinch_passthrough)

        # Interact with the new shell.
        c.interact(escape_character=None)
        c.close()
        sys.exit(c.exitstatus)


POSSIBLE_ENV_PYTHON = [Path("bin", "python"), Path("Scripts", "python.exe")]


def _iter_python(venv):
    for path in POSSIBLE_ENV_PYTHON:
        full_path = Path(venv, path)
        if full_path.is_file():
            yield full_path


class Bash(Shell):
    def _format_path(self, python):
        return python.parent.as_posix()

    # The usual PATH injection technique does not work with Bash.
    # https://github.com/berdario/pew/issues/58#issuecomment-102182346
Ejemplo n.º 11
0
def venv_resolve_deps(
    deps,
    which,
    project,
    pre=False,
    clear=False,
    allow_global=False,
    pypi_mirror=None,
    dev=False,
    pipfile=None,
    lockfile=None,
    keep_outdated=False,
):
    """
    Resolve dependencies for a pipenv project, acts as a portal to the target environment.

    Regardless of whether a virtual environment is present or not, this will spawn
    a subprocess which is isolated to the target environment and which will perform
    dependency resolution.  This function reads the output of that call and mutates
    the provided lockfile accordingly, returning nothing.

    :param List[:class:`~requirementslib.Requirement`] deps: A list of dependencies to resolve.
    :param Callable which: [description]
    :param project: The pipenv Project instance to use during resolution
    :param Optional[bool] pre: Whether to resolve pre-release candidates, defaults to False
    :param Optional[bool] clear: Whether to clear the cache during resolution, defaults to False
    :param Optional[bool] allow_global: Whether to use *sys.executable* as the python binary, defaults to False
    :param Optional[str] pypi_mirror: A URL to substitute any time *pypi.org* is encountered, defaults to None
    :param Optional[bool] dev: Whether to target *dev-packages* or not, defaults to False
    :param pipfile: A Pipfile section to operate on, defaults to None
    :type pipfile: Optional[Dict[str, Union[str, Dict[str, bool, List[str]]]]]
    :param Dict[str, Any] lockfile: A project lockfile to mutate, defaults to None
    :param bool keep_outdated: Whether to retain outdated dependencies and resolve with them in mind, defaults to False
    :raises RuntimeError: Raised on resolution failure
    :return: Nothing
    :rtype: None
    """

    import json
    import tempfile

    from pipenv import resolver
    from pipenv._compat import decode_for_output
    from pipenv.vendor.vistir.compat import Path

    results = []
    pipfile_section = "dev-packages" if dev else "packages"
    lockfile_section = "develop" if dev else "default"
    if not deps:
        if not project.pipfile_exists:
            return None
        deps = project.parsed_pipfile.get(pipfile_section, {})
    if not deps:
        return None

    if not pipfile:
        pipfile = getattr(project, pipfile_section, {})
    if not lockfile:
        lockfile = project._lockfile
    req_dir = create_tracked_tempdir(prefix="pipenv", suffix="requirements")
    cmd = [
        which("python", allow_global=allow_global),
        Path(resolver.__file__.rstrip("co")).as_posix(),
    ]
    if pre:
        cmd.append("--pre")
    if clear:
        cmd.append("--clear")
    if allow_global:
        cmd.append("--system")
    if dev:
        cmd.append("--dev")
    target_file = tempfile.NamedTemporaryFile(prefix="resolver",
                                              suffix=".json",
                                              delete=False)
    target_file.close()
    cmd.extend(["--write", make_posix(target_file.name)])
    with temp_environ():
        os.environ.update({k: str(val) for k, val in os.environ.items()})
        if pypi_mirror:
            os.environ["PIPENV_PYPI_MIRROR"] = str(pypi_mirror)
        os.environ["PIPENV_VERBOSITY"] = str(project.s.PIPENV_VERBOSITY)
        os.environ["PIPENV_REQ_DIR"] = req_dir
        os.environ["PIP_NO_INPUT"] = "1"
        pipenv_site_dir = get_pipenv_sitedir()
        if pipenv_site_dir is not None:
            os.environ["PIPENV_SITE_DIR"] = pipenv_site_dir
        else:
            os.environ.pop("PIPENV_SITE_DIR", None)
        if keep_outdated:
            os.environ["PIPENV_KEEP_OUTDATED"] = "1"
        with create_spinner(text=decode_for_output("Locking..."),
                            setting=project.s) as sp:
            # This conversion is somewhat slow on local and file-type requirements since
            # we now download those requirements / make temporary folders to perform
            # dependency resolution on them, so we are including this step inside the
            # spinner context manager for the UX improvement
            sp.write(decode_for_output("Building requirements..."))
            deps = convert_deps_to_pip(deps,
                                       project,
                                       r=False,
                                       include_index=True)
            constraints = set(deps)
            os.environ["PIPENV_PACKAGES"] = str("\n".join(constraints))
            sp.write(decode_for_output("Resolving dependencies..."))
            c = resolve(cmd, sp, project=project)
            results = c.stdout.strip()
            if c.returncode == 0:
                sp.green.ok(
                    environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
                if not project.s.is_verbose() and c.stderr.strip():
                    click_echo(crayons.yellow(f"Warning: {c.stderr.strip()}"),
                               err=True)
            else:
                sp.red.fail(
                    environments.PIPENV_SPINNER_FAIL_TEXT.format(
                        "Locking Failed!"))
                click_echo(f"Output: {c.stdout.strip()}", err=True)
                click_echo(f"Error: {c.stderr.strip()}", err=True)
    try:
        with open(target_file.name) as fh:
            results = json.load(fh)
    except (IndexError, json.JSONDecodeError):
        click_echo(c.stdout.strip(), err=True)
        click_echo(c.stderr.strip(), err=True)
        if os.path.exists(target_file.name):
            os.unlink(target_file.name)
        raise RuntimeError("There was a problem with locking.")
    if os.path.exists(target_file.name):
        os.unlink(target_file.name)
    if lockfile_section not in lockfile:
        lockfile[lockfile_section] = {}
    prepare_lockfile(results, pipfile, lockfile[lockfile_section])