mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
Merge branch 'bugfix/3148' into feature/keep-outdated-peep
Signed-off-by: Dan Ryan <dan@danryan.co>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Fixed resolution of direct-url dependencies in ``setup.py`` files to respect ``PEP-508`` style URL dependencies.
|
||||
@@ -5,9 +5,6 @@ Exposes a standard API that enables compatibility across python versions,
|
||||
operating systems, etc.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import importlib
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
+18
-16
@@ -11,15 +11,16 @@ import sys
|
||||
from distutils.sysconfig import get_python_lib
|
||||
from sysconfig import get_paths
|
||||
|
||||
import itertools
|
||||
import pkg_resources
|
||||
import six
|
||||
import vistir
|
||||
|
||||
import pipenv
|
||||
|
||||
from cached_property import cached_property
|
||||
from .vendor.cached_property import cached_property
|
||||
import vistir
|
||||
|
||||
from .utils import normalize_path
|
||||
from .utils import normalize_path, make_posix
|
||||
|
||||
|
||||
BASE_WORKING_SET = pkg_resources.WorkingSet(sys.path)
|
||||
@@ -149,7 +150,7 @@ class Environment(object):
|
||||
'stdlib': '/home/hawk/.pyenv/versions/3.7.1/lib/python3.7'}
|
||||
"""
|
||||
|
||||
prefix = self.prefix.as_posix()
|
||||
prefix = make_posix(self.prefix.as_posix())
|
||||
install_scheme = 'nt' if (os.name == 'nt') else 'posix_prefix'
|
||||
paths = get_paths(install_scheme, vars={
|
||||
'base': prefix,
|
||||
@@ -158,8 +159,8 @@ class Environment(object):
|
||||
paths["PATH"] = paths["scripts"] + os.pathsep + os.defpath
|
||||
if "prefix" not in paths:
|
||||
paths["prefix"] = prefix
|
||||
purelib = get_python_lib(plat_specific=0, prefix=prefix)
|
||||
platlib = get_python_lib(plat_specific=1, prefix=prefix)
|
||||
purelib = make_posix(get_python_lib(plat_specific=0, prefix=prefix))
|
||||
platlib = make_posix(get_python_lib(plat_specific=1, prefix=prefix))
|
||||
if purelib == platlib:
|
||||
lib_dirs = purelib
|
||||
else:
|
||||
@@ -180,7 +181,7 @@ class Environment(object):
|
||||
@property
|
||||
def python(self):
|
||||
"""Path to the environment python"""
|
||||
py = vistir.compat.Path(self.base_paths["scripts"]).joinpath("python").as_posix()
|
||||
py = vistir.compat.Path(self.base_paths["scripts"]).joinpath("python").absolute().as_posix()
|
||||
if not py:
|
||||
return vistir.compat.Path(sys.executable).as_posix()
|
||||
return py
|
||||
@@ -248,7 +249,10 @@ class Environment(object):
|
||||
"""
|
||||
|
||||
pkg_resources = self.safe_import("pkg_resources")
|
||||
return pkg_resources.find_distributions(self.paths["libdirs"])
|
||||
libdirs = self.base_paths["libdirs"].split(os.pathsep)
|
||||
dists = (pkg_resources.find_distributions(libdir) for libdir in libdirs)
|
||||
for dist in itertools.chain.from_iterable(dists):
|
||||
yield dist
|
||||
|
||||
def find_egg(self, egg_dist):
|
||||
"""Find an egg by name in the given environment"""
|
||||
@@ -276,13 +280,14 @@ class Environment(object):
|
||||
"""Determine whether the supplied distribution is in the environment."""
|
||||
from .project import _normalized
|
||||
prefixes = [
|
||||
_normalized(prefix) for prefix in self.base_paths["libdirs"]
|
||||
if _normalized(self.prefix).startswith(_normalized(prefix))
|
||||
_normalized(prefix) for prefix in self.base_paths["libdirs"].split(os.pathsep)
|
||||
if _normalized(prefix).startswith(_normalized(self.prefix.as_posix()))
|
||||
]
|
||||
location = self.locate_dist(dist)
|
||||
if not location:
|
||||
return False
|
||||
return any(_normalized(location).startswith(prefix) for prefix in prefixes)
|
||||
location = _normalized(make_posix(location))
|
||||
return any(location.startswith(prefix) for prefix in prefixes)
|
||||
|
||||
def get_installed_packages(self):
|
||||
"""Returns all of the installed packages in a given environment"""
|
||||
@@ -295,7 +300,7 @@ class Environment(object):
|
||||
|
||||
@contextlib.contextmanager
|
||||
def get_finder(self, pre=False):
|
||||
from .vendor.pip_shims import Command, cmdoptions, index_group, PackageFinder
|
||||
from .vendor.pip_shims.shims import Command, cmdoptions, index_group, PackageFinder
|
||||
from .environments import PIPENV_CACHE_DIR
|
||||
index_urls = [source.get("url") for source in self.sources]
|
||||
|
||||
@@ -667,10 +672,7 @@ class Environment(object):
|
||||
monkey_patch.activate()
|
||||
pip_shims = self.safe_import("pip_shims")
|
||||
pathset_base = pip_shims.UninstallPathSet
|
||||
import recursive_monkey_patch
|
||||
recursive_monkey_patch.monkey_patch(
|
||||
PatchedUninstaller, pathset_base
|
||||
)
|
||||
pathset_base._permitted = PatchedUninstaller._permitted
|
||||
dist = next(
|
||||
iter(filter(lambda d: d.project_name == pkgname, self.get_working_set())),
|
||||
None
|
||||
|
||||
+6
-9
@@ -20,7 +20,7 @@ from first import first
|
||||
import pipfile
|
||||
import pipfile.api
|
||||
|
||||
from cached_property import cached_property
|
||||
from .vendor.cached_property import cached_property
|
||||
|
||||
from .cmdparse import Script
|
||||
from .environment import Environment
|
||||
@@ -29,6 +29,7 @@ from .environments import (
|
||||
PIPENV_PIPFILE, PIPENV_PYTHON, PIPENV_TEST_INDEX, PIPENV_VENV_IN_PROJECT,
|
||||
is_in_virtualenv
|
||||
)
|
||||
from .vendor.requirementslib.models.utils import get_default_pyproject_backend
|
||||
from .utils import (
|
||||
cleanup_toml, convert_toml_outline_tables, find_requirements,
|
||||
get_canonical_names, get_url_name, get_workon_home, is_editable,
|
||||
@@ -340,7 +341,7 @@ class Project(object):
|
||||
prefix=prefix, is_venv=is_venv, sources=sources, pipfile=self.parsed_pipfile,
|
||||
project=self
|
||||
)
|
||||
pipenv_dist = get_pipenv_dist()
|
||||
pipenv_dist = get_pipenv_dist(pkg="pipenv")
|
||||
if pipenv_dist:
|
||||
self._environment.extend_dists(pipenv_dist)
|
||||
else:
|
||||
@@ -529,8 +530,8 @@ class Project(object):
|
||||
if not os.path.exists(self.path_to("setup.py")):
|
||||
if not build_system or not build_system.get("requires"):
|
||||
build_system = {
|
||||
"requires": ["setuptools>=38.2.5", "wheel"],
|
||||
"build-backend": "setuptools.build_meta",
|
||||
"requires": ["setuptools>=40.8.0", "wheel"],
|
||||
"build-backend": get_default_pyproject_backend(),
|
||||
}
|
||||
self._build_system = build_system
|
||||
|
||||
@@ -540,7 +541,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def build_backend(self):
|
||||
return self._build_system.get("build-backend", None)
|
||||
return self._build_system.get("build-backend", get_default_pyproject_backend())
|
||||
|
||||
@property
|
||||
def settings(self):
|
||||
@@ -607,10 +608,8 @@ class Project(object):
|
||||
|
||||
def _get_editable_packages(self, dev=False):
|
||||
section = "dev-packages" if dev else "packages"
|
||||
# section = "{0}-editable".format(section)
|
||||
packages = {
|
||||
k: v
|
||||
# for k, v in self._pipfile[section].items()
|
||||
for k, v in self.parsed_pipfile.get(section, {}).items()
|
||||
if is_editable(k) or is_editable(v)
|
||||
}
|
||||
@@ -619,10 +618,8 @@ class Project(object):
|
||||
def _get_vcs_packages(self, dev=False):
|
||||
from pipenv.vendor.requirementslib.utils import is_vcs
|
||||
section = "dev-packages" if dev else "packages"
|
||||
# section = "{0}-vcs".format(section)
|
||||
packages = {
|
||||
k: v
|
||||
# for k, v in self._pipfile[section].items()
|
||||
for k, v in self.parsed_pipfile.get(section, {}).items()
|
||||
if is_vcs(v) or is_vcs(k)
|
||||
}
|
||||
|
||||
+51
-7
@@ -3,6 +3,7 @@ import contextlib
|
||||
import errno
|
||||
import logging
|
||||
import os
|
||||
import posixpath
|
||||
import re
|
||||
import shutil
|
||||
import stat
|
||||
@@ -22,8 +23,8 @@ six.add_move(six.MovedAttribute("Sequence", "collections", "collections.abc"))
|
||||
six.add_move(six.MovedAttribute("Set", "collections", "collections.abc")) # noqa
|
||||
from six.moves import Mapping, Sequence, Set
|
||||
from six.moves.urllib.parse import urlparse
|
||||
from vistir.compat import ResourceWarning, lru_cache
|
||||
from vistir.misc import fs_str
|
||||
from .vendor.vistir.compat import ResourceWarning, lru_cache
|
||||
from .vendor.vistir.misc import fs_str
|
||||
|
||||
import crayons
|
||||
import parse
|
||||
@@ -35,7 +36,7 @@ from .vendor.urllib3 import util as urllib3_util
|
||||
|
||||
|
||||
if environments.MYPY_RUNNING:
|
||||
from typing import Tuple, Dict, Any, List, Union, Optional
|
||||
from typing import Tuple, Dict, Any, List, Union, Optional, Text
|
||||
from .vendor.requirementslib.models.requirements import Requirement, Line
|
||||
from .project import Project
|
||||
|
||||
@@ -280,7 +281,7 @@ class Resolver(object):
|
||||
@staticmethod
|
||||
@lru_cache()
|
||||
def _get_pip_command():
|
||||
from pip_shims.shims import Command
|
||||
from .vendor.pip_shims.shims import Command
|
||||
|
||||
class PipCommand(Command):
|
||||
"""Needed for pip-tools."""
|
||||
@@ -775,7 +776,7 @@ def create_spinner(text, nospin=None, spinner_name=None):
|
||||
|
||||
|
||||
def resolve(cmd, sp):
|
||||
from .vendor import delegator
|
||||
import delegator
|
||||
from .cmdparse import Script
|
||||
from .vendor.pexpect.exceptions import EOF, TIMEOUT
|
||||
from .vendor.vistir.compat import to_native_string
|
||||
@@ -1506,7 +1507,7 @@ def handle_remove_readonly(func, path, exc):
|
||||
warnings.warn(default_warning_message.format(path), ResourceWarning)
|
||||
return
|
||||
|
||||
raise
|
||||
raise exc
|
||||
|
||||
|
||||
def escape_cmd(cmd):
|
||||
@@ -1789,7 +1790,22 @@ def add_to_set(original_set, element):
|
||||
|
||||
def is_url_equal(url, other_url):
|
||||
# type: (str, str) -> bool
|
||||
"""Compare two urls by scheme, host, and path, ignoring auth"""
|
||||
"""
|
||||
Compare two urls by scheme, host, and path, ignoring auth
|
||||
|
||||
:param str url: The initial URL to compare
|
||||
:param str url: Second url to compare to the first
|
||||
:return: Whether the URLs are equal without **auth**, **query**, and **fragment**
|
||||
:rtype: bool
|
||||
|
||||
>>> is_url_equal("https://user:pass@mydomain.com/some/path?some_query",
|
||||
"https://user2:pass2@mydomain.com/some/path")
|
||||
True
|
||||
|
||||
>>> is_url_equal("https://user:pass@mydomain.com/some/path?some_query",
|
||||
"https://mydomain.com/some?some_query")
|
||||
False
|
||||
"""
|
||||
if not isinstance(url, six.string_types):
|
||||
raise TypeError("Expected string for url, received {0!r}".format(url))
|
||||
if not isinstance(other_url, six.string_types):
|
||||
@@ -1801,6 +1817,34 @@ def is_url_equal(url, other_url):
|
||||
return unparsed == unparsed_other
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def make_posix(path):
|
||||
# type: (str) -> str
|
||||
"""
|
||||
Convert a path with possible windows-style separators to a posix-style path
|
||||
(with **/** separators instead of **\\** separators).
|
||||
|
||||
:param Text path: A path to convert.
|
||||
:return: A converted posix-style path
|
||||
:rtype: Text
|
||||
|
||||
>>> make_posix("c:/users/user/venvs/some_venv\\Lib\\site-packages")
|
||||
"c:/users/user/venvs/some_venv/Lib/site-packages"
|
||||
|
||||
>>> make_posix("c:\\users\\user\\venvs\\some_venv")
|
||||
"c:/users/user/venvs/some_venv"
|
||||
"""
|
||||
if not isinstance(path, six.string_types):
|
||||
raise TypeError("Expected a string for path, received {0!r}...".format(path))
|
||||
starts_with_sep = path.startswith(os.path.sep)
|
||||
separated = normalize_path(path).split(os.path.sep)
|
||||
if isinstance(separated, (list, tuple)):
|
||||
path = posixpath.join(*separated)
|
||||
if starts_with_sep:
|
||||
path = "/{0}".format(path)
|
||||
return path
|
||||
|
||||
|
||||
def get_pipenv_dist(pkg="pipenv", pipenv_site=None):
|
||||
from .resolver import find_site_path
|
||||
pipenv_libdir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
+47
-17
@@ -22,6 +22,7 @@ from urllib3.util import parse_url as urllib3_parse
|
||||
from pipenv.utils import mkdir_p
|
||||
from pipenv.vendor.vistir.compat import NamedTemporaryFile, TemporaryDirectory
|
||||
from pipenv.vendor.vistir.contextmanagers import open_file
|
||||
import pipenv.vendor.parse as parse
|
||||
|
||||
|
||||
TASK_NAME = 'update'
|
||||
@@ -458,19 +459,21 @@ def packages_missing_licenses(ctx, vendor_dir=None, requirements_file='vendor.tx
|
||||
possible_pkgs.append(LIBRARY_DIRNAMES[pkg])
|
||||
for pkgpath in possible_pkgs:
|
||||
pkgpath = vendor_dir.joinpath(pkgpath)
|
||||
py_path = pkgpath.parent / "{0}.py".format(pkgpath.stem)
|
||||
if pkgpath.exists() and pkgpath.is_dir():
|
||||
for licensepath in LICENSES:
|
||||
licensepath = pkgpath.joinpath(licensepath)
|
||||
if licensepath.exists():
|
||||
for license_path in LICENSES:
|
||||
license_path = pkgpath.joinpath(license_path)
|
||||
if license_path.exists():
|
||||
match_found = True
|
||||
# log("%s: Trying path %s... FOUND" % (pkg, licensepath))
|
||||
# log("%s: Trying path %s... FOUND" % (pkg, license_path))
|
||||
break
|
||||
elif (pkgpath.exists() or pkgpath.parent.joinpath("{0}.py".format(pkgpath.stem)).exists()):
|
||||
for licensepath in LICENSES:
|
||||
licensepath = pkgpath.parent.joinpath("{0}.{1}".format(pkgpath.stem, licensepath))
|
||||
if licensepath.exists():
|
||||
elif pkgpath.exists() or py_path.exists():
|
||||
for license_path in LICENSES:
|
||||
license_name = "{0}.{1}".format(pkgpath.stem, license_path)
|
||||
license_path = pkgpath.parent / license_name
|
||||
if license_path.exists():
|
||||
match_found = True
|
||||
# log("%s: Trying path %s... FOUND" % (pkg, licensepath))
|
||||
# log("%s: Trying path %s... FOUND" % (pkg, license_path))
|
||||
break
|
||||
if match_found:
|
||||
break
|
||||
@@ -483,7 +486,10 @@ def packages_missing_licenses(ctx, vendor_dir=None, requirements_file='vendor.tx
|
||||
|
||||
|
||||
@invoke.task
|
||||
def download_licenses(ctx, vendor_dir=None, requirements_file='vendor.txt', package=None, only=False, patched=False):
|
||||
def download_licenses(
|
||||
ctx, vendor_dir=None, requirements_file='vendor.txt', package=None, only=False,
|
||||
patched=False
|
||||
):
|
||||
log('Downloading licenses')
|
||||
if not vendor_dir:
|
||||
if patched:
|
||||
@@ -509,13 +515,37 @@ def download_licenses(ctx, vendor_dir=None, requirements_file='vendor.txt', pack
|
||||
requirement = package
|
||||
tmp_dir = vendor_dir / '__tmp__'
|
||||
# TODO: Fix this whenever it gets sorted out (see https://github.com/pypa/pip/issues/5739)
|
||||
cmd = "pip download --no-binary :all: --only-binary requests_download --no-deps"
|
||||
enum_cmd = "pip download --no-deps"
|
||||
ctx.run('pip install flit') # needed for the next step
|
||||
ctx.run(
|
||||
'pip download --no-binary :all: --only-binary requests_download --no-build-isolation --no-deps -d {0} {1}'.format(
|
||||
tmp_dir.as_posix(),
|
||||
requirement,
|
||||
)
|
||||
)
|
||||
for req in requirements_file.read_text().splitlines():
|
||||
if req.startswith("enum34"):
|
||||
exe_cmd = "{0} -d {1} {2}".format(enum_cmd, tmp_dir.as_posix(), req)
|
||||
else:
|
||||
exe_cmd = "{0} --no-build-isolation --no-use-pep517 -d {1} {2}".format(
|
||||
cmd, tmp_dir.as_posix(), req
|
||||
)
|
||||
try:
|
||||
ctx.run(exe_cmd)
|
||||
except invoke.exceptions.UnexpectedExit as e:
|
||||
if "Disabling PEP 517 processing is invalid" not in e.result.stderr:
|
||||
log("WARNING: Failed to download license for {0}".format(req))
|
||||
continue
|
||||
parse_target = (
|
||||
"Disabling PEP 517 processing is invalid: project specifies a build "
|
||||
"backend of {backend} in pyproject.toml"
|
||||
)
|
||||
target = parse.parse(parse_target, e.result.stderr.strip())
|
||||
backend = target.named.get("backend")
|
||||
if backend is not None:
|
||||
if "." in backend:
|
||||
backend, _, _ = backend.partition(".")
|
||||
ctx.run("pip install {0}".format(backend))
|
||||
ctx.run(
|
||||
"{0} --no-build-isolation -d {1} {2}".format(
|
||||
cmd, tmp_dir.as_posix(), req
|
||||
)
|
||||
)
|
||||
for sdist in tmp_dir.iterdir():
|
||||
extract_license(vendor_dir, sdist)
|
||||
new_requirements_file.unlink()
|
||||
@@ -527,7 +557,7 @@ def extract_license(vendor_dir, sdist):
|
||||
ext = sdist.suffix[1:]
|
||||
with tarfile.open(sdist, mode='r:{}'.format(ext)) as tar:
|
||||
found = find_and_extract_license(vendor_dir, tar, tar.getmembers())
|
||||
elif sdist.suffix == '.zip':
|
||||
elif sdist.suffix in ('.zip', '.whl'):
|
||||
with zipfile.ZipFile(sdist) as zip:
|
||||
found = find_and_extract_license(vendor_dir, zip, zip.infolist())
|
||||
else:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding=utf-8 -*-
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
@@ -7,7 +8,7 @@ import pytest
|
||||
|
||||
from vistir.compat import ResourceWarning, fs_str
|
||||
from vistir.contextmanagers import temp_environ
|
||||
from vistir.path import mkdir_p
|
||||
from vistir.path import mkdir_p, create_tracked_tempdir
|
||||
|
||||
from pipenv._compat import Path, TemporaryDirectory
|
||||
from pipenv.exceptions import VirtualenvActivationException
|
||||
@@ -80,6 +81,10 @@ def pytest_runtest_setup(item):
|
||||
pytest.skip('requires github ssh')
|
||||
if item.get_marker('needs_hg') is not None and not WE_HAVE_HG:
|
||||
pytest.skip('requires mercurial')
|
||||
if item.get_marker('skip_py27_win') is not None and (
|
||||
sys.version_info[:2] <= (2, 7) and os.name == "nt"
|
||||
):
|
||||
pytest.skip('must use python > 2.7 on windows')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -91,9 +96,33 @@ def pathlib_tmpdir(request, tmpdir):
|
||||
pass
|
||||
|
||||
|
||||
def _create_tracked_dir():
|
||||
tmp_location = os.environ.get("TEMP", os.environ.get("TMP"))
|
||||
temp_args = {"prefix": "pipenv-", "suffix": "-test"}
|
||||
if tmp_location is not None:
|
||||
temp_args["dir"] = tmp_location
|
||||
temp_path = create_tracked_tempdir(**temp_args)
|
||||
return temp_path
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vistir_tmpdir():
|
||||
temp_path = _create_tracked_dir()
|
||||
yield Path(temp_path)
|
||||
|
||||
|
||||
@pytest.fixture(name='create_tmpdir')
|
||||
def vistir_tmpdir_factory():
|
||||
|
||||
def create_tmpdir():
|
||||
return Path(_create_tracked_dir())
|
||||
|
||||
yield create_tmpdir
|
||||
|
||||
|
||||
# Borrowed from pip's test runner filesystem isolation
|
||||
@pytest.fixture(autouse=True)
|
||||
def isolate(pathlib_tmpdir):
|
||||
def isolate(create_tmpdir):
|
||||
"""
|
||||
Isolate our tests so that things like global configuration files and the
|
||||
like do not affect our test results.
|
||||
@@ -102,7 +131,7 @@ def isolate(pathlib_tmpdir):
|
||||
"""
|
||||
|
||||
# Create a directory to use as our home location.
|
||||
home_dir = os.path.join(str(pathlib_tmpdir), "home")
|
||||
home_dir = os.path.join(str(create_tmpdir()), "home")
|
||||
os.makedirs(home_dir)
|
||||
mkdir_p(os.path.join(home_dir, ".config", "git"))
|
||||
with open(os.path.join(home_dir, ".config", "git", "config"), "wb") as fp:
|
||||
@@ -112,8 +141,10 @@ def isolate(pathlib_tmpdir):
|
||||
os.environ["GIT_CONFIG_NOSYSTEM"] = fs_str("1")
|
||||
os.environ["GIT_AUTHOR_NAME"] = fs_str("pipenv")
|
||||
os.environ["GIT_AUTHOR_EMAIL"] = fs_str("pipenv@pipenv.org")
|
||||
mkdir_p(os.path.join(home_dir, ".virtualenvs"))
|
||||
os.environ["WORKON_HOME"] = fs_str(os.path.join(home_dir, ".virtualenvs"))
|
||||
workon_home = create_tmpdir()
|
||||
os.environ["WORKON_HOME"] = fs_str(str(workon_home))
|
||||
os.environ["HOME"] = home_dir
|
||||
mkdir_p(os.path.join(home_dir, "projects"))
|
||||
# Ignore PIPENV_ACTIVE so that it works as under a bare environment.
|
||||
os.environ.pop("PIPENV_ACTIVE", None)
|
||||
os.environ.pop("VIRTUAL_ENV", None)
|
||||
@@ -189,7 +220,7 @@ class _PipenvInstance(object):
|
||||
"""An instance of a Pipenv Project..."""
|
||||
def __init__(
|
||||
self, pypi=None, pipfile=True, chdir=False, path=None, home_dir=None,
|
||||
venv_root=None, ignore_virtualenvs=True, venv_in_project=True
|
||||
venv_root=None, ignore_virtualenvs=True, venv_in_project=True, name=None
|
||||
):
|
||||
self.pypi = pypi
|
||||
if ignore_virtualenvs:
|
||||
@@ -203,13 +234,24 @@ class _PipenvInstance(object):
|
||||
|
||||
self.original_dir = os.path.abspath(os.curdir)
|
||||
path = path if path else os.environ.get("PIPENV_PROJECT_DIR", None)
|
||||
if name is not None:
|
||||
path = Path(os.environ["HOME"]) / "projects" / name
|
||||
path.mkdir(exist_ok=True)
|
||||
if not path:
|
||||
self._path = TemporaryDirectory(suffix='-project', prefix='pipenv-')
|
||||
path = TemporaryDirectory(suffix='-project', prefix='pipenv-')
|
||||
if isinstance(path, TemporaryDirectory):
|
||||
self._path = path
|
||||
path = Path(self._path.name)
|
||||
try:
|
||||
self.path = str(path.resolve())
|
||||
except OSError:
|
||||
self.path = str(path.absolute())
|
||||
elif isinstance(path, Path):
|
||||
self._path = path
|
||||
try:
|
||||
self.path = str(path.resolve())
|
||||
except OSError:
|
||||
self.path = str(path.absolute())
|
||||
else:
|
||||
self._path = path
|
||||
self.path = path
|
||||
@@ -240,7 +282,7 @@ class _PipenvInstance(object):
|
||||
if self.chdir:
|
||||
os.chdir(self.original_dir)
|
||||
self.path = None
|
||||
if self._path:
|
||||
if self._path and getattr(self._path, "cleanup", None):
|
||||
try:
|
||||
self._path.cleanup()
|
||||
except OSError as e:
|
||||
@@ -322,20 +364,47 @@ def testsroot():
|
||||
return TESTS_ROOT
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def virtualenv(pathlib_tmpdir):
|
||||
virtualenv_path = pathlib_tmpdir / "venv"
|
||||
with temp_environ():
|
||||
c = delegator.run("virtualenv {}".format(virtualenv_path), block=True)
|
||||
class VirtualEnv(object):
|
||||
def __init__(self, name="venv", base_dir=None):
|
||||
if base_dir is None:
|
||||
base_dir = Path(_create_tracked_dir())
|
||||
self.base_dir = base_dir
|
||||
self.name = name
|
||||
self.path = base_dir / name
|
||||
|
||||
def __enter__(self):
|
||||
self._old_environ = os.environ.copy()
|
||||
self.create()
|
||||
return self.activate()
|
||||
|
||||
def __exit__(self, *args, **kwargs):
|
||||
os.environ = self._old_environ
|
||||
|
||||
def create(self):
|
||||
python = Path(sys.executable).as_posix()
|
||||
cmd = "{0} -m virtualenv {1}".format(python, self.path.as_posix())
|
||||
c = delegator.run(cmd, block=True)
|
||||
assert c.return_code == 0
|
||||
for name in ("bin", "Scripts"):
|
||||
activate_this = virtualenv_path / name / "activate_this.py"
|
||||
if activate_this.exists():
|
||||
with open(str(activate_this)) as f:
|
||||
code = compile(f.read(), str(activate_this), "exec")
|
||||
exec(code, dict(__file__=str(activate_this)))
|
||||
break
|
||||
|
||||
def activate(self):
|
||||
script_path = "Scripts" if os.name == "nt" else "bin"
|
||||
activate_this = self.path / script_path / "activate_this.py"
|
||||
if activate_this.exists():
|
||||
with open(str(activate_this)) as f:
|
||||
code = compile(f.read(), str(activate_this), "exec")
|
||||
exec(code, dict(__file__=str(activate_this)))
|
||||
os.environ["VIRTUAL_ENV"] = str(self.path)
|
||||
return self.path
|
||||
else:
|
||||
raise VirtualenvActivationException("Can't find the activate_this.py script.")
|
||||
os.environ["VIRTUAL_ENV"] = str(virtualenv_path)
|
||||
yield virtualenv_path
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def virtualenv(vistir_tmpdir):
|
||||
with temp_environ(), VirtualEnv(base_dir=vistir_tmpdir) as venv:
|
||||
yield venv
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def raw_venv():
|
||||
yield VirtualEnv
|
||||
|
||||
@@ -461,11 +461,11 @@ version = "*"
|
||||
extras = ["socks"]
|
||||
""".strip()
|
||||
f.write(contents)
|
||||
c = p.pipenv("install plette[validation]")
|
||||
c = p.pipenv("install plette")
|
||||
assert c.return_code == 0
|
||||
with open(p.pipfile_path) as f:
|
||||
contents = f.read()
|
||||
assert "[packages.requests]" not in contents
|
||||
assert 'six = {version = "*"}' in contents
|
||||
assert 'requests = {version = "*"' in contents
|
||||
assert 'plette = {' in contents
|
||||
assert 'plette = "*"' in contents
|
||||
|
||||
@@ -57,7 +57,7 @@ testpipenv = {path = ".", editable = true, extras = ["dev"]}
|
||||
project.write_toml({"packages": {}, "dev-packages": {}})
|
||||
c = p.pipenv("install {0}".format(line))
|
||||
assert c.return_code == 0
|
||||
assert "testpipenv" in p.pipfile["packages"], "{0}\n{1}\n\n{2}\n\n{3}".format(p.pipfile, Path(p.pipfile_path).read_text(), Path(os.getcwd()).joinpath("setup.py").read_text(), Path(os.path.join(os.getcwd(), "testpipenv.egg-info/PKG-INFO")).read_text())
|
||||
assert "testpipenv" in p.pipfile["packages"]
|
||||
assert p.pipfile["packages"]["testpipenv"]["path"] == "."
|
||||
assert p.pipfile["packages"]["testpipenv"]["extras"] == ["dev"]
|
||||
assert "six" in p.lockfile["default"]
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import os
|
||||
|
||||
# -*- coding=utf-8 -*-
|
||||
import pytest
|
||||
|
||||
from flaky import flaky
|
||||
@@ -239,13 +238,15 @@ def test_get_vcs_refs(PipenvInstance, pip_src_dir):
|
||||
@pytest.mark.vcs
|
||||
@pytest.mark.install
|
||||
@pytest.mark.needs_internet
|
||||
@pytest.mark.skip_py27_win
|
||||
def test_vcs_entry_supersedes_non_vcs(PipenvInstance, pip_src_dir):
|
||||
"""See issue #2181 -- non-editable VCS dep was specified, but not showing up
|
||||
in the lockfile -- due to not running pip install before locking and not locking
|
||||
the resolution graph of non-editable vcs dependencies.
|
||||
"""
|
||||
with PipenvInstance(chdir=True) as p:
|
||||
pyinstaller_path = p._pipfile.get_fixture_path("git/pyinstaller")
|
||||
# pyinstaller_path = p._pipfile.get_fixture_path("git/pyinstaller")
|
||||
pyinstaller_uri = "https://github.com/pyinstaller/pyinstaller.git"
|
||||
with open(p.pipfile_path, "w") as f:
|
||||
f.write(
|
||||
"""
|
||||
@@ -257,7 +258,7 @@ name = "pypi"
|
||||
[packages]
|
||||
PyUpdater = "*"
|
||||
PyInstaller = {{ref = "develop", git = "{0}"}}
|
||||
""".format(pyinstaller_path.as_uri()).strip()
|
||||
""".format(pyinstaller_uri).strip()
|
||||
)
|
||||
c = p.pipenv("install")
|
||||
assert c.return_code == 0
|
||||
@@ -268,7 +269,7 @@ PyInstaller = {{ref = "develop", git = "{0}"}}
|
||||
assert p.lockfile["default"]["pyinstaller"].get("ref") is not None
|
||||
assert (
|
||||
p.lockfile["default"]["pyinstaller"]["git"]
|
||||
== pyinstaller_path.as_uri()
|
||||
== pyinstaller_uri
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -5,12 +5,8 @@ XXX: Try our best to reduce tests in this file.
|
||||
|
||||
import os
|
||||
|
||||
from tempfile import mkdtemp
|
||||
|
||||
import mock
|
||||
import pytest
|
||||
|
||||
from pipenv._compat import Path
|
||||
from pipenv.project import Project
|
||||
from pipenv.utils import temp_environ
|
||||
from pipenv.vendor import delegator
|
||||
@@ -93,17 +89,12 @@ def test_proper_names_unamanged_virtualenv(PipenvInstance, pypi):
|
||||
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_directory_with_leading_dash(PipenvInstance):
|
||||
def mocked_mkdtemp(suffix, prefix, dir):
|
||||
if suffix == '-project':
|
||||
prefix = '-dir-with-leading-dash'
|
||||
return mkdtemp(suffix, prefix, dir)
|
||||
|
||||
with mock.patch('pipenv.vendor.vistir.compat.mkdtemp', side_effect=mocked_mkdtemp):
|
||||
with temp_environ(), PipenvInstance(chdir=True) as p:
|
||||
def test_directory_with_leading_dash(raw_venv, PipenvInstance):
|
||||
with temp_environ():
|
||||
with PipenvInstance(chdir=True, venv_in_project=False, name="-project-with-dash") as p:
|
||||
if "PIPENV_VENV_IN_PROJECT" in os.environ:
|
||||
del os.environ['PIPENV_VENV_IN_PROJECT']
|
||||
c = p.pipenv('--python python')
|
||||
c = p.pipenv('run pip freeze')
|
||||
assert c.return_code == 0
|
||||
c = p.pipenv('--venv')
|
||||
assert c.return_code == 0
|
||||
|
||||
@@ -171,11 +171,11 @@ def test_include_editable_packages(PipenvInstance, pypi, testsroot, pathlib_tmpd
|
||||
@pytest.mark.virtualenv
|
||||
def test_run_in_virtualenv_with_global_context(PipenvInstance, pypi, virtualenv):
|
||||
with PipenvInstance(chdir=True, pypi=pypi, venv_root=virtualenv.as_posix(), ignore_virtualenvs=False, venv_in_project=False) as p:
|
||||
c = p.pipenv('run which pip')
|
||||
c = p.pipenv('run pip freeze')
|
||||
assert c.return_code == 0
|
||||
assert 'Creating a virtualenv' not in c.err
|
||||
project = Project()
|
||||
assert project.virtualenv_location == str(virtualenv)
|
||||
assert project.virtualenv_location == virtualenv.as_posix()
|
||||
c = p.pipenv("run pip install click")
|
||||
assert c.return_code == 0
|
||||
assert "Courtesy Notice" in c.err
|
||||
@@ -183,7 +183,7 @@ def test_run_in_virtualenv_with_global_context(PipenvInstance, pypi, virtualenv)
|
||||
assert c.return_code == 0
|
||||
c = p.pipenv('run python -c "import click;print(click.__file__)"')
|
||||
assert c.return_code == 0
|
||||
assert c.out.strip().startswith(virtualenv.as_posix())
|
||||
assert c.out.strip().startswith(str(virtualenv))
|
||||
c = p.pipenv("clean --dry-run")
|
||||
assert c.return_code == 0
|
||||
assert "click" in c.out
|
||||
@@ -193,7 +193,7 @@ def test_run_in_virtualenv_with_global_context(PipenvInstance, pypi, virtualenv)
|
||||
@pytest.mark.virtualenv
|
||||
def test_run_in_virtualenv(PipenvInstance, pypi):
|
||||
with PipenvInstance(chdir=True, pypi=pypi) as p:
|
||||
c = p.pipenv('run which pip')
|
||||
c = p.pipenv('run pip freeze')
|
||||
assert c.return_code == 0
|
||||
assert 'Creating a virtualenv' in c.err
|
||||
project = Project()
|
||||
|
||||
Reference in New Issue
Block a user