From eb4a55a5e7102d295cdfc9b9b149ed0852273b23 Mon Sep 17 00:00:00 2001 From: phernandez Date: Fri, 21 Feb 2025 22:11:54 -0600 Subject: [PATCH] code cleanup --- src/basic_memory/cli/commands/status.py | 5 ++-- src/basic_memory/cli/commands/sync.py | 5 ++-- src/basic_memory/services/file_service.py | 2 +- src/basic_memory/sync/sync_service.py | 26 ++++++------------- src/basic_memory/sync/utils.py | 31 ----------------------- tests/cli/test_status.py | 9 ++----- tests/cli/test_sync.py | 5 ++-- tests/sync/test_watch_service.py | 5 ++-- 8 files changed, 21 insertions(+), 67 deletions(-) delete mode 100644 src/basic_memory/sync/utils.py diff --git a/src/basic_memory/cli/commands/status.py b/src/basic_memory/cli/commands/status.py index c56a3295..58fcd842 100644 --- a/src/basic_memory/cli/commands/status.py +++ b/src/basic_memory/cli/commands/status.py @@ -14,13 +14,12 @@ from basic_memory.cli.app import app from basic_memory.cli.commands.sync import get_sync_service from basic_memory.config import config from basic_memory.sync import SyncService -from basic_memory.sync.utils import SyncReport +from basic_memory.sync.sync_service import SyncReport # Create rich console console = Console() - def add_files_to_tree( tree: Tree, paths: Set[str], style: str, checksums: Dict[str, str] | None = None ): @@ -141,4 +140,4 @@ def status( asyncio.run(run_status(sync_service, verbose)) # pragma: no cover except Exception as e: logger.exception(f"Error checking status: {e}") - raise typer.Exit(code=1) # pragma: no cover + raise typer.Exit(code=1) # pragma: no cover \ No newline at end of file diff --git a/src/basic_memory/cli/commands/sync.py b/src/basic_memory/cli/commands/sync.py index e0cd141e..9e1ec8d9 100644 --- a/src/basic_memory/cli/commands/sync.py +++ b/src/basic_memory/cli/commands/sync.py @@ -26,7 +26,7 @@ from basic_memory.services import EntityService, FileService from basic_memory.services.link_resolver import LinkResolver from basic_memory.services.search_service import SearchService from basic_memory.sync import SyncService -from basic_memory.sync.utils import SyncReport +from basic_memory.sync.sync_service import SyncReport from basic_memory.sync.watch_service import WatchService console = Console() @@ -58,7 +58,6 @@ async def get_sync_service(): # pragma: no cover search_service = SearchService(search_repository, entity_repository, file_service) link_resolver = LinkResolver(entity_repository, search_service) - # Initialize services entity_service = EntityService( entity_parser, @@ -76,7 +75,7 @@ async def get_sync_service(): # pragma: no cover entity_repository=entity_repository, relation_repository=relation_repository, search_service=search_service, - file_service=file_service + file_service=file_service, ) return sync_service diff --git a/src/basic_memory/services/file_service.py b/src/basic_memory/services/file_service.py index 6d439075..1928b631 100644 --- a/src/basic_memory/services/file_service.py +++ b/src/basic_memory/services/file_service.py @@ -196,7 +196,7 @@ class FileService: return await file_utils.compute_checksum(full_path.read_text()) - async def file_stats(self, path: Union[Path, str]) -> stat_result: + def file_stats(self, path: Union[Path, str]) -> stat_result: """ Return file stats for a given path. :param path: diff --git a/src/basic_memory/sync/sync_service.py b/src/basic_memory/sync/sync_service.py index 8781d249..c20d3a98 100644 --- a/src/basic_memory/sync/sync_service.py +++ b/src/basic_memory/sync/sync_service.py @@ -59,14 +59,6 @@ class ScanResult: errors: Dict[str, str] = field(default_factory=dict) -@dataclass -class FileState: - """State of a file including file path, permalink and checksum info.""" - - file_path: str - permalink: str - checksum: str - class SyncService: """Syncs documents and knowledge files with database.""" @@ -87,7 +79,7 @@ class SyncService: self.search_service = search_service self.file_service = file_service - async def get_db_file_state(self) -> Dict[str, FileState]: + async def get_db_file_state(self) -> Dict[str, str]: """Get file_path and checksums from database. Args: db_records: database records @@ -97,9 +89,7 @@ class SyncService: """ db_records = await self.entity_repository.find_all() return { - r.file_path: FileState( - file_path=r.file_path, permalink=r.permalink, checksum=r.checksum or "" - ) + r.file_path: r.checksum or "" for r in db_records } @@ -108,7 +98,7 @@ class SyncService: with logfire.span("sync", directory=directory): # initial paths from db to sync - # path -> FileState + # path -> checksum db_paths = await self.get_db_file_state() # Track potentially moved files by checksum @@ -124,24 +114,24 @@ class SyncService: report.checksums[file_path] = checksum # Now detect moves and deletions - for db_path, db_state in db_paths.items(): + for db_path, db_checksum in db_paths.items(): report.checksums[file_path] = checksum local_checksum_for_db_path = scan_result.files.get(db_path) # file not modified - if db_state.checksum == local_checksum_for_db_path: + if db_checksum == local_checksum_for_db_path: pass # if checksums don't match for the same path, its modified - if local_checksum_for_db_path and db_state.checksum != local_checksum_for_db_path: + if local_checksum_for_db_path and db_checksum != local_checksum_for_db_path: report.modified.add(db_path) # check if it's moved or deleted if not local_checksum_for_db_path: # if we find the checksum in another file, it's a move - if db_state.checksum in scan_result.checksums: - new_path = scan_result.checksums[db_state.checksum] + if db_checksum in scan_result.checksums: + new_path = scan_result.checksums[db_checksum] report.moves[db_path] = new_path # Remove from new files since it's a move report.new.remove(new_path) diff --git a/src/basic_memory/sync/utils.py b/src/basic_memory/sync/utils.py deleted file mode 100644 index e2e0a0d6..00000000 --- a/src/basic_memory/sync/utils.py +++ /dev/null @@ -1,31 +0,0 @@ -"""Types and utilities for file sync.""" - -from dataclasses import dataclass, field -from typing import Set, Dict - - -@dataclass -class SyncReport: - """Report of file changes found compared to database state. - - Attributes: - total: Total number of files in directory being synced - new: Files that exist on disk but not in database - modified: Files that exist in both but have different checksums - deleted: Files that exist in database but not on disk - moves: Files that have been moved from one location to another - checksums: Current checksums for files on disk - """ - - total: int = 0 - # We keep paths as strings in sets/dicts for easier serialization - new: Set[str] = field(default_factory=set) - modified: Set[str] = field(default_factory=set) - deleted: Set[str] = field(default_factory=set) - moves: Dict[str, str] = field(default_factory=dict) # old_path -> new_path - checksums: Dict[str, str] = field(default_factory=dict) # path -> checksum - - @property - def total_changes(self) -> int: - """Total number of changes.""" - return len(self.new) + len(self.modified) + len(self.deleted) + len(self.moves) diff --git a/tests/cli/test_status.py b/tests/cli/test_status.py index 4951f729..8cbb9271 100644 --- a/tests/cli/test_status.py +++ b/tests/cli/test_status.py @@ -1,7 +1,6 @@ """Tests for CLI status command.""" import pytest -import pytest_asyncio from typer.testing import CliRunner from basic_memory.cli.app import app @@ -9,18 +8,14 @@ from basic_memory.cli.commands.status import ( add_files_to_tree, build_directory_summary, group_changes_by_directory, - run_status, display_changes, ) -from basic_memory.sync.utils import SyncReport -from basic_memory.repository import EntityRepository +from basic_memory.sync.sync_service import SyncReport # Set up CLI runner runner = CliRunner() - - @pytest.mark.asyncio async def test_status_command_error(tmp_path, monkeypatch): """Test CLI status command error handling.""" @@ -122,4 +117,4 @@ def test_add_files_to_tree(): checksums = {"dir1/file1.md": "abcd1234", "dir1/file2.md": "efgh5678"} tree = Tree("Test with checksums") - add_files_to_tree(tree, paths, "green", checksums) + add_files_to_tree(tree, paths, "green", checksums) \ No newline at end of file diff --git a/tests/cli/test_sync.py b/tests/cli/test_sync.py index fbd6d959..63d26864 100644 --- a/tests/cli/test_sync.py +++ b/tests/cli/test_sync.py @@ -1,6 +1,7 @@ """Tests for CLI sync command.""" import asyncio + import pytest from typer.testing import CliRunner @@ -13,7 +14,7 @@ from basic_memory.cli.commands.sync import ( ValidationIssue, ) from basic_memory.config import config -from basic_memory.sync.utils import SyncReport +from basic_memory.sync.sync_service import SyncReport # Set up CLI runner runner = CliRunner() @@ -106,4 +107,4 @@ async def test_run_sync_watch_mode(sync_service, test_config): def test_sync_command(): """Test the sync command.""" result = runner.invoke(app, ["sync", "--verbose"]) - assert result.exit_code == 0 + assert result.exit_code == 0 \ No newline at end of file diff --git a/tests/sync/test_watch_service.py b/tests/sync/test_watch_service.py index 75dc0ad0..d666f664 100644 --- a/tests/sync/test_watch_service.py +++ b/tests/sync/test_watch_service.py @@ -1,13 +1,14 @@ """Tests for watch service.""" import json + import pytest from watchfiles import Change from basic_memory.services.file_service import FileService +from basic_memory.sync.sync_service import SyncReport from basic_memory.sync.sync_service import SyncService from basic_memory.sync.watch_service import WatchService, WatchServiceState -from basic_memory.sync.utils import SyncReport @pytest.fixture @@ -118,4 +119,4 @@ async def test_handle_changes(watch_service, mock_sync_service): assert "new" in actions assert "modified" in actions assert "moved" in actions - assert "deleted" in actions + assert "deleted" in actions \ No newline at end of file