Skip to content

Commit

Permalink
Port over latest changes from integration testing with pipenv -- comp…
Browse files Browse the repository at this point in the history
…letely remove the posix path conversions.
  • Loading branch information
matteius committed Jan 27, 2024
1 parent 627bd73 commit 6c7aff9
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 59 deletions.
22 changes: 11 additions & 11 deletions src/pythonfinder/models/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,22 @@ def set_children(self, children):
return children or self._gen_children()

def __str__(self) -> str:
return f"{self.path.as_posix()}"
return f"{self.path}"

def __lt__(self, other) -> bool:
return self.path.as_posix() < other.path.as_posix()
return self.path < other.path

def __lte__(self, other) -> bool:
return self.path.as_posix() <= other.path.as_posix()
return self.path <= other.path

def __gt__(self, other) -> bool:
return self.path.as_posix() > other.path.as_posix()
return self.path > other.path

def __gte__(self, other) -> bool:
return self.path.as_posix() >= other.path.as_posix()
return self.path >= other.path

def __eq__(self, other) -> bool:
return self.path.as_posix() == other.path.as_posix()
return self.path == other.path

def which(self, name) -> PathEntry | None:
"""Search in this path for an executable.
Expand All @@ -84,9 +84,9 @@ def which(self, name) -> PathEntry | None:
if self.path is not None:
found = next(
(
children[(self.path / child).as_posix()]
children[(self.path / child)]
for child in valid_names
if (self.path / child).as_posix() in children
if (self.path / child) in children
),
None,
)
Expand Down Expand Up @@ -207,7 +207,7 @@ def pythons(self) -> dict[str | Path, PathEntry]:
if not self.pythons_ref:
self.pythons_ref = defaultdict(PathEntry)
for python in self._iter_pythons():
python_path = python.path.as_posix()
python_path = python.path
self.pythons_ref[python_path] = python
return self.pythons_ref

Expand Down Expand Up @@ -320,7 +320,7 @@ def _gen_children(self):

try:
entry = PathEntry.create(path=child_path, **pass_args)
self.children_ref[child_path.as_posix()] = entry
self.children_ref[child_path] = entry
except (InvalidPythonVersion, ValueError):
continue # Or handle as needed

Expand Down Expand Up @@ -367,7 +367,7 @@ def create(
child_creation_args["name"] = _new.name
for pth, python in pythons.items():
pth = ensure_path(pth)
children[pth.as_posix()] = PathEntry(
children[str(path)] = PathEntry(
py_version=python, path=pth, **child_creation_args
)
_new.children_ref = children
Expand Down
70 changes: 42 additions & 28 deletions src/pythonfinder/models/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
parse_asdf_version_order,
parse_pyenv_version_order,
resolve_path,
split_version_and_name,
)
from .mixins import PathEntry
from .python import PythonFinder
Expand Down Expand Up @@ -157,9 +156,9 @@ def version_dict(self) -> DefaultDict[tuple, list[PathEntry]]:

def _handle_virtualenv_and_system_paths(self):
venv = os.environ.get("VIRTUAL_ENV")
bin_dir = "Scripts" if os.name == "nt" else "bin"
if venv:
venv_path = Path(venv).resolve()
bin_dir = "Scripts" if os.name == "nt" else "bin"
venv_bin_path = venv_path / bin_dir
if venv_bin_path.exists() and (self.system or self.global_search):
self.path_order = [str(venv_bin_path), *self.path_order]
Expand Down Expand Up @@ -235,7 +234,7 @@ def _remove_shims(self):
if not current_path.endswith("shims"):
normalized = resolve_path(current_path)
new_order.append(normalized)
new_order = [ensure_path(p).as_posix() for p in new_order]
new_order = [ensure_path(p) for p in new_order]
self.path_order = new_order

def _remove_path(self, path) -> SystemPath:
Expand Down Expand Up @@ -440,35 +439,50 @@ def sub_finder(obj):
def alternate_sub_finder(obj):
return obj.find_all_python_versions(None, None, None, None, None, None, name)

major, minor, patch, name = split_version_and_name(major, minor, patch, name)
if major and minor and patch:
_tuple_pre = pre if pre is not None else False
_tuple_dev = dev if dev is not None else False

if sort_by_path:
paths = [self.get_path(k) for k in self.path_order]
for path in paths:
found_version = sub_finder(path)
if found_version:
return found_version
if name and not (minor or patch or pre or dev or arch or major):
for path in paths:
found_version = alternate_sub_finder(path)
if found_version:
return found_version
found_version = self._find_version_by_path(
sub_finder,
alternate_sub_finder,
name,
minor,
patch,
pre,
dev,
arch,
major,
)
if found_version:
return found_version

ver = next(iter(self.get_pythons(sub_finder)), None)
if not ver and name and not (minor or patch or pre or dev or arch or major):
if not ver and name and not any([minor, patch, pre, dev, arch, major]):
ver = next(iter(self.get_pythons(alternate_sub_finder)), None)

if ver:
if ver.as_python.version_tuple[:5] in self.python_version_dict:
self.python_version_dict[ver.as_python.version_tuple[:5]].append(ver)
else:
self.python_version_dict[ver.as_python.version_tuple[:5]] = [ver]
self._update_python_version_dict(ver)

return ver

def _find_version_by_path(self, sub_finder, alternate_sub_finder, name, *args):
paths = [self.get_path(k) for k in self.path_order]
for path in paths:
found_version = sub_finder(path)
if found_version:
return found_version
if name and not any(args):
for path in paths:
found_version = alternate_sub_finder(path)
if found_version:
return found_version
return None

def _update_python_version_dict(self, ver):
if ver:
version_key = ver.as_python.version_tuple[:5]
if version_key in self.python_version_dict:
self.python_version_dict[version_key].append(ver)
else:
self.python_version_dict[version_key] = [ver]

@classmethod
def create(
cls,
Expand Down Expand Up @@ -501,18 +515,18 @@ def create(
path_instance = ensure_path(path)
path_entries.update(
{
path_instance.as_posix(): PathEntry.create(
path=path_instance.absolute(),
path_instance: PathEntry.create(
path=path_instance.resolve(),
is_root=True,
only_python=only_python,
)
}
)
paths = [path, *paths]
_path_objects = [ensure_path(p.strip('"')) for p in paths]
_path_objects = [ensure_path(p) for p in paths]
path_entries.update(
{
p.as_posix(): PathEntry.create(
str(p): PathEntry.create(
path=p.absolute(), is_root=True, only_python=only_python
)
for p in _path_objects
Expand Down
20 changes: 9 additions & 11 deletions src/pythonfinder/models/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ def versions(self) -> DefaultDict[tuple, PathEntry]:

def _iter_pythons(self) -> Iterator:
for path, entry, version_tuple in self._iter_versions():
if path.as_posix() in self._pythons:
yield self._pythons[path.as_posix()]
if str(path) in self._pythons:
yield self._pythons[str(path)]
elif version_tuple not in self.versions:
for python in entry.find_all_python_versions():
yield python
Expand All @@ -180,7 +180,7 @@ def pythons(self) -> dict:

self.pythons_ref = defaultdict(PathEntry)
for python in self._iter_pythons():
python_path = python.path.as_posix()
python_path = str(python.path)
self.pythons_ref[python_path] = python
return self.pythons_ref

Expand Down Expand Up @@ -282,13 +282,11 @@ def version_sort(path_entry):
return path_entry.as_python.version_sort

unnested = [sub_finder(self.roots[path]) for path in self.roots]
print(f"unnested: {unnested}")
unnested = [
p
for p in unnested
if p is not None and p.is_python and p.as_python is not None
]
print(unnested)
paths = sorted(list(unnested), key=version_sort, reverse=True)
return next(iter(p for p in paths if p is not None), None)

Expand Down Expand Up @@ -328,10 +326,10 @@ def __getattribute__(self, key):
if self.executable:
executable = self.executable
elif self.comes_from:
executable = self.comes_from.path.as_posix()
executable = self.comes_from.path
if executable is not None:
if not isinstance(executable, str):
executable = executable.as_posix()
executable = executable
instance_dict = self.parse_executable(executable)
for k in instance_dict.keys():
try:
Expand Down Expand Up @@ -491,7 +489,7 @@ def get_architecture(self) -> str:
return self.architecture
arch = None
if self.comes_from is not None:
arch, _ = platform.architecture(self.comes_from.path.as_posix())
arch, _ = platform.architecture(str(self.comes_from.path))
elif self.executable is not None:
arch, _ = platform.architecture(self.executable)
if arch is None:
Expand Down Expand Up @@ -528,7 +526,7 @@ def from_path(
elif hasattr(path, "path") and isinstance(path.path, Path):
path_obj = path.path
path_name = getattr(path, "name", path_obj.name)
path_str = path.path.absolute().as_posix()
path_str = str(path.path.absolute())
elif isinstance(path, PythonFinder): # If path is a PythonFinder object
path_name = None
path_str = path.path
Expand Down Expand Up @@ -566,7 +564,7 @@ def parse_executable(cls, path) -> dict[str, str | int | Version | None]:
if path is None:
raise TypeError("Must pass a valid path to parse.")
if not isinstance(path, str):
path = path.as_posix()
path = str(path)
# if not looks_like_python(path):
# raise ValueError("Path %r does not look like a valid python path" % path)
try:
Expand Down Expand Up @@ -597,7 +595,7 @@ def from_windows_launcher(
exe_path = ensure_path(
getattr(launcher_entry.info.install_path, "executable_path", default_path)
)
company = getattr(launcher_entry, "company", guess_company(exe_path.as_posix()))
company = getattr(launcher_entry, "company", guess_company(exe_path))
creation_dict.update(
{
"architecture": getattr(
Expand Down
14 changes: 7 additions & 7 deletions src/pythonfinder/pythonfinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,11 @@ def find_all_python_versions(
filter(lambda v: v and v.as_python, versions), key=version_sort, reverse=True
)
path_map = {}
for path in path_list:
for p in path_list:
try:
resolved_path = path.path.resolve()
except OSError:
resolved_path = path.path.absolute()
if not path_map.get(resolved_path.as_posix()):
path_map[resolved_path.as_posix()] = path
return path_list
resolved_path = p.path.resolve(strict=True)
except (OSError, RuntimeError):
resolved_path = p.path.absolute()
if resolved_path not in path_map:
path_map[resolved_path] = p
return [path_map[p] for p in path_map]
4 changes: 2 additions & 2 deletions src/pythonfinder/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,10 @@ def ensure_path(path: Path | str) -> Path:
:return: A fully expanded Path object.
"""
if isinstance(path, Path):
return path.resolve()
return path.absolute()
# Expand environment variables and user tilde in the path
expanded_path = os.path.expandvars(os.path.expanduser(path))
return Path(expanded_path).resolve()
return Path(expanded_path).absolute()


def resolve_path(path: Path | str) -> Path:
Expand Down

0 comments on commit 6c7aff9

Please sign in to comment.