mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
Syntax error and pythonfinder issue fixes
Signed-off-by: Dan Ryan <dan@danryan.co>
This commit is contained in:
+1
-2
@@ -1142,8 +1142,7 @@ def normalize_path(path):
|
||||
def get_url_name(url):
|
||||
if not isinstance(url, six.string_types):
|
||||
return
|
||||
from urllib3.util import parse as urllib3_parse
|
||||
return urllib3_parse(url).host
|
||||
return urllib3_util.parse_url(url).host
|
||||
|
||||
|
||||
def get_canonical_names(packages):
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
# -*- coding=utf-8 -*-
|
||||
import attr
|
||||
|
||||
from .pyenv import PyenvFinder
|
||||
|
||||
|
||||
@attr.s
|
||||
class AsdfFinder(PyenvFinder):
|
||||
version_root = attr.ib(default="installs/python/*")
|
||||
+22
-20
@@ -131,7 +131,8 @@ class SystemPath(object):
|
||||
)
|
||||
|
||||
def _get_last_instance(self, path):
|
||||
paths = [normalize_path(p) for p in reversed(self.path_order)]
|
||||
reversed_paths = reversed(self.path_order)
|
||||
paths = [normalize_path(p) for p in reversed_paths]
|
||||
normalized_target = normalize_path(path)
|
||||
last_instance = next(
|
||||
iter(p for p in paths if normalized_target in p), None
|
||||
@@ -150,7 +151,7 @@ class SystemPath(object):
|
||||
)
|
||||
|
||||
def _remove_path(self, path):
|
||||
path_copy = reversed(self.path_order[:])
|
||||
path_copy = [p for p in reversed(self.path_order[:])]
|
||||
new_order = []
|
||||
target = normalize_path(path)
|
||||
path_map = {
|
||||
@@ -163,22 +164,23 @@ class SystemPath(object):
|
||||
normalized = normalize_path(current_path)
|
||||
if normalized != target:
|
||||
new_order.append(normalized)
|
||||
new_order = reversed(new_order)
|
||||
new_order = [p for p in reversed(new_order)]
|
||||
self.path_order = new_order
|
||||
|
||||
def _setup_asdf(self):
|
||||
from .python import PythonFinder
|
||||
self.asdf_finder = PythonFinder.create(
|
||||
root=ASDF_DATA_DIR, ignore_unsupported=True,
|
||||
sort_function=parse_asdf_version_order, version_glob_path="installs/python/*")
|
||||
asdf_index = self._get_last_instance(ASDF_DATA_DIR)
|
||||
if not asdf_index:
|
||||
# we are in a virtualenv without global pyenv on the path, so we should
|
||||
# not write pyenv to the path here
|
||||
return
|
||||
self.asdf_finder = PythonFinder.create(
|
||||
root=ASDF_DATA_DIR, ignore_unsupported=True,
|
||||
sort_function=parse_asdf_version_order, version_glob_path="installs/python/*")
|
||||
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._remove_path(normalize_path(os.path.join(ASDF_DATA_DIR, "shims")))
|
||||
self._register_finder("asdf", self.asdf_finder)
|
||||
|
||||
def _setup_pyenv(self):
|
||||
@@ -452,7 +454,7 @@ class PathEntry(BasePath):
|
||||
only_python = attr.ib(default=False)
|
||||
name = attr.ib()
|
||||
py_version = attr.ib()
|
||||
pythons = attr.ib()
|
||||
_pythons = attr.ib(default=attr.Factory(defaultdict))
|
||||
|
||||
def __str__(self):
|
||||
return fs_str("{0}".format(self.path.as_posix()))
|
||||
@@ -506,19 +508,19 @@ class PathEntry(BasePath):
|
||||
return py_version
|
||||
return
|
||||
|
||||
@pythons.default
|
||||
def get_pythons(self):
|
||||
pythons = defaultdict()
|
||||
if self.is_dir:
|
||||
for path, entry in self.children.items():
|
||||
_path = ensure_path(entry.path)
|
||||
if entry.is_python:
|
||||
pythons[_path.as_posix()] = entry
|
||||
else:
|
||||
if self.is_python:
|
||||
_path = ensure_path(self.path)
|
||||
pythons[_path.as_posix()] = self
|
||||
return pythons
|
||||
@property
|
||||
def pythons(self):
|
||||
if not self._pythons:
|
||||
if self.is_dir:
|
||||
for path, entry in self.children.items():
|
||||
_path = ensure_path(entry.path)
|
||||
if entry.is_python:
|
||||
self._pythons[_path.as_posix()] = entry
|
||||
else:
|
||||
if self.is_python:
|
||||
_path = ensure_path(self.path)
|
||||
self._pythons[_path.as_posix()] = self
|
||||
return self._pythons
|
||||
|
||||
@cached_property
|
||||
def as_python(self):
|
||||
|
||||
-237
@@ -1,237 +0,0 @@
|
||||
# -*- coding=utf-8 -*-
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
import logging
|
||||
import operator
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
import attr
|
||||
import sysconfig
|
||||
|
||||
from vistir.compat import Path
|
||||
|
||||
from ..utils import (
|
||||
ensure_path,
|
||||
optional_instance_of,
|
||||
unnest,
|
||||
)
|
||||
from .mixins import BaseFinder, BasePath
|
||||
from .path import SystemPath, PathEntry
|
||||
from .python import PythonVersion
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@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()
|
||||
|
||||
@property
|
||||
def expanded_paths(self):
|
||||
return (
|
||||
path for path in unnest(p for p in self.versions.values())
|
||||
if path is not None
|
||||
)
|
||||
|
||||
def get_version_order(self):
|
||||
version_order_file, version_order_lines = self.root.joinpath("version"), []
|
||||
if version_order_file.exists():
|
||||
version_order_lines = version_order_file.read_text(encoding="utf-8").splitlines()
|
||||
|
||||
version_paths = [
|
||||
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}
|
||||
version_order = [versions[v] for v in version_order_lines if v in versions]
|
||||
for version in version_order:
|
||||
version_paths.remove(version)
|
||||
version_order += version_paths
|
||||
return version_order
|
||||
|
||||
@classmethod
|
||||
def version_from_bin_dir(cls, base_dir, name=None):
|
||||
py_version = None
|
||||
version_path = PathEntry.create(
|
||||
path=base_dir.absolute().as_posix(),
|
||||
only_python=True,
|
||||
name=base_dir.parent.name,
|
||||
)
|
||||
py_version = next(iter(version_path.find_all_python_versions()), None)
|
||||
return py_version
|
||||
|
||||
@versions.default
|
||||
def get_versions(self):
|
||||
versions = defaultdict()
|
||||
bin_ = "{base}/bin"
|
||||
for p in self.get_version_order():
|
||||
bin_dir = Path(bin_.format(base=p.as_posix()))
|
||||
version_path = None
|
||||
if bin_dir.exists():
|
||||
version_path = PathEntry.create(
|
||||
path=bin_dir.absolute().as_posix(),
|
||||
only_python=False,
|
||||
name=p.name,
|
||||
is_root=True,
|
||||
)
|
||||
version = None
|
||||
try:
|
||||
version = PythonVersion.parse(p.name)
|
||||
except ValueError:
|
||||
entry = next(iter(version_path.find_all_python_versions()), None)
|
||||
if not entry:
|
||||
if self.ignore_unsupported:
|
||||
continue
|
||||
raise
|
||||
else:
|
||||
version = entry.py_version.as_dict()
|
||||
except Exception:
|
||||
if not self.ignore_unsupported:
|
||||
raise
|
||||
logger.warning(
|
||||
"Unsupported Python version %r, ignoring...", p.name, exc_info=True
|
||||
)
|
||||
continue
|
||||
if not version:
|
||||
continue
|
||||
version_tuple = (
|
||||
version.get("major"),
|
||||
version.get("minor"),
|
||||
version.get("patch"),
|
||||
version.get("is_prerelease"),
|
||||
version.get("is_devrelease"),
|
||||
version.get("is_debug"),
|
||||
)
|
||||
self.roots[p] = version_path
|
||||
versions[version_tuple] = version_path
|
||||
self.paths.append(version_path)
|
||||
return versions
|
||||
|
||||
@pythons.default
|
||||
def get_pythons(self):
|
||||
pythons = defaultdict()
|
||||
for p in self.paths:
|
||||
pythons.update(p.pythons)
|
||||
return pythons
|
||||
|
||||
@classmethod
|
||||
def create(cls, root, ignore_unsupported=True):
|
||||
root = ensure_path(root)
|
||||
return cls(root=root, ignore_unsupported=ignore_unsupported)
|
||||
|
||||
def find_all_python_versions(
|
||||
self,
|
||||
major=None,
|
||||
minor=None,
|
||||
patch=None,
|
||||
pre=None,
|
||||
dev=None,
|
||||
arch=None,
|
||||
name=None,
|
||||
):
|
||||
"""Search for a specific python version on the path. Return all copies
|
||||
|
||||
:param major: Major python version to search for.
|
||||
:type major: int
|
||||
:param int minor: Minor python version to search for, defaults to None
|
||||
:param int patch: Patch python version to search for, defaults to None
|
||||
:param bool pre: Search for prereleases (default None) - prioritize releases if None
|
||||
:param bool dev: Search for devreleases (default None) - prioritize releases if None
|
||||
:param str arch: Architecture to include, e.g. '64bit', defaults to None
|
||||
:param str name: The name of a python version, e.g. ``anaconda3-5.3.0``
|
||||
:return: A list of :class:`~pythonfinder.models.PathEntry` instances matching the version requested.
|
||||
:rtype: List[:class:`~pythonfinder.models.PathEntry`]
|
||||
"""
|
||||
|
||||
version_matcher = operator.methodcaller(
|
||||
"matches",
|
||||
major=major,
|
||||
minor=minor,
|
||||
patch=patch,
|
||||
pre=pre,
|
||||
dev=dev,
|
||||
arch=arch,
|
||||
name=name,
|
||||
)
|
||||
py = operator.attrgetter("as_python")
|
||||
pythons = (
|
||||
py_ver for py_ver in (py(p) for p in self.pythons.values() if p is not None)
|
||||
if py_ver is not None
|
||||
)
|
||||
# pythons = filter(None, [p.as_python for p in self.pythons.values()])
|
||||
matching_versions = filter(lambda py: version_matcher(py), pythons)
|
||||
version_sort = operator.attrgetter("version_sort")
|
||||
return sorted(matching_versions, key=version_sort, reverse=True)
|
||||
|
||||
def find_python_version(
|
||||
self,
|
||||
major=None,
|
||||
minor=None,
|
||||
patch=None,
|
||||
pre=None,
|
||||
dev=None,
|
||||
arch=None,
|
||||
name=None,
|
||||
):
|
||||
"""Search or self for the specified Python version and return the first match.
|
||||
|
||||
:param major: Major version number.
|
||||
:type major: int
|
||||
:param int minor: Minor python version to search for, defaults to None
|
||||
:param int patch: Patch python version to search for, defaults to None
|
||||
:param bool pre: Search for prereleases (default None) - prioritize releases if None
|
||||
:param bool dev: Search for devreleases (default None) - prioritize releases if None
|
||||
:param str arch: Architecture to include, e.g. '64bit', defaults to None
|
||||
:param str name: The name of a python version, e.g. ``anaconda3-5.3.0``
|
||||
:returns: A :class:`~pythonfinder.models.PathEntry` instance matching the version requested.
|
||||
"""
|
||||
|
||||
version_matcher = operator.methodcaller(
|
||||
"matches",
|
||||
major=major,
|
||||
minor=minor,
|
||||
patch=patch,
|
||||
pre=pre,
|
||||
dev=dev,
|
||||
arch=arch,
|
||||
name=name,
|
||||
)
|
||||
pythons = filter(None, [p.as_python for p in self.pythons.values()])
|
||||
matching_versions = filter(lambda py: version_matcher(py), pythons)
|
||||
version_sort = operator.attrgetter("version_sort")
|
||||
return next(iter(c for c in sorted(matching_versions, key=version_sort, reverse=True)), None)
|
||||
|
||||
|
||||
@attr.s
|
||||
class VersionPath(SystemPath):
|
||||
base = attr.ib(default=None, validator=optional_instance_of(Path))
|
||||
name = attr.ib(default=None)
|
||||
|
||||
@classmethod
|
||||
def create(cls, path, only_python=True, pythons=None, name=None):
|
||||
"""Accepts a path to a base python version directory.
|
||||
|
||||
Generates the pyenv version listings for it"""
|
||||
path = ensure_path(path)
|
||||
path_entries = defaultdict(PathEntry)
|
||||
bin_ = sysconfig._INSTALL_SCHEMES[sysconfig._get_default_scheme()]["scripts"]
|
||||
if path.as_posix().endswith(Path(bin_).name):
|
||||
path = path.parent
|
||||
bin_dir = ensure_path(bin_.format(base=path.as_posix()))
|
||||
if not name:
|
||||
name = path.name
|
||||
current_entry = PathEntry.create(
|
||||
bin_dir, is_root=True, only_python=True, pythons=pythons, name=name
|
||||
)
|
||||
path_entries[bin_dir.as_posix()] = current_entry
|
||||
return cls(name=name, base=bin_dir, paths=path_entries)
|
||||
Vendored
+6
-4
@@ -12,7 +12,7 @@ import six
|
||||
|
||||
import vistir
|
||||
|
||||
from .environment import PYENV_INSTALLED, PYENV_ROOT, ASDF_INSTALLED, ASDF_DATA_DIR
|
||||
from .environment import PYENV_ROOT
|
||||
from .exceptions import InvalidPythonVersion
|
||||
|
||||
try:
|
||||
@@ -90,7 +90,7 @@ def looks_like_python(name):
|
||||
|
||||
@lru_cache(maxsize=1024)
|
||||
def path_is_python(path):
|
||||
return path_is_known_executable(path) and looks_like_python(path.name)
|
||||
return path_is_executable(path) and looks_like_python(path.name)
|
||||
|
||||
|
||||
@lru_cache(maxsize=1024)
|
||||
@@ -116,7 +116,9 @@ def _filter_none(k, v):
|
||||
|
||||
|
||||
def normalize_path(path):
|
||||
return os.path.normpath(os.path.normcase(os.path.abspath(str(path))))
|
||||
return os.path.normpath(os.path.normcase(
|
||||
os.path.abspath(os.path.expandvars(os.path.expanduser(str(path))))
|
||||
))
|
||||
|
||||
|
||||
@lru_cache(maxsize=1024)
|
||||
@@ -161,7 +163,7 @@ def parse_asdf_version_order(filename=".tool-versions"):
|
||||
line for line in contents.splitlines() if line.startswith("python")
|
||||
), None)
|
||||
if python_section:
|
||||
python_key, versions = python_section.partition()
|
||||
python_key, _, versions = python_section.partition(" ")
|
||||
if versions:
|
||||
return versions.split()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user