Skip to content

Commit

Permalink
Fix pyenv usage for windows and linux. (#137)
Browse files Browse the repository at this point in the history
* Fix pyenv usage for windows and linux.

* Fix asd usage for windows and linux.
  • Loading branch information
matteius committed May 16, 2023
1 parent dcee887 commit 2293771
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 30 deletions.
1 change: 1 addition & 0 deletions news/137.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Corrected ``asdf`` and ``pyenv`` detection and usage which broke with the release of ``pythonfinder==2.0.0``
65 changes: 56 additions & 9 deletions src/pythonfinder/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import os
import platform
import sys
import posixpath
import ntpath
import re
import shutil


def is_type_checking():
Expand All @@ -13,16 +17,19 @@ def is_type_checking():
return TYPE_CHECKING


PYENV_INSTALLED = bool(os.environ.get("PYENV_SHELL")) or bool(
os.environ.get("PYENV_ROOT")
)
ASDF_INSTALLED = bool(os.environ.get("ASDF_DIR"))
PYENV_ROOT = os.path.expanduser(
os.path.expandvars(os.environ.get("PYENV_ROOT", "~/.pyenv"))
)
# Check if the path is in Unix-style (Git Bash)
if PYENV_ROOT.startswith('/') and os.name == 'nt':
# Convert to Windows-style path
drive, tail = re.match(r"^/([a-zA-Z])/(.*)", PYENV_ROOT).groups()
PYENV_ROOT = drive.upper() + ":\\" + tail.replace('/', '\\')
PYENV_INSTALLED = shutil.which("pyenv") != None
ASDF_DATA_DIR = os.path.expanduser(
os.path.expandvars(os.environ.get("ASDF_DATA_DIR", "~/.asdf"))
)
ASDF_INSTALLED = shutil.which("asdf") != None
IS_64BIT_OS = None
SYSTEM_ARCH = platform.architecture()[0]

Expand All @@ -41,10 +48,50 @@ def is_type_checking():
"""


def get_shim_paths():
shim_paths = []
def join_path_for_platform(path, path_parts):
# If we're on Unix or Unix-like system
if os.name == 'posix' or sys.platform == 'linux':
return posixpath.join(path, *path_parts)
# If we're on Windows
elif os.name == 'nt' or sys.platform == 'win32':
return ntpath.join(path, *path_parts)
else:
raise Exception("Unknown environment")


def set_asdf_paths():
if ASDF_INSTALLED:
shim_paths.append(os.path.join(ASDF_DATA_DIR, "shims"))
python_versions = join_path_for_platform(ASDF_DATA_DIR, ["installs", "python"])
try:
# Get a list of all files and directories in the given path
all_files_and_dirs = os.listdir(python_versions)
# Filter out files and keep only directories
for name in all_files_and_dirs:
if os.path.isdir(os.path.join(python_versions, name)):
asdf_path = os.path.join(python_versions, name)
asdf_path = os.path.join(asdf_path, "bin")
os.environ['PATH'] = asdf_path + os.pathsep + os.environ['PATH']
except FileNotFoundError:
pass


def set_pyenv_paths():
if PYENV_INSTALLED:
shim_paths.append(os.path.join(PYENV_ROOT, "shims"))
return [os.path.normpath(os.path.normcase(p)) for p in shim_paths]
is_windows = False
if os.name == "nt":
python_versions = join_path_for_platform(PYENV_ROOT, ["pyenv-win", "versions"])
is_windows = True
else:
python_versions = join_path_for_platform(PYENV_ROOT, ["versions"])
try:
# Get a list of all files and directories in the given path
all_files_and_dirs = os.listdir(python_versions)
# Filter out files and keep only directories
for name in all_files_and_dirs:
if os.path.isdir(os.path.join(python_versions, name)):
pyenv_path = os.path.join(python_versions, name)
if not is_windows:
pyenv_path = os.path.join(pyenv_path, "bin")
os.environ['PATH'] = pyenv_path + os.pathsep + os.environ['PATH']
except FileNotFoundError:
pass
9 changes: 0 additions & 9 deletions src/pythonfinder/models/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,13 @@

from pydantic import BaseModel, Field, validator

from ..environment import get_shim_paths
from ..exceptions import InvalidPythonVersion
from ..utils import (
KNOWN_EXTS,
ensure_path,
expand_paths,
filter_pythons,
is_in_path,
looks_like_python,
normalize_path,
path_is_known_executable,
)

Expand Down Expand Up @@ -317,7 +314,6 @@ def _filter_children(self) -> Iterator[Path]:
return children

def _gen_children(self) -> Iterator:
shim_paths = get_shim_paths()
pass_name = self.name != self.path.name
pass_args = {"is_root": False, "only_python": self.only_python}
if pass_name:
Expand All @@ -330,8 +326,6 @@ def _gen_children(self) -> Iterator:
yield (self.path.as_posix(), self)
elif self.is_root:
for child in self._filter_children():
if any(is_in_path(str(child), shim) for shim in shim_paths):
continue
if self.only_python:
try:
entry = PathEntry.create(path=child, **pass_args)
Expand Down Expand Up @@ -372,7 +366,6 @@ def create(
:param str name: Name of the python version, e.g. ``anaconda3-5.3.0``
:return: A new instance of the class.
"""

target = ensure_path(path)
guessed_name = False
if not name:
Expand All @@ -393,8 +386,6 @@ def create(
if not guessed_name:
child_creation_args["name"] = _new.name
for pth, python in pythons.items():
if any(shim in normalize_path(str(pth)) for shim in get_shim_paths()):
continue
pth = ensure_path(pth)
children[pth.as_posix()] = PathEntry(
py_version=python, path=pth, **child_creation_args
Expand Down
21 changes: 11 additions & 10 deletions src/pythonfinder/models/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
ASDF_INSTALLED,
PYENV_INSTALLED,
PYENV_ROOT,
get_shim_paths,
)
from ..utils import (
dedup,
Expand Down Expand Up @@ -180,10 +179,6 @@ def _run_setup(self) -> SystemPath:
path_instances = [
ensure_path(p.strip('"'))
for p in path_order
if not any(
is_in_path(normalize_path(str(p)), normalize_path(shim))
for shim in get_shim_paths()
)
]
self.paths.update(
{
Expand Down Expand Up @@ -249,6 +244,16 @@ def _slice_in_paths(self, start_idx, paths) -> SystemPath:
self.path_order = path_order
return self

def _remove_shims(self):
path_copy = [p for p in self.path_order[:]]
new_order = []
for current_path in path_copy:
if not current_path.endswith("shims"):
normalized = normalize_path(current_path)
new_order.append(normalized)
new_order = [ensure_path(p).as_posix() for p in new_order]
self.path_order = new_order

def _remove_path(self, path) -> SystemPath:
path_copy = [p for p in reversed(self.path_order[:])]
new_order = []
Expand Down Expand Up @@ -306,7 +311,6 @@ def _setup_pyenv(self) -> SystemPath:
version_glob_path="versions/*",
ignore_unsupported=self.ignore_unsupported,
)
pyenv_index = None
try:
pyenv_index = self._get_last_instance(PYENV_ROOT)
except ValueError:
Expand All @@ -321,7 +325,7 @@ def _setup_pyenv(self) -> SystemPath:
self.paths[pyenv_finder.root] = pyenv_finder
self.paths.update(pyenv_finder.roots)
self.pyenv_finder = pyenv_finder
self._remove_path(os.path.join(PYENV_ROOT, "shims"))
self._remove_shims()
self._register_finder("pyenv", pyenv_finder)
return self

Expand Down Expand Up @@ -518,9 +522,6 @@ def create(
}
)
paths = [path, *paths]
paths = [
p for p in paths if not any(is_in_path(p, shim) for shim in get_shim_paths())
]
_path_objects = [ensure_path(p.strip('"')) for p in paths]
path_entries.update(
{
Expand Down
2 changes: 0 additions & 2 deletions src/pythonfinder/models/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ class PythonFinder(PathEntry):
roots: Dict = Field(default_factory=lambda: defaultdict())
#: List of paths discovered during search
paths: List = Field(default_factory=lambda: list())
#: shim directory
shim_dir: str = "shims"
#: Versions discovered in the specified paths
_versions: Dict = Field(default_factory=lambda: defaultdict())
pythons_ref: Dict = Field(default_factory=lambda: defaultdict())
Expand Down
3 changes: 3 additions & 0 deletions src/pythonfinder/pythonfinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .models.common import FinderBaseModel
from .models.path import PathEntry, SystemPath
from .models.python import PythonVersion
from .environment import set_asdf_paths, set_pyenv_paths
from .utils import Iterable, version_re


Expand All @@ -32,6 +33,8 @@ def __eq__(self, other) -> bool:
return self.__hash__ == other.__hash__

def create_system_path(self) -> SystemPath:
set_asdf_paths()
set_pyenv_paths()
return SystemPath.create(
path=self.path_prepend,
system=self.system,
Expand Down

0 comments on commit 2293771

Please sign in to comment.