Skip to content

Commit 84a23d1

Browse files
committed
Refactoring to set correct system location for pip and npm
1 parent 730234c commit 84a23d1

File tree

2 files changed

+30
-14
lines changed

2 files changed

+30
-14
lines changed

dependency_resolver/detectors/npm_detector.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def get_dependencies(
4545
stdout, _, exit_code = executor.execute_command("npm list --json --depth=0", working_dir)
4646

4747
location = self._get_npm_location(executor, working_dir)
48-
scope = "system" if location == "system" else "project"
48+
scope = "system" if self._is_system_location(location) else "project"
4949
dependencies: dict[str, dict[str, str]] = {}
5050

5151
# Build result with desired field order: scope, location, hash, dependencies
@@ -76,8 +76,16 @@ def get_dependencies(
7676

7777
return result
7878

79+
def _is_system_location(self, location: str) -> bool:
80+
"""Check if a location represents a system-wide npm installation.
81+
82+
For npm, system scope means no local package.json or node_modules found.
83+
This is determined by the special 'system' marker returned by _get_npm_location.
84+
"""
85+
return location == "system"
86+
7987
def _get_npm_location(self, executor: EnvironmentExecutor, working_dir: Optional[str] = None) -> str:
80-
"""Get the location of the npm project."""
88+
"""Get the actual location path of the npm project or global installation."""
8189
search_dir = working_dir or "."
8290

8391
package_json_path = f"{search_dir}/package.json"
@@ -88,6 +96,12 @@ def _get_npm_location(self, executor: EnvironmentExecutor, working_dir: Optional
8896
if executor.path_exists(node_modules_path):
8997
return self._resolve_absolute_path(executor, search_dir)
9098

99+
# Fallback: get npm global location when no local project found
100+
stdout, _, exit_code = executor.execute_command("npm config get prefix")
101+
if exit_code == 0 and stdout.strip():
102+
return stdout.strip()
103+
104+
# Final fallback: return "system" marker for system scope identification
91105
return "system"
92106

93107
def _resolve_absolute_path(self, executor: EnvironmentExecutor, path: str) -> str:
@@ -140,4 +154,5 @@ def _generate_location_hash(self, executor: EnvironmentExecutor, location: str)
140154

141155
def has_system_scope(self, executor: EnvironmentExecutor, working_dir: Optional[str] = None) -> bool:
142156
"""NPM has system scope when no local package.json or node_modules exists."""
143-
return self._get_npm_location(executor, working_dir) == "system"
157+
location = self._get_npm_location(executor, working_dir)
158+
return self._is_system_location(location)

dependency_resolver/detectors/pip_detector.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def get_dependencies(
4343

4444
if exit_code != 0:
4545
location = self._get_pip_location(executor, working_dir)
46-
scope = "system" if location == "system" else "project"
46+
scope = "system" if self._is_system_location(location) else "project"
4747
result: dict[str, Any] = {"scope": scope}
4848
if scope == "project":
4949
result["location"] = location
@@ -62,7 +62,7 @@ def get_dependencies(
6262
}
6363

6464
location = self._get_pip_location(executor, working_dir)
65-
scope = "system" if location == "system" else "project"
65+
scope = "system" if self._is_system_location(location) else "project"
6666

6767
# Build result with desired field order: scope, location, hash, dependencies
6868
final_result: dict[str, Any] = {"scope": scope}
@@ -77,23 +77,23 @@ def get_dependencies(
7777

7878
return final_result
7979

80+
def _is_system_location(self, location: str) -> bool:
81+
"""Check if a location path represents a system-wide installation."""
82+
return location.startswith(("/usr/lib", "/usr/local/lib"))
83+
8084
def _get_pip_location(self, executor: EnvironmentExecutor, working_dir: Optional[str] = None) -> str:
81-
"""Get the location of the pip environment, properly classifying system vs project scope."""
85+
"""Get the actual location path of the pip environment."""
8286
pip_command = self._get_pip_command(executor, working_dir)
8387
stdout, _, exit_code = executor.execute_command(f"{pip_command} show pip", working_dir)
8488

8589
if exit_code == 0:
8690
for line in stdout.split("\n"):
8791
if line.startswith("Location:"):
8892
location = line.split(":", 1)[1].strip()
89-
90-
# Check if this is a system location
91-
if location.startswith(("/usr/lib", "/usr/local/lib")):
92-
return "system"
93-
9493
return location
9594

96-
return "system"
95+
# Fallback: return a default system location when pip location cannot be determined
96+
return "/usr/lib/python3/dist-packages"
9797

9898
def _get_pip_command(self, executor: EnvironmentExecutor, working_dir: Optional[str] = None) -> str:
9999
"""Get the appropriate pip command, activating venv if available."""
@@ -291,5 +291,6 @@ def _generate_location_hash(self, executor: EnvironmentExecutor, location: str)
291291
return ""
292292

293293
def has_system_scope(self, executor: EnvironmentExecutor, working_dir: Optional[str] = None) -> bool:
294-
"""PIP has system scope when no virtual environment is found."""
295-
return self._get_pip_location(executor, working_dir) == "system"
294+
"""PIP has system scope when pip is installed in a system location."""
295+
location = self._get_pip_location(executor, working_dir)
296+
return self._is_system_location(location)

0 commit comments

Comments
 (0)