Skip to content

Commit

Permalink
Performance overhaul
Browse files Browse the repository at this point in the history
- Improve lookups and fallbacks for all finders
- Add support for named pythons, such as `anaconda...`
- Fix `pythonz` failures
- Fixes #19
- Fixes #20

Signed-off-by: Dan Ryan <dan@danryan.co>
  • Loading branch information
techalchemy committed Oct 18, 2018
1 parent 551c5a8 commit a3bfc96
Show file tree
Hide file tree
Showing 15 changed files with 557 additions and 199 deletions.
1 change: 1 addition & 0 deletions news/19.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Switch to using ``--ignore-unsupported`` by default during lookups.
1 change: 1 addition & 0 deletions news/20.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Introduced lookup by name when searching for python versions, which allows searching for non-standard python releases such as ``anaconda3-5.3.0``.
3 changes: 3 additions & 0 deletions news/21.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
General improvements:
- Improved ``pyenv`` support and architecture lookup support.
- Improved overall performance and caching.
9 changes: 5 additions & 4 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,15 @@ package_data =
LICENSE*
README*
install_requires =
attrs
backports.functools_lru_cache; python_version <= "3.4"
cached-property
click
crayons
packaging
vistir
pathlib2;python_version<"3.5"
six
crayons
attrs
cached-property
vistir

[options.packages.find]
where = src
Expand Down
18 changes: 8 additions & 10 deletions src/pythonfinder/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
@click.option(
"--version", is_flag=True, default=False, help="Display PythonFinder version."
)
@click.option("--ignore-unsupported/--no-unsupported", is_flag=True, default=True, help="Ignore unsupported python versions.")
@click.option("--ignore-unsupported/--no-unsupported", is_flag=True, default=True, envvar="PYTHONFINDER_IGNORE_UNSUPPORTED", help="Ignore unsupported python versions.")
@click.version_option(prog_name='pyfinder', version=__version__)
@click.pass_context
def cli(ctx, find=False, which=False, findall=False, version=False, ignore_unsupported=True):
Expand All @@ -36,7 +36,7 @@ def cli(ctx, find=False, which=False, findall=False, version=False, ignore_unsup
for v in versions:
py = v.py_version
click.secho(
"Python: {py.version!s} ({py.architecture!s}) @ {py.comes_from.path!s}".format(
"{py.name!s}: {py.version!s} ({py.architecture!s}) @ {py.comes_from.path!s}".format(
py=py
),
fg="yellow",
Expand All @@ -47,23 +47,21 @@ def cli(ctx, find=False, which=False, findall=False, version=False, ignore_unsup
fg="red",
)
if find:
if any([find.startswith("{0}".format(n)) for n in range(10)]):
found = finder.find_python_version(find.strip())
else:
found = finder.system_path.python_executables
click.secho("Searching for python: {0!s}".format(find.strip()), fg="yellow")
found = finder.find_python_version(find.strip())
if found:
click.echo("Found Python Version: {0}".format(found), color="white")
click.secho("Found python at the following locations:", fg="green")
sys.exit(0)
else:
click.echo("Failed to find matching executable...")
click.secho("Failed to find matching executable...", fg="yellow")
sys.exit(1)
elif which:
found = finder.system_path.which(which.strip())
if found:
click.echo("Found Executable: {0}".format(found), color="white")
click.secho("Found Executable: {0}".format(found), fg="white")
sys.exit(0)
else:
click.echo("Failed to find matching executable...")
click.secho("Failed to find matching executable...", fg="yellow")
sys.exit(1)
else:
click.echo("Please provide a command", color="red")
Expand Down
3 changes: 3 additions & 0 deletions src/pythonfinder/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@
IS_64BIT_OS = platform.machine() == "AMD64"
else:
IS_64BIT_OS = False


IGNORE_UNSUPPORTED = bool(os.environ.get("PYTHONFINDER_IGNORE_UNSUPPORTED", False))
38 changes: 32 additions & 6 deletions src/pythonfinder/models/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
from __future__ import absolute_import, unicode_literals

import abc
import attr
import operator
import six

from ..utils import KNOWN_EXTS, unnest
from ..utils import ensure_path, KNOWN_EXTS, unnest


@attr.s
class BasePath(object):
def which(self, name):
"""Search in this path for an executable.
Expand All @@ -33,7 +35,14 @@ def which(self, name):
return found

def find_all_python_versions(
self, major=None, minor=None, patch=None, pre=None, dev=None, arch=None
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
Expand All @@ -44,6 +53,7 @@ def find_all_python_versions(
: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`]
"""
Expand All @@ -52,7 +62,14 @@ def find_all_python_versions(
"find_all_python_versions" if self.is_dir else "find_python_version"
)
sub_finder = operator.methodcaller(
call_method, major, minor=minor, patch=patch, pre=pre, dev=dev, arch=arch
call_method,
major=major,
minor=minor,
patch=patch,
pre=pre,
dev=dev,
arch=arch,
name=name,
)
if not self.is_dir:
return sub_finder(self)
Expand All @@ -61,7 +78,14 @@ def find_all_python_versions(
return [c for c in sorted(path_filter, key=version_sort, reverse=True)]

def find_python_version(
self, major=None, minor=None, patch=None, pre=None, dev=None, arch=None
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.
Expand All @@ -72,6 +96,7 @@ def find_python_version(
: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.
"""

Expand All @@ -83,12 +108,13 @@ def find_python_version(
pre=pre,
dev=dev,
arch=arch,
name=name,
)
is_py = operator.attrgetter("is_python")
py_version = operator.attrgetter("as_python")
if not self.is_dir:
if self.is_python and self.as_python and version_matcher(self.as_python):
return self
if self.is_python and self.as_python and version_matcher(self.py_version):
return attr.evolve(self)
return
finder = (
(child, child.as_python)
Expand Down
Loading

0 comments on commit a3bfc96

Please sign in to comment.