mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 06:46:15 +00:00
Merge pull request #4304 from pypa/feature/linting-cleanup
This commit is contained in:
@@ -4,13 +4,22 @@ venv_file := $(CURDIR)/.test_venv
|
||||
get_venv_path =$(file < $(venv_file))
|
||||
# This is how we will build tag-specific wheels, e.g. py36 or py37
|
||||
PY_VERSIONS:= 2.7 3.5 3.6 3.7 3.8
|
||||
BACKSLASH = '\\'
|
||||
# This is how we will build generic wheels, e.g. py2 or py3
|
||||
INSTALL_TARGETS := $(addprefix install-py,$(PY_VERSIONS))
|
||||
CLEAN_TARGETS := $(addprefix clean-py,$(PY_VERSIONS))
|
||||
DATE_STRING := $(shell date +%Y.%m.%d)
|
||||
THIS_MONTH_DATE := $(shell date +%Y.%m.01)
|
||||
NEXT_MONTH_DATE := $(shell date -d "+1 month" +%Y.%m.01)
|
||||
|
||||
PATCHED_PIP_VERSION := $(shell awk '/__version__/{gsub(/"/,"",$$3); print $$3}' pipenv/patched/notpip/__init__.py)
|
||||
PATCHED_PIPTOOLS_VERSION := $(shell awk -F "=" '/pip-tools/ {print $$3}' pipenv/patched/patched.txt)
|
||||
GITDIR_STAMPFILE := $(CURDIR)/.git-checkout-dir
|
||||
create_git_tmpdir = $(shell mktemp -dt pipenv-vendor-XXXXXXXX 2>/dev/null || mktemp -d 2>/dev/null)
|
||||
write_git_tmpdir = $(file > $(GITDIR_STAMPFILE),$(create_git_tmpdir))
|
||||
get_checkout_dir = $(file < $(GITDIR_STAMPFILE))
|
||||
get_checkout_subdir = $(addprefix $(get_checkout_dir), $(1))
|
||||
pip-checkout-dir = $(get_checkout_dir)/patch-pip
|
||||
piptools-checkout-dir = $(get_checkout_dir)/patch-piptools
|
||||
|
||||
format:
|
||||
black pipenv/*.py
|
||||
@@ -19,10 +28,9 @@ test:
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
pip install -e . && pipenv install --dev
|
||||
pip install -e .
|
||||
|
||||
install.stamp:
|
||||
[ ! -e install.stamp ] && $(MAKE) install
|
||||
install.stamp: install
|
||||
@touch install.stamp
|
||||
|
||||
.PHONY: install-py%
|
||||
@@ -75,12 +83,8 @@ retest: virtualenv submodules test-install
|
||||
. $(get_venv_path)/bin/activate && pipenv run pytest -ra -k 'test_check_unused or test_install_editable_git_tag or test_get_vcs_refs or test_skip_requirements_when_pipfile or test_editable_vcs_install or test_basic_vcs_install or test_git_vcs_install or test_ssh_vcs_install or test_vcs_can_use_markers' -vvv --full-trace --tb=long
|
||||
|
||||
.PHONY: build
|
||||
build: install.stamp
|
||||
pipenv run python setup.py sdist bdist_wheel
|
||||
|
||||
build.stamp:
|
||||
[ ! -e build.stamp ] && $(MAKE) build
|
||||
@touch build.stamp
|
||||
build: install-virtualenvs.stamp install.stamp
|
||||
PIPENV_PYTHON=3.7 pipenv run python setup.py sdist bdist_wheel
|
||||
|
||||
.PHONY: update-version
|
||||
update-version:
|
||||
@@ -121,5 +125,56 @@ cleanbuild:
|
||||
@rm -rf build.stamp
|
||||
|
||||
.PHONY: clean
|
||||
clean: cleanbuild
|
||||
rm -rf install.stamp build.stamp install-virtualenvs.stamp
|
||||
clean:
|
||||
rm -rf install.stamp build.stamp install-virtualenvs.stamp .git-checkout-dir
|
||||
|
||||
.PHONY: gitclean
|
||||
gitclean:
|
||||
@echo "Cleaning up git trees..."
|
||||
@rm -rf $(file < .git-checkout-dir)
|
||||
@echo "Cleaning up git checkout stamp"
|
||||
@rm -rf .git-checkout-dir
|
||||
|
||||
.git-checkout-dir:
|
||||
@echo "Creating git repo temp file"
|
||||
@echo "Creating git checkout stamp file at .git-checkout-dir"
|
||||
@echo $(file > $(CURDIR)/.git-checkout-dir,$(shell mktemp -dt pipenv-vendor-XXXXXXXX 2>/dev/null || mktemp -d 2>/dev/null))
|
||||
|
||||
.PHONY: clone-pip
|
||||
clone-pip: .git-checkout-dir
|
||||
[ -e $(pip-checkout-dir) ] && echo "Pip already exists, moving on!" || git clone https://github.com/pypa/pip.git $(pip-checkout-dir) -b $(PATCHED_PIP_VERSION)
|
||||
|
||||
.PHONY: clone-piptools
|
||||
clone-piptools: .git-checkout-dir
|
||||
[ -e $(piptools-checkout-dir) ] && echo "Piptools already exists, moving on!" || git clone https://github.com/jazzband/pip-tools.git $(piptools-checkout-dir) -b $(PATCHED_PIPTOOLS_VERSION)
|
||||
|
||||
.PHONY: patch-pip
|
||||
patch-pip: clone-pip
|
||||
@find $(CURDIR)/tasks/vendoring/patches/patched/ -regex ".*/pip[0-9]+.patch" -exec cp {} $(pip-checkout-dir) \;
|
||||
@sed -i -r 's:([a-b]\/)pipenv/patched/:\1src/:g' $(pip-checkout-dir)/*.patch
|
||||
@find $(CURDIR)/tasks/vendoring/patches/patched/ -regex ".*/_post-pip-[^/\.]*.patch" -exec cp {} $(pip-checkout-dir)/ \;
|
||||
@sed -i -r 's:([a-b]\/)pipenv/patched/not:\1src/:g' $(pip-checkout-dir)/_post-*.patch
|
||||
@cd $(pip-checkout-dir)/ && git apply --ignore-whitespace --verbose pip*.patch
|
||||
@echo "Head to $(pip-checkout-dir) to update the pip patches to the latest version"
|
||||
|
||||
.PHONY: patch-piptools
|
||||
patch-piptools: clone-piptools
|
||||
@find $(CURDIR)/tasks/vendoring/patches/patched/ -regex ".*/piptools[^/\.]*.patch" -exec cp {} $(piptools-checkout-dir)/ \;
|
||||
@sed -i -r 's:([a-b]\/)pipenv/patched/:\1/:g' $(piptools-checkout-dir)/*.patch
|
||||
@cd $(piptools-checkout-dir)/ && git apply --ignore-whitespace --verbose piptools*.patch
|
||||
@echo "Head to $(piptools-checkout-dir) to update the piptools patches to the latest version"
|
||||
|
||||
.PHONY: patches
|
||||
patches: patch-pip patch-piptools
|
||||
|
||||
.PHONY: reimport-pip-patch
|
||||
reimport-pip-patch:
|
||||
@sed -i -r 's:([a-b]\/)src/:\1pipenv/patched/not:g' $(pip-checkout-dir)/_post-*.patch
|
||||
@sed -i -r 's:([a-b]\/)src/:\1pipenv/patched/:g' $(pip-checkout-dir)/pip*.patch
|
||||
@find $(pip-checkout-dir) -maxdepth 1 -regex ".*/pip[0-9]+.patch" -exec cp {} $(CURDIR)/tasks/vendoring/patches/patched/ \;
|
||||
@find $(pip-checkout-dir) -maxdepth 1 -regex ".*/_post-pip-[^/\.]*.patch" -exec cp {} $(CURDIR)/tasks/vendoring/patches/patched/ \;
|
||||
|
||||
.PHONY: reimport-piptools-patch
|
||||
reimport-piptools-patch:
|
||||
@sed -i -r 's:([a-b]\/):\1pipenv/patched/:g' $(piptools-checkout-dir)/*.patch
|
||||
@find $(piptools-checkout-dir)/ -maxdepth 1 -regex ".*/piptools[^/\.]*.patch" -exec cp {} $(CURDIR)/tasks/vendoring/patches/patched/ \;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
``+`` signs in URL authentication fragments will no longer be incorrectly replaced with space ( `` `` ) characters.
|
||||
@@ -1 +1 @@
|
||||
Fix a bug that Pipenv rejects to work under the root directory.
|
||||
Fixed a regression which caused Pipenv to fail when running under ``/``.
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
``setup.py`` files with ``version`` variables read from ``os.environ`` are now able to be parsed successfully.
|
||||
@@ -1 +1 @@
|
||||
Fix a bug that system-wide packages will be considered when inside a venv.
|
||||
Fixed a bug which caused Pipenv to fail to install packages in a virtual environment if those packages were already present in the system global environment.
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
Remove expection of ``version`` key in ``test_ssh_vcs_install`` to prevent it
|
||||
from failing.
|
||||
Remove expection of ``version`` key in ``test_ssh_vcs_install`` to prevent it from failing.
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Fixed a regression with installing the current directory, or ``.``, inside a ``venv`` based virtual environment.
|
||||
@@ -0,0 +1 @@
|
||||
Fixed a bug with the discovery of python paths on Windows which could prevent installation of environments during ``pipenv install``.
|
||||
@@ -0,0 +1 @@
|
||||
Fixed an issue in the ``requirementslib`` AST parser which prevented parsing of ``setup.py`` files for dependency metadata.
|
||||
@@ -1,4 +1,3 @@
|
||||
- Updated vendored dependencies:
|
||||
|
||||
- **pythonfinder**: ``1.2.2`` => ``1.2.4``
|
||||
- **requirementslib**: ``1.5.9`` => ``1.5.10``
|
||||
Updated vendored dependencies:
|
||||
- **pythonfinder**: ``1.2.2`` => ``1.2.4``
|
||||
- **requirementslib**: ``1.5.9`` => ``1.5.10``
|
||||
|
||||
@@ -357,7 +357,7 @@ def lock(
|
||||
dev_only=dev_only,
|
||||
emit_requirements=emit_requirements,
|
||||
pypi_mirror=state.pypi_mirror,
|
||||
pre=state.installstate.pre,
|
||||
pre=pre,
|
||||
)
|
||||
elif state.lockoptions.dev_only:
|
||||
raise PipenvOptionsError(
|
||||
@@ -368,7 +368,7 @@ def lock(
|
||||
do_lock(
|
||||
ctx=ctx,
|
||||
clear=state.clear,
|
||||
pre=state.installstate.pre,
|
||||
pre=pre,
|
||||
keep_outdated=state.installstate.keep_outdated,
|
||||
pypi_mirror=state.pypi_mirror,
|
||||
write=not state.quiet,
|
||||
|
||||
@@ -83,12 +83,14 @@ class InstallState(object):
|
||||
self.packages = []
|
||||
self.editables = []
|
||||
|
||||
|
||||
class LockOptions(object):
|
||||
def __init__(self):
|
||||
self.dev_only = False
|
||||
self.emit_requirements = False
|
||||
self.emit_requirements_header = False
|
||||
|
||||
|
||||
pass_state = make_pass_decorator(State, ensure=True)
|
||||
|
||||
|
||||
@@ -329,6 +331,7 @@ def emit_requirements_flag(f):
|
||||
return option("--requirements", "-r", default=False, is_flag=True, expose_value=False,
|
||||
help="Generate output in requirements.txt format.", callback=callback)(f)
|
||||
|
||||
|
||||
def emit_requirements_header_flag(f):
|
||||
def callback(ctx, param, value):
|
||||
state = ctx.ensure_object(State)
|
||||
@@ -338,6 +341,7 @@ def emit_requirements_header_flag(f):
|
||||
return option("--header/--no-header", default=True, is_flag=True, expose_value=False,
|
||||
help="Add header to generated requirements", callback=callback)(f)
|
||||
|
||||
|
||||
def dev_only_flag(f):
|
||||
def callback(ctx, param, value):
|
||||
state = ctx.ensure_object(State)
|
||||
@@ -347,6 +351,7 @@ def dev_only_flag(f):
|
||||
return option("--dev-only", default=False, is_flag=True, expose_value=False,
|
||||
help="Emit development dependencies *only* (overrides --dev)", callback=callback)(f)
|
||||
|
||||
|
||||
def code_option(f):
|
||||
def callback(ctx, param, value):
|
||||
state = ctx.ensure_object(State)
|
||||
|
||||
+2
-2
@@ -1616,10 +1616,10 @@ def which_pip(allow_global=False):
|
||||
def system_which(command, mult=False):
|
||||
"""Emulates the system's which. Returns None if not found."""
|
||||
_which = "which -a" if not os.name == "nt" else "where"
|
||||
os.environ = {
|
||||
os.environ.update({
|
||||
vistir.compat.fs_str(k): vistir.compat.fs_str(val)
|
||||
for k, val in os.environ.items()
|
||||
}
|
||||
})
|
||||
result = None
|
||||
try:
|
||||
c = delegator.run("{0} {1}".format(_which, command))
|
||||
|
||||
+47
-4
@@ -26,15 +26,27 @@ from .utils import normalize_path, make_posix
|
||||
|
||||
|
||||
if False:
|
||||
from typing import Optional
|
||||
import pip_shims.shims
|
||||
import tomlkit
|
||||
from typing import ContextManager, Dict, Generator, List, Optional, Set, Union
|
||||
from types import ModuleType
|
||||
from .project import TSource, TPipfile, Project
|
||||
from .vendor.packaging.version import Version
|
||||
|
||||
BASE_WORKING_SET = pkg_resources.WorkingSet(sys.path)
|
||||
# TODO: Unittests for this class
|
||||
|
||||
|
||||
class Environment(object):
|
||||
def __init__(self, prefix=None, is_venv=False, base_working_set=None, pipfile=None,
|
||||
sources=None, project=None):
|
||||
def __init__(
|
||||
self,
|
||||
prefix=None, # type: Optional[str]
|
||||
is_venv=False, # type: bool
|
||||
base_working_set=None, # type: pkg_resources.WorkingSet
|
||||
pipfile=None, # type: Optional[Union[tomlkit.toml_document.TOMLDocument, TPipfile]]
|
||||
sources=None, # type: Optional[List[TSource]]
|
||||
project=None # type: Optional[Project]
|
||||
):
|
||||
super(Environment, self).__init__()
|
||||
self._modules = {'pkg_resources': pkg_resources, 'pipenv': pipenv}
|
||||
self.base_working_set = base_working_set if base_working_set else BASE_WORKING_SET
|
||||
@@ -58,6 +70,7 @@ class Environment(object):
|
||||
self.sys_paths = get_paths()
|
||||
|
||||
def safe_import(self, name):
|
||||
# type: (str) -> ModuleType
|
||||
"""Helper utility for reimporting previously imported modules while inside the env"""
|
||||
module = None
|
||||
if name not in self._modules:
|
||||
@@ -77,10 +90,12 @@ class Environment(object):
|
||||
except TypeError:
|
||||
del sys.modules[name]
|
||||
sys.modules[name] = self._modules[name]
|
||||
return self._modules[name]
|
||||
return module
|
||||
|
||||
@classmethod
|
||||
def resolve_dist(cls, dist, working_set):
|
||||
# type: (pkg_resources.Distribution, pkg_resources.WorkingSet) -> Set[pkg_resources.Distribution]
|
||||
"""Given a local distribution and a working set, returns all dependencies from the set.
|
||||
|
||||
:param dist: A single distribution to find the dependencies of
|
||||
@@ -104,28 +119,33 @@ class Environment(object):
|
||||
return deps
|
||||
|
||||
def extend_dists(self, dist):
|
||||
# type: (pkg_resources.Distribution) -> None
|
||||
extras = self.resolve_dist(dist, self.base_working_set)
|
||||
self.extra_dists.append(dist)
|
||||
if extras:
|
||||
self.extra_dists.extend(extras)
|
||||
|
||||
def add_dist(self, dist_name):
|
||||
# type: (str) -> None
|
||||
dist = pkg_resources.get_distribution(pkg_resources.Requirement(dist_name))
|
||||
self.extend_dists(dist)
|
||||
|
||||
@cached_property
|
||||
def python_version(self):
|
||||
# type: () -> str
|
||||
with self.activated():
|
||||
sysconfig = self.safe_import("sysconfig")
|
||||
py_version = sysconfig.get_python_version()
|
||||
return py_version
|
||||
|
||||
def find_libdir(self):
|
||||
# type: () -> Optional[vistir.compat.Path]
|
||||
libdir = self.prefix / "lib"
|
||||
return next(iter(list(libdir.iterdir())), None)
|
||||
|
||||
@property
|
||||
def python_info(self):
|
||||
# type: () -> Dict[str, str]
|
||||
include_dir = self.prefix / "include"
|
||||
if not os.path.exists(include_dir):
|
||||
include_dirs = self.get_include_path()
|
||||
@@ -142,6 +162,7 @@ class Environment(object):
|
||||
return {}
|
||||
|
||||
def _replace_parent_version(self, path, replace_version):
|
||||
# type: (str, str) -> str
|
||||
if not os.path.exists(path):
|
||||
base, leaf = os.path.split(path)
|
||||
base, parent = os.path.split(base)
|
||||
@@ -153,6 +174,7 @@ class Environment(object):
|
||||
|
||||
@cached_property
|
||||
def base_paths(self):
|
||||
# type: () -> Dict[str, str]
|
||||
"""
|
||||
Returns the context appropriate paths for the environment.
|
||||
|
||||
@@ -231,6 +253,7 @@ class Environment(object):
|
||||
|
||||
@cached_property
|
||||
def script_basedir(self):
|
||||
# type: () -> str
|
||||
"""Path to the environment scripts dir"""
|
||||
prefix = make_posix(self.prefix.as_posix())
|
||||
install_scheme = 'nt' if (os.name == 'nt') else 'posix_prefix'
|
||||
@@ -242,6 +265,7 @@ class Environment(object):
|
||||
|
||||
@property
|
||||
def python(self):
|
||||
# type: () -> str
|
||||
"""Path to the environment python"""
|
||||
py = vistir.compat.Path(self.script_basedir).joinpath("python").absolute().as_posix()
|
||||
if not py:
|
||||
@@ -250,6 +274,7 @@ class Environment(object):
|
||||
|
||||
@cached_property
|
||||
def sys_path(self):
|
||||
# type: () -> List[str]
|
||||
"""
|
||||
The system path inside the environment
|
||||
|
||||
@@ -272,6 +297,7 @@ class Environment(object):
|
||||
return path
|
||||
|
||||
def build_command(self, python_lib=False, python_inc=False, scripts=False, py_version=False):
|
||||
# type: (bool, bool, bool, bool) -> str
|
||||
"""Build the text for running a command in the given environment
|
||||
|
||||
:param python_lib: Whether to include the python lib dir commands, defaults to False
|
||||
@@ -313,6 +339,7 @@ class Environment(object):
|
||||
return py_command
|
||||
|
||||
def get_paths(self):
|
||||
# type: () -> Optional[Dict[str, str]]
|
||||
"""
|
||||
Get the paths for the environment by running a subcommand
|
||||
|
||||
@@ -343,6 +370,7 @@ class Environment(object):
|
||||
return None
|
||||
|
||||
def get_lib_paths(self):
|
||||
# type: () -> Dict[str, str]
|
||||
"""Get the include path for the environment
|
||||
|
||||
:return: The python include path for the environment
|
||||
@@ -390,6 +418,7 @@ class Environment(object):
|
||||
return {}
|
||||
|
||||
def get_include_path(self):
|
||||
# type: () -> Optional[Dict[str, str]]
|
||||
"""Get the include path for the environment
|
||||
|
||||
:return: The python include path for the environment
|
||||
@@ -424,6 +453,7 @@ class Environment(object):
|
||||
|
||||
@cached_property
|
||||
def sys_prefix(self):
|
||||
# type: () -> str
|
||||
"""
|
||||
The prefix run inside the context of the environment
|
||||
|
||||
@@ -438,6 +468,7 @@ class Environment(object):
|
||||
|
||||
@cached_property
|
||||
def paths(self):
|
||||
# type: () -> Dict[str, str]
|
||||
paths = {}
|
||||
with vistir.contextmanagers.temp_environ(), vistir.contextmanagers.temp_path():
|
||||
os.environ["PYTHONIOENCODING"] = vistir.compat.fs_str("utf-8")
|
||||
@@ -451,10 +482,12 @@ class Environment(object):
|
||||
|
||||
@property
|
||||
def scripts_dir(self):
|
||||
# type: () -> str
|
||||
return self.paths["scripts"]
|
||||
|
||||
@property
|
||||
def libdir(self):
|
||||
# type: () -> str
|
||||
purelib = self.paths.get("purelib", None)
|
||||
if purelib and os.path.exists(purelib):
|
||||
return "purelib", purelib
|
||||
@@ -462,6 +495,7 @@ class Environment(object):
|
||||
|
||||
@property
|
||||
def pip_version(self):
|
||||
# type: () -> Version
|
||||
"""
|
||||
Get the pip version in the environment. Useful for knowing which args we can use
|
||||
when installing.
|
||||
@@ -475,6 +509,7 @@ class Environment(object):
|
||||
return parse_version("20.2")
|
||||
|
||||
def expand_egg_links(self):
|
||||
# type: () -> None
|
||||
"""
|
||||
Expand paths specified in egg-link files to prevent pip errors during
|
||||
reinstall
|
||||
@@ -497,6 +532,7 @@ class Environment(object):
|
||||
pth.write_text("\n".join(contents))
|
||||
|
||||
def get_distributions(self):
|
||||
# type: () -> Generator[pkg_resources.Distribution, None, None]
|
||||
"""
|
||||
Retrives the distributions installed on the library path of the environment
|
||||
|
||||
@@ -511,6 +547,7 @@ class Environment(object):
|
||||
yield dist
|
||||
|
||||
def find_egg(self, egg_dist):
|
||||
# type: (pkg_resources.Distribution) -> str
|
||||
"""Find an egg by name in the given environment"""
|
||||
site_packages = self.libdir[1]
|
||||
search_filename = "{0}.egg-link".format(egg_dist.project_name)
|
||||
@@ -525,6 +562,7 @@ class Environment(object):
|
||||
return egg
|
||||
|
||||
def locate_dist(self, dist):
|
||||
# type: (pkg_resources.Distribution) -> str
|
||||
"""Given a distribution, try to find a corresponding egg link first.
|
||||
|
||||
If the egg - link doesn 't exist, return the supplied distribution."""
|
||||
@@ -533,6 +571,7 @@ class Environment(object):
|
||||
return location or dist.location
|
||||
|
||||
def dist_is_in_project(self, dist):
|
||||
# type: (pkg_resources.Distribution) -> bool
|
||||
"""Determine whether the supplied distribution is in the environment."""
|
||||
from .project import _normalized
|
||||
prefixes = [
|
||||
@@ -546,6 +585,7 @@ class Environment(object):
|
||||
return any(location.startswith(prefix) for prefix in prefixes)
|
||||
|
||||
def get_installed_packages(self):
|
||||
# type: () -> List[pkg_resources.Distribution]
|
||||
"""Returns all of the installed packages in a given environment"""
|
||||
workingset = self.get_working_set()
|
||||
packages = [
|
||||
@@ -556,6 +596,7 @@ class Environment(object):
|
||||
|
||||
@contextlib.contextmanager
|
||||
def get_finder(self, pre=False):
|
||||
# type: (bool) -> ContextManager[pip_shims.shims.PackageFinder]
|
||||
from .vendor.pip_shims.shims import (
|
||||
InstallCommand, get_package_finder
|
||||
)
|
||||
@@ -571,7 +612,8 @@ class Environment(object):
|
||||
yield finder
|
||||
|
||||
def get_package_info(self, pre=False):
|
||||
from .vendor.pip_shims.shims import pip_version, parse_version, CandidateEvaluator
|
||||
# type: (bool) -> Generator[pkg_resources.Distribution, None, None]
|
||||
from .vendor.pip_shims.shims import pip_version, parse_version
|
||||
dependency_links = []
|
||||
packages = self.get_installed_packages()
|
||||
# This code is borrowed from pip's current implementation
|
||||
@@ -611,6 +653,7 @@ class Environment(object):
|
||||
yield dist
|
||||
|
||||
def get_outdated_packages(self, pre=False):
|
||||
# type: (bool) -> List[pkg_resources.Distribution]
|
||||
return [
|
||||
pkg for pkg in self.get_package_info(pre=pre)
|
||||
if pkg.latest_version._key > pkg.parsed_version._key
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import operator
|
||||
import re
|
||||
import six
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
@@ -63,8 +64,8 @@ class InstallerError(RuntimeError):
|
||||
self.err = c.err
|
||||
|
||||
|
||||
@six.add_metaclass(ABCMeta)
|
||||
class Installer(object):
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
def __init__(self):
|
||||
self.cmd = self._find_installer()
|
||||
|
||||
+45
-2
@@ -37,8 +37,14 @@ from .utils import (
|
||||
)
|
||||
|
||||
if is_type_checking():
|
||||
from typing import Dict, Text, Union
|
||||
import pkg_resources
|
||||
from typing import Dict, List, Optional, Set, Text, Tuple, Union
|
||||
TSource = Dict[Text, Union[Text, bool]]
|
||||
TPackageEntry = Dict[str, Union[bool, str, List[str]]]
|
||||
TPackage = Dict[str, TPackageEntry]
|
||||
TScripts = Dict[str, str]
|
||||
TPipenv = Dict[str, bool]
|
||||
TPipfile = Dict[str, Union[TPackage, TScripts, TPipenv, List[TSource]]]
|
||||
|
||||
|
||||
def _normalized(p):
|
||||
@@ -158,6 +164,7 @@ class Project(object):
|
||||
pass
|
||||
|
||||
def path_to(self, p):
|
||||
# type: (str) -> str
|
||||
"""Returns the absolute path to a given relative path."""
|
||||
if os.path.isabs(p):
|
||||
return p
|
||||
@@ -219,16 +226,19 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
# type: () -> str
|
||||
if self._name is None:
|
||||
self._name = self.pipfile_location.split(os.sep)[-2]
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def pipfile_exists(self):
|
||||
# type: () -> bool
|
||||
return os.path.isfile(self.pipfile_location)
|
||||
|
||||
@property
|
||||
def required_python_version(self):
|
||||
# type: () -> str
|
||||
if self.pipfile_exists:
|
||||
required = self.parsed_pipfile.get("requires", {}).get(
|
||||
"python_full_version"
|
||||
@@ -240,13 +250,16 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def project_directory(self):
|
||||
# type: () -> str
|
||||
return os.path.abspath(os.path.join(self.pipfile_location, os.pardir))
|
||||
|
||||
@property
|
||||
def requirements_exists(self):
|
||||
# type: () -> bool
|
||||
return bool(self.requirements_location)
|
||||
|
||||
def is_venv_in_project(self):
|
||||
# type: () -> bool
|
||||
return PIPENV_VENV_IN_PROJECT or (
|
||||
self.project_directory
|
||||
and os.path.isdir(os.path.join(self.project_directory, ".venv"))
|
||||
@@ -254,6 +267,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def virtualenv_exists(self):
|
||||
# type: () -> bool
|
||||
if os.path.exists(self.virtualenv_location):
|
||||
if os.name == "nt":
|
||||
extra = ["Scripts", "activate.bat"]
|
||||
@@ -264,6 +278,7 @@ class Project(object):
|
||||
return False
|
||||
|
||||
def get_location_for_virtualenv(self):
|
||||
# type: () -> str
|
||||
# If there's no project yet, set location based on config.
|
||||
if not self.project_directory:
|
||||
if self.is_venv_in_project():
|
||||
@@ -295,6 +310,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def working_set(self):
|
||||
# type: () -> pkg_resources.WorkingSet
|
||||
from .utils import load_path
|
||||
sys_path = load_path(self.which("python"))
|
||||
import pkg_resources
|
||||
@@ -306,10 +322,12 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def installed_package_names(self):
|
||||
# type: () -> List[str]
|
||||
return get_canonical_names([pkg.key for pkg in self.installed_packages])
|
||||
|
||||
@property
|
||||
def lockfile_package_names(self):
|
||||
# type: () -> Dict[str, Set[str]]
|
||||
dev_keys = get_canonical_names(self.lockfile_content["develop"].keys())
|
||||
default_keys = get_canonical_names(self.lockfile_content["default"].keys())
|
||||
return {
|
||||
@@ -320,6 +338,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def pipfile_package_names(self):
|
||||
# type: () -> Dict[str, Set[str]]
|
||||
dev_keys = get_canonical_names(self.dev_packages.keys())
|
||||
default_keys = get_canonical_names(self.packages.keys())
|
||||
return {
|
||||
@@ -349,16 +368,19 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def environment(self):
|
||||
# type: () -> Environment
|
||||
if not self._environment:
|
||||
allow_global = os.environ.get("PIPENV_USE_SYSTEM", PIPENV_USE_SYSTEM)
|
||||
self._environment = self.get_environment(allow_global=allow_global)
|
||||
return self._environment
|
||||
|
||||
def get_outdated_packages(self):
|
||||
# type: () -> List[pkg_resources.Distribution]
|
||||
return self.environment.get_outdated_packages(pre=self.pipfile.get("pre", False))
|
||||
|
||||
@classmethod
|
||||
def _sanitize(cls, name):
|
||||
# type: (str) -> Tuple[str, str]
|
||||
# Replace dangerous characters into '_'. The length of the sanitized
|
||||
# project name is limited as 42 because of the limit of linux kernel
|
||||
#
|
||||
@@ -374,6 +396,7 @@ class Project(object):
|
||||
return re.sub(r'[ $`!*@"\\\r\n\t]', "_", name)[0:42]
|
||||
|
||||
def _get_virtualenv_hash(self, name):
|
||||
# type: (str) -> str
|
||||
"""Get the name of the virtualenv adjusted for windows if needed
|
||||
|
||||
Returns (name, encoded_hash)
|
||||
@@ -416,6 +439,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def virtualenv_name(self):
|
||||
# type: () -> str
|
||||
sanitized, encoded_hash = self._get_virtualenv_hash(self.name)
|
||||
suffix = "-{0}".format(PIPENV_PYTHON) if PIPENV_PYTHON else ""
|
||||
# If the pipfile was located at '/home/user/MY_PROJECT/Pipfile',
|
||||
@@ -424,6 +448,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def virtualenv_location(self):
|
||||
# type: () -> str
|
||||
# if VIRTUAL_ENV is set, use that.
|
||||
virtualenv_env = os.getenv("VIRTUAL_ENV")
|
||||
if (
|
||||
@@ -439,6 +464,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def virtualenv_src_location(self):
|
||||
# type: () -> str
|
||||
if self.virtualenv_location:
|
||||
loc = os.sep.join([self.virtualenv_location, "src"])
|
||||
else:
|
||||
@@ -448,6 +474,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def download_location(self):
|
||||
# type: () -> str
|
||||
if self._download_location is None:
|
||||
loc = os.sep.join([self.virtualenv_location, "downloads"])
|
||||
self._download_location = loc
|
||||
@@ -457,6 +484,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def proper_names_db_path(self):
|
||||
# type: () -> str
|
||||
if self._proper_names_db_path is None:
|
||||
self._proper_names_db_path = vistir.compat.Path(
|
||||
self.virtualenv_location, "pipenv-proper-names.txt"
|
||||
@@ -466,16 +494,19 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def proper_names(self):
|
||||
# type: () -> str
|
||||
with self.proper_names_db_path.open() as f:
|
||||
return f.read().splitlines()
|
||||
|
||||
def register_proper_name(self, name):
|
||||
# type: (str) -> None
|
||||
"""Registers a proper name to the database."""
|
||||
with self.proper_names_db_path.open("a") as f:
|
||||
f.write(u"{0}\n".format(name))
|
||||
|
||||
@property
|
||||
def pipfile_location(self):
|
||||
# type: () -> str
|
||||
if PIPENV_PIPFILE:
|
||||
return PIPENV_PIPFILE
|
||||
|
||||
@@ -489,6 +520,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def requirements_location(self):
|
||||
# type: () -> Optional[str]
|
||||
if self._requirements_location is None:
|
||||
try:
|
||||
loc = find_requirements(max_depth=PIPENV_MAX_DEPTH)
|
||||
@@ -499,6 +531,7 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def parsed_pipfile(self):
|
||||
# type: () -> Union[tomlkit.toml_document.TOMLDocument, TPipfile]
|
||||
"""Parse Pipfile into a TOMLFile and cache it
|
||||
|
||||
(call clear_pipfile_cache() afterwards if mutating)"""
|
||||
@@ -511,6 +544,7 @@ class Project(object):
|
||||
return _pipfile_cache[cache_key]
|
||||
|
||||
def read_pipfile(self):
|
||||
# type: () -> str
|
||||
# Open the pipfile, read it into memory.
|
||||
if not self.pipfile_exists:
|
||||
return ""
|
||||
@@ -521,10 +555,12 @@ class Project(object):
|
||||
return contents
|
||||
|
||||
def clear_pipfile_cache(self):
|
||||
# type: () -> None
|
||||
"""Clear pipfile cache (e.g., so we can mutate parsed pipfile)"""
|
||||
_pipfile_cache.clear()
|
||||
|
||||
def _parse_pipfile(self, contents):
|
||||
# type: () -> Union[tomlkit.toml_document.TOMLDocument, TPipfile]
|
||||
try:
|
||||
return tomlkit.parse(contents)
|
||||
except Exception:
|
||||
@@ -533,6 +569,7 @@ class Project(object):
|
||||
return toml.loads(contents)
|
||||
|
||||
def _read_pyproject(self):
|
||||
# type: () -> None
|
||||
pyproject = self.path_to("pyproject.toml")
|
||||
if os.path.exists(pyproject):
|
||||
self._pyproject = toml.load(pyproject)
|
||||
@@ -547,24 +584,29 @@ class Project(object):
|
||||
|
||||
@property
|
||||
def build_requires(self):
|
||||
# type: () -> List[str]
|
||||
return self._build_system.get("requires", ["setuptools>=40.8.0", "wheel"])
|
||||
|
||||
@property
|
||||
def build_backend(self):
|
||||
# type: () -> str
|
||||
return self._build_system.get("build-backend", get_default_pyproject_backend())
|
||||
|
||||
@property
|
||||
def settings(self):
|
||||
# type: () -> Union[tomlkit.items.Table, Dict[str, Union[str, bool]]]
|
||||
"""A dictionary of the settings added to the Pipfile."""
|
||||
return self.parsed_pipfile.get("pipenv", {})
|
||||
|
||||
def has_script(self, name):
|
||||
# type: (str) -> bool
|
||||
try:
|
||||
return name in self.parsed_pipfile["scripts"]
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
def build_script(self, name, extra_args=None):
|
||||
# type: (str, Optional[List[str]])
|
||||
try:
|
||||
script = Script.parse(self.parsed_pipfile["scripts"][name])
|
||||
except KeyError:
|
||||
@@ -574,6 +616,7 @@ class Project(object):
|
||||
return script
|
||||
|
||||
def update_settings(self, d):
|
||||
# type: (Dict[str, Union[str, bool]]) -> None
|
||||
settings = self.settings
|
||||
changed = False
|
||||
for new in d:
|
||||
@@ -1004,7 +1047,7 @@ class Project(object):
|
||||
|
||||
if expand_env_vars:
|
||||
# Expand environment variables in Pipfile.lock at runtime.
|
||||
for i, source in enumerate(j["_meta"]["sources"][:]):
|
||||
for i, _ in enumerate(j["_meta"]["sources"][:]):
|
||||
j["_meta"]["sources"][i]["url"] = os.path.expandvars(
|
||||
j["_meta"]["sources"][i]["url"]
|
||||
)
|
||||
|
||||
@@ -1877,7 +1877,6 @@ def get_vcs_deps(
|
||||
# sys.path = [repo.checkout_directory, "", ".", get_python_lib(plat_specific=0)]
|
||||
commit_hash = repo.get_commit_hash()
|
||||
name = requirement.normalized_name
|
||||
version = requirement._specifiers = "=={0}".format(requirement.req.setup_info.version)
|
||||
lockfile[name] = requirement.pipfile_entry[1]
|
||||
lockfile[name]['ref'] = commit_hash
|
||||
result.append(requirement)
|
||||
|
||||
Reference in New Issue
Block a user