Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge #3191, #3196 and #3209 #3217

Merged
merged 89 commits into from
Nov 14, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
80a6dcb
add PIPENV_SKIP_LOCK envvar, and suitable doc
devxpy Oct 27, 2018
023e786
fix PIPENV_SKIP_LOCK for `pipenv unisntall` command.
devxpy Oct 27, 2018
09ba364
Merge branch 'master' into master
devxpy Oct 30, 2018
e2769fe
Merge branch 'master' into master
devxpy Oct 30, 2018
9ed610f
Merge branch 'master' into master
devxpy Nov 3, 2018
18be92b
Merge branch 'master' into master
devxpy Nov 7, 2018
2b195dd
fix errors from merge
devxpy Nov 8, 2018
3eba19d
Improve toml parsing
frostming Nov 8, 2018
e147dc3
Drops prettytoml/contoml form vendors
frostming Nov 8, 2018
b27d6a7
clear references in patched.txt
frostming Nov 8, 2018
1555200
Add back some tests
frostming Nov 8, 2018
53b073c
python 2.7 unicode
frostming Nov 8, 2018
b3aa66b
make tomlkit dump toml's inline table
frostming Nov 8, 2018
9743d98
Merge branch 'master' into improve-toml-parse
techalchemy Nov 8, 2018
36f054d
Grab updates from latest vendored changes
techalchemy Nov 8, 2018
65d7090
Force inline table
frostming Nov 8, 2018
5b49670
Fix broken requirementslib updates
techalchemy Nov 8, 2018
f3003b6
Merge branch 'master' into update-vendor
techalchemy Nov 8, 2018
0762528
Final fix
frostming Nov 9, 2018
3490fc8
fix patch
frostming Nov 9, 2018
de78c1e
Only convert outline tables when write toml
frostming Nov 9, 2018
accd0ea
Move to utils function
frostming Nov 9, 2018
6df7d88
update tomlkit
frostming Nov 10, 2018
1f7c9ef
update patch
frostming Nov 10, 2018
de98b87
backports import
frostming Nov 10, 2018
f5c7c58
Change fallback style
frostming Nov 10, 2018
2b90c89
Revendor requirementslib
techalchemy Nov 11, 2018
dec7be5
Introduce `pipenv.environments.Environment`
techalchemy Nov 11, 2018
642b6f9
Update vistir and requirementslib
techalchemy Nov 11, 2018
aedb41c
Fix stdout and stderr wrappers
techalchemy Nov 11, 2018
45100b8
Fix stdout and stderr wrappers
techalchemy Nov 11, 2018
118c9d3
Add dramatically improved queued installation
techalchemy Nov 11, 2018
5602952
Merge branch 'update-vendor' of github.com:pypa/pipenv into update-ve…
techalchemy Nov 11, 2018
690d1e8
Merge branch 'update-vendor' into feature/improved-async-installer
techalchemy Nov 11, 2018
8644611
Merge branch 'master' into update-vendor
techalchemy Nov 11, 2018
ac96370
Merge branch 'update-vendor' into feature/improved-async-installer
techalchemy Nov 11, 2018
8643a73
Fix configparser import
techalchemy Nov 11, 2018
0caf7a0
Fix configparser import
techalchemy Nov 11, 2018
650cc32
Fix resource errors
techalchemy Nov 11, 2018
fe9d996
Fix resource errors
techalchemy Nov 11, 2018
e5be2ac
Fix python 2.7 installations
techalchemy Nov 12, 2018
382be38
Fix python 2.7 installations
techalchemy Nov 12, 2018
489e534
Fix various bugs with python 2.7 and vendored deps
techalchemy Nov 12, 2018
3984632
Fix various bugs with python 2.7 and vendored deps
techalchemy Nov 12, 2018
32a6dd3
Support python 2 parsing
techalchemy Nov 12, 2018
4009198
Fix environment site import
techalchemy Nov 12, 2018
32b1113
Support python 2 parsing
techalchemy Nov 12, 2018
1216ae0
Fix environment site import
techalchemy Nov 12, 2018
70fc92b
Fix import errors on setup parsing
techalchemy Nov 12, 2018
7e139ad
Fix import errors on setup parsing
techalchemy Nov 12, 2018
8502ac9
Revendor
techalchemy Nov 12, 2018
013e3d0
Revendor
techalchemy Nov 12, 2018
96cbd58
Fix prefix comparison for py2
techalchemy Nov 12, 2018
8fa4057
Merge branch 'master' into update-vendor
techalchemy Nov 12, 2018
0c7f287
Fix prefix comparison for py2
techalchemy Nov 12, 2018
eed0f0f
Merge branch 'master' into feature/improved-async-installer
techalchemy Nov 12, 2018
d7d50ef
no samefile for windows python2.7
techalchemy Nov 12, 2018
9eabde0
no samefile for windows python2.7
techalchemy Nov 12, 2018
ef59d15
Fix bugs in environment implementation
techalchemy Nov 13, 2018
9296f56
Fix bugs in environment implementation
techalchemy Nov 13, 2018
e62b800
Fix syntax
techalchemy Nov 13, 2018
cb601b0
Fix syntax
techalchemy Nov 13, 2018
13c9e62
Update pythonfinder
techalchemy Nov 13, 2018
7bc754a
Merge branch 'master' into update-vendor
techalchemy Nov 13, 2018
d73879b
Update requirementslib
techalchemy Nov 13, 2018
e328ae2
Fix feedback
techalchemy Nov 13, 2018
310e0b2
Fix pythonfinder
techalchemy Nov 13, 2018
6b3c9a7
Remove accidentally committed test script
techalchemy Nov 13, 2018
4370281
Merge branch 'update-vendor' into feature/improved-async-installer
techalchemy Nov 13, 2018
c3cdbfb
Merge remote-tracking branch 'frostming/improve-toml-parse' into main…
techalchemy Nov 13, 2018
72e2ef7
Derive source names from URLs when not supplied
techalchemy Nov 13, 2018
1e3b8f9
Update news entries
techalchemy Nov 13, 2018
15f8d78
Syntax error and pythonfinder issue fixes
techalchemy Nov 13, 2018
f494571
Code cleanup -- unused functions
techalchemy Nov 13, 2018
2e10ff6
Fix pythonfinder
techalchemy Nov 13, 2018
f9b97da
Get rid of split file test
techalchemy Nov 14, 2018
095c9ef
remove useless tests
frostming Nov 14, 2018
08c384b
Implement `auto_envvar_prefix`
techalchemy Nov 14, 2018
2f97279
Update vendor file
techalchemy Nov 14, 2018
3585ef1
Merge branch 'maintenance/merge-3191-3196-3209' of github.com:pypa/pi…
techalchemy Nov 14, 2018
ec166f9
Reformat cli and command code
techalchemy Nov 14, 2018
e864343
Merge remote-tracking branch 'devxpy/master' into maintenance/merge-3…
techalchemy Nov 14, 2018
86c894d
Woops, delegator isn't updated, neither packaging
techalchemy Nov 14, 2018
ada66d3
Remove old patch
techalchemy Nov 14, 2018
bfa0b29
Update vendored deps
techalchemy Nov 14, 2018
5e5e1ed
Stray print
techalchemy Nov 14, 2018
08d94d4
Update core and rebuild ci
techalchemy Nov 14, 2018
a8f4c7e
accidental commit
techalchemy Nov 14, 2018
41cbe4d
Pin postreleases to pass packaging ci
techalchemy Nov 14, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix bugs in environment implementation
- Fix virtualenv
- Update pythonfinder

