Skip to content

Commit bd8794c

Browse files
committed
refactor: move get_lockfile_installed_paths into LockFile classmethod
1 parent 48d87c0 commit bd8794c

File tree

5 files changed

+38
-36
lines changed

5 files changed

+38
-36
lines changed

src/apm_cli/cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
try:
4242
from apm_cli.deps.apm_resolver import APMDependencyResolver
4343
from apm_cli.deps.github_downloader import GitHubPackageDownloader
44-
from apm_cli.deps.lockfile import get_lockfile_installed_paths
44+
from apm_cli.deps.lockfile import LockFile
4545
from apm_cli.models.apm_package import APMPackage, DependencyReference
4646
from apm_cli.integration import PromptIntegrator, AgentIntegrator
4747

@@ -169,7 +169,7 @@ def _check_orphaned_packages():
169169
expected_installed.add(str(install_path))
170170

171171
# Also include transitive dependencies from apm.lock
172-
lockfile_paths = get_lockfile_installed_paths(Path.cwd())
172+
lockfile_paths = LockFile.installed_paths_for_project(Path.cwd())
173173
expected_installed.update(lockfile_paths)
174174
except Exception:
175175
return [] # If can't parse apm.yml, assume no orphans
@@ -798,7 +798,7 @@ def prune(ctx, dry_run):
798798
expected_installed.add(f"{repo_parts[0]}/{repo_parts[1]}")
799799

800800
# Also include transitive dependencies from apm.lock
801-
lockfile_paths = get_lockfile_installed_paths(Path.cwd())
801+
lockfile_paths = LockFile.installed_paths_for_project(Path.cwd())
802802
expected_installed.update(lockfile_paths)
803803
except Exception as e:
804804
_rich_error(f"Failed to parse apm.yml: {e}")

src/apm_cli/deps/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from .verifier import verify_dependencies, install_missing_dependencies, load_apm_config
1010
from .github_downloader import GitHubPackageDownloader
1111
from .package_validator import PackageValidator
12-
from .lockfile import LockFile, LockedDependency, get_lockfile_path, get_lockfile_installed_paths
12+
from .lockfile import LockFile, LockedDependency, get_lockfile_path
1313

1414
__all__ = [
1515
'sync_workflow_dependencies',
@@ -29,5 +29,5 @@
2929
'LockFile',
3030
'LockedDependency',
3131
'get_lockfile_path',
32-
'get_lockfile_installed_paths',
32+
3333
]

src/apm_cli/deps/lockfile.py

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -238,31 +238,34 @@ def save(self, path: Path) -> None:
238238
"""Save lock file to disk (alias for write)."""
239239
self.write(path)
240240

241+
@classmethod
242+
def installed_paths_for_project(cls, project_root: Path) -> List[str]:
243+
"""Load apm.lock from project_root and return installed paths.
244+
245+
Returns an empty list if the lockfile is missing, corrupt, or
246+
unreadable.
247+
248+
Args:
249+
project_root: Path to project root containing apm.lock.
250+
251+
Returns:
252+
List[str]: Relative installed paths (e.g., ['owner/repo']),
253+
ordered by depth then repo_url (no duplicates).
254+
"""
255+
try:
256+
lockfile = cls.read(project_root / "apm.lock")
257+
if not lockfile:
258+
return []
259+
return lockfile.get_installed_paths(project_root / "apm_modules")
260+
except (FileNotFoundError, yaml.YAMLError, ValueError, KeyError):
261+
return []
262+
241263

242264
def get_lockfile_path(project_root: Path) -> Path:
243265
"""Get the path to the lock file for a project."""
244266
return project_root / "apm.lock"
245267

246268

247269
def get_lockfile_installed_paths(project_root: Path) -> List[str]:
248-
"""Get installed paths for all dependencies recorded in apm.lock.
249-
250-
Convenience wrapper that loads the lockfile and delegates to
251-
LockFile.get_installed_paths(). Returns an empty list if the
252-
lockfile is missing, corrupt, or unreadable.
253-
254-
Args:
255-
project_root: Path to project root containing apm.lock.
256-
257-
Returns:
258-
List[str]: Relative installed paths (e.g., ['owner/repo']),
259-
ordered by depth then repo_url (no duplicates).
260-
"""
261-
try:
262-
lockfile_path = get_lockfile_path(project_root)
263-
lockfile = LockFile.read(lockfile_path)
264-
if not lockfile:
265-
return []
266-
return lockfile.get_installed_paths(project_root / "apm_modules")
267-
except (FileNotFoundError, yaml.YAMLError, ValueError, KeyError):
268-
return []
270+
"""Deprecated: use LockFile.installed_paths_for_project() instead."""
271+
return LockFile.installed_paths_for_project(project_root)

