Syntax error and pythonfinder issue fixes

Signed-off-by: Dan Ryan <dan@danryan.co>
This commit is contained in:
Dan Ryan
2018-11-13 17:46:30 -05:00
parent 1e3b8f9615
commit 15f8d78bce
5 changed files with 29 additions and 272 deletions
+1 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+6 -4
View File
@@ -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()