Update pythonfinder

Signed-off-by: Dan Ryan <dan@danryan.co>
This commit is contained in:
Dan Ryan
2019-07-06 03:26:51 -04:00
parent e559b00a90
commit e2b38d2741
6 changed files with 74 additions and 17 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ from .exceptions import InvalidPythonVersion
from .models import SystemPath, WindowsFinder
from .pythonfinder import Finder
__version__ = "1.2.1"
__version__ = "1.2.2.dev0"
logger = logging.getLogger(__name__)
@@ -15,7 +15,8 @@ import sys
# These tags are treated specially when the Company is 'PythonCore'
_PYTHONCORE_COMPATIBILITY_TAGS = {
'2.0', '2.1', '2.2', '2.3', '2.4', '2.5', '2.6', '2.7',
'3.0', '3.1', '3.2', '3.3', '3.4'
'3.0', '3.1', '3.2', '3.3', '3.4', '3.5', '3.6', '3.7',
'3.8'
}
_IS_64BIT_OS = None
+2 -2
View File
@@ -14,8 +14,6 @@ from cached_property import cached_property
from vistir.compat import Path, fs_str
from vistir.misc import dedup
from .mixins import BaseFinder, BasePath
from .python import PythonVersion
from ..environment import (
ASDF_DATA_DIR,
ASDF_INSTALLED,
@@ -42,6 +40,8 @@ from ..utils import (
split_version_and_name,
unnest,
)
from .mixins import BaseFinder, BasePath
from .python import PythonVersion
if MYPY_RUNNING:
from typing import (
+28 -9
View File
@@ -13,7 +13,6 @@ import six
from packaging.version import Version
from vistir.compat import Path, lru_cache
from .mixins import BaseFinder, BasePath
from ..environment import ASDF_DATA_DIR, MYPY_RUNNING, PYENV_ROOT, SYSTEM_ARCH
from ..exceptions import InvalidPythonVersion
from ..utils import (
@@ -21,14 +20,17 @@ from ..utils import (
_filter_none,
ensure_path,
get_python_version,
guess_company,
is_in_path,
looks_like_python,
optional_instance_of,
parse_asdf_version_order,
parse_pyenv_version_order,
parse_python_version,
path_is_pythoncore,
unnest,
)
from .mixins import BaseFinder, BasePath
if MYPY_RUNNING:
from typing import (
@@ -114,7 +116,8 @@ class PythonFinder(BaseFinder, BasePath):
versions[v] for v in parse_asdf_version_order() if v in versions
]
for version in version_order:
version_paths.remove(version)
if version in version_paths:
version_paths.remove(version)
if version_order:
version_order += version_paths
else:
@@ -351,6 +354,7 @@ class PythonVersion(object):
architecture = attr.ib(default=None) # type: Optional[str]
comes_from = attr.ib(default=None) # type: Optional[PathEntry]
executable = attr.ib(default=None) # type: Optional[str]
company = attr.ib(default="PythonCore") # type: Optional[str]
name = attr.ib(default=None, type=str)
def __getattribute__(self, key):
@@ -381,11 +385,14 @@ class PythonVersion(object):
"""
A tuple for sorting against other instances of the same class.
Returns a tuple of the python version but includes a point for non-dev,
and a point for non-prerelease versions. So released versions will have 2 points
for this value. E.g. `(3, 6, 6, 2)` is a release, `(3, 6, 6, 1)` is a prerelease,
`(3, 6, 6, 0)` is a dev release, and `(3, 6, 6, 3)` is a postrelease.
Returns a tuple of the python version but includes points for core python,
non-dev, and non-prerelease versions. So released versions will have 2 points
for this value. E.g. ``(1, 3, 6, 6, 2)`` is a release, ``(1, 3, 6, 6, 1)`` is a
prerelease, ``(1, 3, 6, 6, 0)`` is a dev release, and ``(1, 3, 6, 6, 3)`` is a
postrelease. ``(0, 3, 7, 3, 2)`` represents a non-core python release, e.g. by
a repackager of python like Continuum.
"""
company_sort = 1 if self.company == "PythonCore" else 0
release_sort = 2
if self.is_postrelease:
release_sort = 3
@@ -395,7 +402,13 @@ class PythonVersion(object):
release_sort = 0
elif self.is_debug:
release_sort = 1
return (self.major, self.minor, self.patch if self.patch else 0, release_sort)
return (
company_sort,
self.major,
self.minor,
self.patch if self.patch else 0,
release_sort,
)
@property
def version_tuple(self):
@@ -473,6 +486,7 @@ class PythonVersion(object):
"is_devrelease": self.is_devrelease,
"is_debug": self.is_debug,
"version": self.version,
"company": self.company,
}
def update_metadata(self, metadata):
@@ -532,8 +546,8 @@ class PythonVersion(object):
return self.architecture
@classmethod
def from_path(cls, path, name=None, ignore_unsupported=True):
# type: (Union[str, PathEntry], Optional[str], bool) -> PythonVersion
def from_path(cls, path, name=None, ignore_unsupported=True, company=None):
# type: (Union[str, PathEntry], Optional[str], bool, Optional[str]) -> PythonVersion
"""
Parses a python version from a system path.
@@ -544,6 +558,7 @@ class PythonVersion(object):
:type path: str or :class:`~pythonfinder.models.path.PathEntry` instance
:param str name: Name of the python distribution in question
:param bool ignore_unsupported: Whether to ignore or error on unsupported paths.
:param Optional[str] company: The company or vendor packaging the distribution.
:return: An instance of a PythonVersion.
:rtype: :class:`~pythonfinder.models.python.PythonVersion`
"""
@@ -576,6 +591,8 @@ class PythonVersion(object):
instance_dict = cls.parse_executable(path.path.absolute().as_posix())
if name is None:
name = path_name
if company is None:
company = guess_company(path.path.as_posix())
instance_dict.update(
{"comes_from": path, "name": name, "executable": path.path.as_posix()}
)
@@ -622,6 +639,7 @@ class PythonVersion(object):
exe_path = ensure_path(
getattr(launcher_entry.info.install_path, "executable_path", default_path)
)
company = getattr(launcher_entry, "company", "PythonCore")
creation_dict.update(
{
"architecture": getattr(
@@ -629,6 +647,7 @@ class PythonVersion(object):
),
"executable": exe_path,
"name": name,
"company": company,
}
)
py_version = cls.create(**creation_dict)
+7 -4
View File
@@ -6,12 +6,12 @@ from collections import defaultdict
import attr
from .mixins import BaseFinder
from .path import PathEntry
from .python import PythonVersion, VersionMap
from ..environment import MYPY_RUNNING
from ..exceptions import InvalidPythonVersion
from ..utils import ensure_path
from .mixins import BaseFinder
from .path import PathEntry
from .python import PythonVersion, VersionMap
if MYPY_RUNNING:
from typing import DefaultDict, Tuple, List, Optional, Union, TypeVar, Type, Any
@@ -81,6 +81,7 @@ class WindowsFinder(BaseFinder):
path = None
for version_object in env_versions:
install_path = getattr(version_object.info, "install_path", None)
name = getattr(version_object, "tag", None)
if install_path is None:
continue
try:
@@ -88,7 +89,9 @@ class WindowsFinder(BaseFinder):
except AttributeError:
continue
try:
py_version = PythonVersion.from_windows_launcher(version_object)
py_version = PythonVersion.from_windows_launcher(
version_object, name=name
)
except InvalidPythonVersion:
continue
if py_version is None:
+34
View File
@@ -239,6 +239,40 @@ def path_is_python(path):
return path_is_executable(path) and looks_like_python(path.name)
@lru_cache(maxsize=1024)
def guess_company(path):
# type: (str) -> Optional[str]
"""Given a path to python, guess the company who created it
:param str path: The path to guess about
:return: The guessed company
:rtype: Optional[str]
"""
non_core_pythons = [impl for impl in PYTHON_IMPLEMENTATIONS if impl != "python"]
return next(
iter(impl for impl in non_core_pythons if impl in path.lower()), "PythonCore"
)
@lru_cache(maxsize=1024)
def path_is_pythoncore(path):
# type: (str) -> bool
"""Given a path, determine whether it appears to be pythoncore.
Does not verify whether the path is in fact a path to python, but simply
does an exclusionary check on the possible known python implementations
to see if their names are present in the path (fairly dumb check).
:param str path: The path to check
:return: Whether that path is a PythonCore path or not
:rtype: bool
"""
company = guess_company(path)
if company:
return company == "PythonCore"
return False
@lru_cache(maxsize=1024)
def ensure_path(path):
# type: (Union[vistir.compat.Path, str]) -> vistir.compat.Path