Signed-off-by: Dan Ryan <dan@danryan.co>
  • Loading branch information
techalchemy committed Nov 13, 2018
commit ef59d1520e9b84bd611587a2fd79680df19d53d9
5 changes: 3 additions & 2 deletions pipenv/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,8 @@ def do_create_virtualenv(python=None, site_packages=False, pypi_mirror=None):
prefix=project.get_location_for_virtualenv(),
is_venv=True,
sources=sources,
pipfile=project.parsed_pipfile
pipfile=project.parsed_pipfile,
project=project
)
project._environment.add_dist("pipenv")
# Say where the virtualenv is.
Expand Down Expand Up @@ -1621,7 +1622,7 @@ def do_outdated(pypi_mirror=None):
outdated_packages = {
canonicalize_name(pkg.project_name): package_info
(pkg.project_name, pkg.parsed_version, pkg.latest_version)
for pkg in project.get_outdated_packages()
for pkg in project.environment.get_outdated_packages()
}
for result in installed_packages:
dep = Requirement.from_line(str(result.as_requirement()))
Expand Down
33 changes: 18 additions & 15 deletions pipenv/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,26 @@


class Environment(object):
def __init__(self, prefix=None, is_venv=False, base_working_set=None, pipfile=None, sources=None):
def __init__(self, prefix=None, is_venv=False, base_working_set=None, pipfile=None,
sources=None, project=None):
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
prefix = os.path.normcase(os.path.normpath(os.path.abspath(str(prefix))))
self.is_venv = not prefix == os.path.normcase(os.path.normpath(sys.prefix))
if not sources:
sources = []
self.project = project
if project and not sources:
sources = project.sources
self.sources = sources
if project and not pipfile:
pipfile = project.pipfile
self.pipfile = pipfile
self.extra_dists = []
prefix = prefix if prefix else sys.prefix
self.prefix = vistir.compat.Path(prefix)
self.sys_paths = get_paths()

