Skip to content

Commit

Permalink
Handle conda paths on Windows and some refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
kemzeb committed May 16, 2024
1 parent ac3ff3c commit 442853e
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 18 deletions.
6 changes: 3 additions & 3 deletions src/pipdeptree/_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import locale
from json import JSONDecodeError
from pathlib import Path
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any

from pip._internal.models.direct_url import (
DirectUrl, # noqa: PLC2701
Expand Down Expand Up @@ -34,7 +34,7 @@ def __init__(self, dist: Distribution) -> None:
self._version = Version(dist.version)

@property
def raw_name(self) -> str:
def raw_name(self) -> str | Any:
return self._raw_name

@property
Expand Down Expand Up @@ -71,6 +71,6 @@ def editable_project_location(self) -> str | None:
result = None
egg_link_path = egg_link_path_from_sys_path(self.raw_name)
if egg_link_path:
with Path(egg_link_path).open("r", encoding=locale.getpreferredencoding(False)) as f:
with Path(egg_link_path).open("r", encoding=locale.getpreferredencoding(False)) as f: # noqa: FBT003
result = f.readline().rstrip()
return result
2 changes: 1 addition & 1 deletion src/pipdeptree/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def build_parser() -> ArgumentParser:
"--python",
default=sys.executable,
help=(
'Python interpreter to inspect. With "auto", it attempts to detect your envrionment and falls back to using'
'Python interpreter to inspect. With "auto", it attempts to detect your environment and falls back to using'
" the system interpreter if it fails."
),
)
Expand Down
29 changes: 16 additions & 13 deletions src/pipdeptree/_detect_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ def detect_active_interpreter() -> str:
If it fails to find any, it will fallback to using the system interpreter.
"""
detection_funcs: tuple[Callable[[], Path | None]] = (
detection_funcs: list[Callable[[], Path | None]] = [
detect_venv_or_virtualenv_interpreter,
detect_conda_env_interpreter,
detect_poetry_env_interpreter,
)

]
for detect in detection_funcs:
path = detect()
if not path:
Expand All @@ -44,6 +43,10 @@ def detect_venv_or_virtualenv_interpreter() -> Path | None:
return path / file_name if file_name else None


def determine_bin_dir() -> str:
return "Scripts" if os.name == "nt" else "bin"


def detect_conda_env_interpreter() -> Path | None:
# Env var mentioned in https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#saving-environment-variables.
env_var = os.environ.get("CONDA_PREFIX")
Expand All @@ -52,17 +55,21 @@ def detect_conda_env_interpreter() -> Path | None:

path = Path(env_var)

# See https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/environments.html for the directory layout.
path /= determine_bin_dir()
# On POSIX systems, conda adds the python executable to the /bin directory. On Windows, it resides in the parent
# directory of /bin (i.e. the root directory).
# See https://docs.anaconda.com/free/working-with-conda/configurations/python-path/#examples.
if os.name == "posix": # pragma: posix cover
path /= "bin"

file_name = determine_interpreter_file_name()

return path / file_name if file_name else None


def detect_poetry_env_interpreter() -> Path | None:
# See https://python-poetry.org/docs/managing-environments/#displaying-the-environment-information. poetry doesn't
# expose an environment variable like other implementations, so we instead use its CLI to snatch the active
# interpreter.
# poetry doesn't expose an environment variable like other implementations, so we instead use its CLI to snatch the
# active interpreter.
# See https://python-poetry.org/docs/managing-environments/#displaying-the-environment-information.
try:
result = subprocess.run(
("poetry", "env", "info", "--executable"), # noqa: S603
Expand All @@ -77,11 +84,7 @@ def detect_poetry_env_interpreter() -> Path | None:
return Path(result.stdout.strip())


def determine_bin_dir() -> Path:
return "Scripts" if os.name == "nt" else "bin"


def determine_interpreter_file_name() -> Path | None:
def determine_interpreter_file_name() -> str | None:
impl_name_to_file_name_dict = {"CPython": "python", "PyPy": "pypy"}
name = impl_name_to_file_name_dict.get(platform.python_implementation())
if not name:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_detect_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def test_detect_active_interpreter_using_env_vars(tmp_path: Path, mocker: MockFi


def test_detect_active_interpreter_poetry(tmp_path: Path, mocker: MockFixture) -> None:
faked_result = CompletedProcess(None, 0, stdout=str(tmp_path))
faked_result = CompletedProcess("", 0, stdout=str(tmp_path))
mocker.patch("pipdeptree._detect_env.subprocess.run", return_value=faked_result)
mocker.patch("pipdeptree._detect_env.os.environ", {})

Expand Down

0 comments on commit 442853e

Please sign in to comment.