src/apm_cli/primitives/discovery.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .models import PrimitiveCollection
99
from .parser import parse_primitive_file, parse_skill_file
1010
from ..models.apm_package import APMPackage
11-
from ..deps.lockfile import get_lockfile_installed_paths
11+
from ..deps.lockfile import LockFile
1212

1313

1414
# Common primitive patterns for local discovery (with recursive search)
@@ -252,7 +252,7 @@ def get_dependency_declaration_order(base_dir: str) -> List[str]:
252252

253253
# Include transitive dependencies from apm.lock
254254
# Direct deps from apm.yml have priority; transitive deps are appended
255-
lockfile_paths = get_lockfile_installed_paths(Path(base_dir))
255+
lockfile_paths = LockFile.installed_paths_for_project(Path(base_dir))
256256
direct_set = set(dependency_names)
257257
for path in lockfile_paths:
258258
if path not in direct_set:

tests/unit/test_transitive_deps.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Unit tests for transitive dependency handling.
22
33
Tests that:
4-
- get_lockfile_installed_paths() correctly returns paths for all locked deps
4+
- LockFile.installed_paths_for_project() correctly returns paths for all locked deps
55
- _check_orphaned_packages() does not flag transitive deps as orphaned
66
- get_dependency_declaration_order() includes transitive deps from lockfile
77
"""
@@ -13,7 +13,6 @@
1313
from apm_cli.deps.lockfile import (
1414
LockFile,
1515
LockedDependency,
16-
get_lockfile_installed_paths,
1716
)
1817
from apm_cli.primitives.discovery import get_dependency_declaration_order
1918

@@ -23,15 +22,15 @@ class TestGetLockfileInstalledPaths:
2322

2423
def test_returns_empty_when_no_lockfile(self, tmp_path):
2524
"""Returns empty list when no apm.lock exists."""
26-
assert get_lockfile_installed_paths(tmp_path) == []
25+
assert LockFile.installed_paths_for_project(tmp_path) == []
2726

2827
def test_returns_paths_for_regular_packages(self, tmp_path):
2928
lockfile = LockFile()
3029
lockfile.add_dependency(LockedDependency(repo_url="owner/repo-a", depth=1))
3130
lockfile.add_dependency(LockedDependency(repo_url="owner/repo-b", depth=2))
3231
lockfile.write(tmp_path / "apm.lock")
3332

34-
paths = get_lockfile_installed_paths(tmp_path)
33+
paths = LockFile.installed_paths_for_project(tmp_path)
3534
assert "owner/repo-a" in paths
3635
assert "owner/repo-b" in paths
3736

@@ -40,7 +39,7 @@ def test_no_duplicates(self, tmp_path):
4039
lockfile.add_dependency(LockedDependency(repo_url="owner/repo", depth=1))
4140
lockfile.write(tmp_path / "apm.lock")
4241

43-
paths = get_lockfile_installed_paths(tmp_path)
42+
paths = LockFile.installed_paths_for_project(tmp_path)
4443
assert paths.count("owner/repo") == 1
4544

4645
def test_ordered_by_depth_then_repo(self, tmp_path):
@@ -50,7 +49,7 @@ def test_ordered_by_depth_then_repo(self, tmp_path):
5049
lockfile.add_dependency(LockedDependency(repo_url="m/mid", depth=2))
5150
lockfile.write(tmp_path / "apm.lock")
5251

53-
paths = get_lockfile_installed_paths(tmp_path)
52+
paths = LockFile.installed_paths_for_project(tmp_path)
5453
assert paths == ["a/direct", "m/mid", "z/deep"]
5554

5655
def test_virtual_file_package_path(self, tmp_path):
@@ -64,14 +63,14 @@ def test_virtual_file_package_path(self, tmp_path):
6463
))
6564
lockfile.write(tmp_path / "apm.lock")
6665

67-
paths = get_lockfile_installed_paths(tmp_path)
66+
paths = LockFile.installed_paths_for_project(tmp_path)
6867
# Virtual file: owner/<repo>-<stem> → owner/repo-code-review
6968
assert "owner/repo-code-review" in paths
7069

7170
def test_corrupt_lockfile(self, tmp_path):
7271
"""Corrupt lockfile should return empty list."""
7372
(tmp_path / "apm.lock").write_text("not: valid: yaml: [")
74-
assert get_lockfile_installed_paths(tmp_path) == []
73+
assert LockFile.installed_paths_for_project(tmp_path) == []
7574

7675

7776
class TestTransitiveDependencyDiscovery:

0 commit comments

Comments
 (0)