def safe_import(self, name):
"""Helper utility for reimporting previously imported modules while inside the env"""
Expand Down Expand Up @@ -73,7 +81,7 @@ def resolve_dist(cls, dist, working_set):
deps.add(dist)
try:
reqs = dist.requires()
except AttributeError:
except (AttributeError, OSError): # The METADATA file can't be found
return deps
for req in reqs:
dist = working_set.find(req)
Expand Down Expand Up @@ -187,12 +195,6 @@ def sys_path(self):
path = json.loads(path.strip())
return path

@cached_property
def system_paths(self):
paths = {}
paths = get_paths()
return paths

@cached_property
def sys_prefix(self):
"""The prefix run inside the context of the environment
Expand Down Expand Up @@ -271,7 +273,8 @@ def get_installed_packages(self):
packages = [pkg for pkg in workingset if self.dist_is_in_project(pkg)]
return packages

def get_finder(self):
@contextlib.contextmanager
def get_finder(self, pre=False):
from .vendor.pip_shims import Command, cmdoptions, index_group, PackageFinder
from .environments import PIPENV_CACHE_DIR
index_urls = [source.get("url") for source in self.sources]
Expand All @@ -286,10 +289,10 @@ class PipCommand(Command):
cmd_opts = pip_command.cmd_opts
pip_command.parser.insert_option_group(0, index_opts)
pip_command.parser.insert_option_group(0, cmd_opts)
pip_args = self._modules["pipenv"].utils.prepare_pip_source_args(self.sources, [])
pip_args = self._modules["pipenv"].utils.prepare_pip_source_args(self.sources)
pip_options, _ = pip_command.parser.parse_args(pip_args)
pip_options.cache_dir = PIPENV_CACHE_DIR
pip_options.pre = self.pipfile.get("pre", False)
pip_options.pre = self.pipfile.get("pre", pre)
with pip_command._build_session(pip_options) as session:
finder = PackageFinder(
find_links=pip_options.find_links,
Expand All @@ -300,7 +303,7 @@ class PipCommand(Command):
)
yield finder

def get_package_info(self):
def get_package_info(self, pre=False):
dependency_links = []
packages = self.get_installed_packages()
# This code is borrowed from pip's current implementation
Expand All @@ -314,7 +317,7 @@ def get_package_info(self):
for dist in packages:
typ = 'unknown'
all_candidates = finder.find_all_candidates(dist.key)
if not finder.pip_options.pre:
if not self.pipfile.get("pre", finder.allow_all_prereleases):
# Remove prereleases
all_candidates = [
candidate for candidate in all_candidates
Expand All @@ -334,9 +337,9 @@ def get_package_info(self):
dist.latest_filetype = typ
yield dist

def get_outdated_packages(self):
def get_outdated_packages(self, pre=False):
return [
pkg for pkg in self.get_package_info()
pkg for pkg in self.get_package_info(pre=pre)
if pkg.latest_version._version > pkg.parsed_version._version
]

Expand Down
5 changes: 3 additions & 2 deletions pipenv/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,13 +352,14 @@ def environment(self):
is_venv = prefix == sys.prefix
sources = self.sources if self.sources else [DEFAULT_SOURCE,]
self._environment = Environment(
prefix=prefix, is_venv=is_venv, sources=sources, pipfile=self.parsed_pipfile
prefix=prefix, is_venv=is_venv, sources=sources, pipfile=self.parsed_pipfile,
project=self
)
self._environment.add_dist("pipenv")
return self._environment

def get_outdated_packages(self):
return self.environment.get_outdated_packages()
return self.environment.get_outdated_packages(pre=self.pipfile.get("pre", False))

@classmethod
def _sanitize(cls, name):
Expand Down
4 changes: 4 additions & 0 deletions pipenv/vendor/pythonfinder/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
PYENV_INSTALLED = bool(os.environ.get("PYENV_SHELL")) or bool(
os.environ.get("PYENV_ROOT")
)
ASDF_INSTALLED = bool(os.environ.get("ASDF_DATA_DIR"))
PYENV_ROOT = os.path.expanduser(
os.path.expandvars(os.environ.get("PYENV_ROOT", "~/.pyenv"))
)
ASDF_DATA_DIR = os.path.expanduser(
os.path.expandvars(os.environ.get("ASDF_DATA_DIR", "~/.asdf"))
)
IS_64BIT_OS = None
SYSTEM_ARCH = platform.architecture()[0]

Expand Down
9 changes: 9 additions & 0 deletions pipenv/vendor/pythonfinder/models/asdf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# -*- coding=utf-8 -*-
import attr

from .pyenv import PyenvFinder


@attr.s
class AsdfFinder(PyenvFinder):
version_root = attr.ib(default="installs/python/*")
69 changes: 51 additions & 18 deletions pipenv/vendor/pythonfinder/models/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from vistir.compat import Path, fs_str

from .mixins import BasePath
from ..environment import PYENV_INSTALLED, PYENV_ROOT
from ..environment import PYENV_INSTALLED, PYENV_ROOT, ASDF_INSTALLED, ASDF_DATA_DIR
from ..exceptions import InvalidPythonVersion
from ..utils import (
ensure_path,
Expand All @@ -40,6 +40,7 @@ class SystemPath(object):
python_version_dict = attr.ib(default=attr.Factory(defaultdict))
only_python = attr.ib(default=False)
pyenv_finder = attr.ib(default=None, validator=optional_instance_of("PyenvPath"))
asdf_finder = attr.ib(default=None)
system = attr.ib(default=False)
_version_dict = attr.ib(default=attr.Factory(defaultdict))
ignore_unsupported = attr.ib(default=False)
Expand Down Expand Up @@ -105,6 +106,8 @@ def __attrs_post_init__(self):
self._setup_windows()
if PYENV_INSTALLED:
self._setup_pyenv()
if ASDF_INSTALLED:
self._setup_asdf()
venv = os.environ.get("VIRTUAL_ENV")
if os.name == "nt":
bin_dir = "Scripts"
Expand All @@ -124,32 +127,62 @@ def __attrs_post_init__(self):
path=syspath_bin, is_root=True, only_python=False
)

def _setup_pyenv(self):
from .pyenv import PyenvFinder

last_pyenv = next(
(p for p in reversed(self.path_order) if PYENV_ROOT.lower() in p.lower()),
def _get_last_instance(self, path):
last_instance = next(iter(
(p for p in reversed(self.path_order) if path.lower() in p.lower())),
None,
)
try:
pyenv_index = self.path_order.index(last_pyenv)
path_index = self.path_order.index(last_instance)
except ValueError:
return
return path_index

def _slice_in_paths(self, start_idx, paths):
before_path = self.path_order[: start_idx + 1]
after_path = self.path_order[start_idx + 2 :]
self.path_order = (
before_path + [p.as_posix() for p in paths] + after_path
)

def _remove_path(self, path):
path_copy = reversed(self.path_order[:])
new_order = []
target = os.path.normcase(os.path.normpath(os.path.abspath(path)))
path_map = {
os.path.normcase(os.path.normpath(os.path.abspath(pth))): pth
for pth in self.paths.keys()
}
if target in path_map:
del self.paths[path_map.get(target)]
for current_path in path_copy:
normalized = os.path.normcase(os.path.normpath(os.path.abspath(current_path)))
if normalized != target:
new_order.append(normalized)
new_order = reversed(new_order)
self.path_order = new_order

def _setup_asdf(self):
from .asdf import AsdfFinder
asdf_index = self._get_last_instance(ASDF_DATA_DIR)
self.asdf_finder = AsdfFinder.create(root=ASDF_DATA_DIR, ignore_unsupported=True)
root_paths = [p for p in self.asdf_finder.roots]
self._slice_in_paths(asdf_index, root_paths)
self.paths.update(self.asdf_finder.roots)
self._register_finder("asdf", self.asdf_finder)

def _setup_pyenv(self):
from .pyenv import PyenvFinder

pyenv_index = self._get_last_instance(PYENV_ROOT)
self.pyenv_finder = PyenvFinder.create(
root=PYENV_ROOT, ignore_unsupported=self.ignore_unsupported
)
root_paths = [p for p in self.pyenv_finder.roots]
before_path = self.path_order[: pyenv_index + 1]
after_path = self.path_order[pyenv_index + 2 :]
self.path_order = (
before_path + [p.as_posix() for p in root_paths] + after_path
)
pyenv_shim_path = os.path.join(PYENV_ROOT, "shims")
if pyenv_shim_path in self.path_order:
self.path_order.remove(pyenv_shim_path)
self._slice_in_paths(pyenv_index, root_paths)

self.paths.update(self.pyenv_finder.roots)
if pyenv_shim_path in self.paths:
del self.paths[pyenv_shim_path]
self._remove_path(os.path.join(PYENV_ROOT, "shims"))
self._register_finder("pyenv", self.pyenv_finder)

def _setup_windows(self):
Expand Down Expand Up @@ -396,7 +429,7 @@ def create(
)


@attr.s
@attr.s(slots=True)
class PathEntry(BasePath):
path = attr.ib(default=None, validator=optional_instance_of(Path))
_children = attr.ib(default=attr.Factory(dict))
Expand Down
7 changes: 4 additions & 3 deletions pipenv/vendor/pythonfinder/models/pyenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@
logger = logging.getLogger(__name__)


@attr.s
@attr.s(slots=True)
class PyenvFinder(BaseFinder, BasePath):
root = attr.ib(default=None, validator=optional_instance_of(Path))
#: ignore_unsupported should come before versions, because its value is used
#: in versions's default initializer.
ignore_unsupported = attr.ib(default=True)
paths = attr.ib(default=attr.Factory(list))
roots = attr.ib(default=attr.Factory(defaultdict))
version_root = attr.ib(default="versions/*")
versions = attr.ib()
pythons = attr.ib()

Expand All @@ -50,7 +51,7 @@ def get_version_order(self):
version_order_lines = version_order_file.read_text(encoding="utf-8").splitlines()

version_paths = [
p for p in self.root.glob("versions/*")
p for p in self.root.glob(self.version_root)
if not (p.parent.name == "envs" or p.name == "envs")
]
versions = {v.name: v for v in version_paths}
Expand All @@ -74,7 +75,7 @@ def version_from_bin_dir(cls, base_dir, name=None):
@versions.default
def get_versions(self):
versions = defaultdict()
bin_ = sysconfig._INSTALL_SCHEMES['posix_prefix']["scripts"]
bin_ = "{base}/bin"
for p in self.get_version_order():
bin_dir = Path(bin_.format(base=p.as_posix()))
version_path = None
Expand Down
2 changes: 1 addition & 1 deletion pipenv/vendor/pythonfinder/models/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
)


@attr.s
@attr.s(slots=True)
class PythonVersion(object):
major = attr.ib(default=0)
minor = attr.ib(default=None)
Expand Down
6 changes: 3 additions & 3 deletions pipenv/vendor/pythonfinder/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def get_python_version(path):
version_cmd = [path, "-c", "import sys; print(sys.version.split()[0])"]
try:
c = vistir.misc.run(version_cmd, block=True, nospin=True, return_object=True,
combine_stderr=False)
combine_stderr=False)
except OSError:
raise InvalidPythonVersion("%s is not a valid python path" % path)
if not c.out:
Expand Down Expand Up @@ -92,7 +92,7 @@ def looks_like_python(name):

@lru_cache(maxsize=1024)
def path_is_python(path):
return path_is_executable(path) and looks_like_python(path.name)
return path_is_known_executable(path) and looks_like_python(path.name)


@lru_cache(maxsize=1024)
Expand All @@ -117,7 +117,7 @@ def _filter_none(k, v):
return False


@lru_cache(maxsize=128)
@lru_cache(maxsize=1024)
def filter_pythons(path):
"""Return all valid pythons in a given path"""
if not isinstance(path, vistir.compat.Path):
Expand Down