From 054cea976c254459d1403e2df1e62c1cabb4babe Mon Sep 17 00:00:00 2001 From: phernandez Date: Sun, 22 Dec 2024 09:22:02 -0600 Subject: [PATCH] remove unused fileio code --- src/basic_memory/api/routers/knowledge.py | 2 +- src/basic_memory/cli/main.py | 8 +- src/basic_memory/fileio.py | 215 -------------------- src/basic_memory/services/entity_service.py | 2 +- src/basic_memory/services/exceptions.py | 10 + tests/services/test_entity_service.py | 2 +- 6 files changed, 17 insertions(+), 222 deletions(-) delete mode 100644 src/basic_memory/fileio.py create mode 100644 src/basic_memory/services/exceptions.py diff --git a/src/basic_memory/api/routers/knowledge.py b/src/basic_memory/api/routers/knowledge.py index 4eef2d27..06019793 100644 --- a/src/basic_memory/api/routers/knowledge.py +++ b/src/basic_memory/api/routers/knowledge.py @@ -4,7 +4,6 @@ from fastapi import APIRouter, HTTPException from loguru import logger from basic_memory.deps import EntityServiceDep, RelationServiceDep, ObservationServiceDep -from basic_memory.fileio import EntityNotFoundError from basic_memory.schemas import ( CreateEntityRequest, CreateEntityResponse, @@ -26,6 +25,7 @@ from basic_memory.schemas import ( RelationResponse, DeleteEntityRequest, ) +from basic_memory.services.exceptions import EntityNotFoundError router = APIRouter(prefix="/knowledge", tags=["knowledge"]) diff --git a/src/basic_memory/cli/main.py b/src/basic_memory/cli/main.py index 9159bcac..d93d1338 100644 --- a/src/basic_memory/cli/main.py +++ b/src/basic_memory/cli/main.py @@ -1,9 +1,9 @@ """Main CLI entry point for basic-memory""" + import typer -from . import migrate app = typer.Typer() -app.add_typer(migrate.app, name="migrate") +# app.add_typer(migrate.app, name="migrate") -if __name__ == "__main__": - app() \ No newline at end of file +if __name__ == "__main__": # pragma: no cover + app() diff --git a/src/basic_memory/fileio.py b/src/basic_memory/fileio.py deleted file mode 100644 index b3d5f09e..00000000 --- a/src/basic_memory/fileio.py +++ /dev/null @@ -1,215 +0,0 @@ -""" -File I/O operations for basic-memory. -Handles reading and writing entities and observations to the filesystem. -""" -from pathlib import Path - -from loguru import logger - -from basic_memory.schemas import Entity, Relation - - -class FileOperationError(Exception): - """Raised when file operations fail""" - pass - - -class EntityNotFoundError(Exception): - """Raised when an entity cannot be found""" - pass - - -def get_entity_path(project_entities_path: Path, entity_id: str) -> Path: - assert entity_id is not None, "entity_id cannot be None" - """ - Get the filesystem path for an entity. - - Args: - project_entities_path: Base path to project's entities directory - entity_id: ID of entity (e.g., '.../project/basic_memory.md') - - Returns: - Path object for the entity file - """ - return Path(f"{project_entities_path}/{entity_id}.md") - - -async def write_entity_file(project_entities_path: Path, entity_id: str, entity: Entity) -> bool: - """ - Write entity to filesystem in markdown format. - - Args: - project_entities_path: Base path to project's entities directory - entity_id: ID of entity - entity: Entity to write - - Returns: - True if successful - - Raises: - FileOperationError: If file operations fail - """ - logger.debug(f"Writing entity file for {entity_id}") - - entity_path = get_entity_path(project_entities_path, entity_id) - - # Handle directory creation separately - try: - entity_path.parent.mkdir(parents=True, exist_ok=True) - except Exception as e: - raise FileOperationError(f"Failed to create entity directory: {str(e)}") from e - - # Format entity data as markdown - content = [ - f"# {entity.name}\n", - f"type: {entity.entity_type}\n", - "\n", # Observations section - "## Observations\n", - ] - - # Add observations - for obs in entity.observations: - obs_line = f"- {obs}" - content.append(f"{obs_line}\n") - - # Add relations section if we have relations - if hasattr(entity, 'relations') and entity.relations: - content.extend([ - "\n", # Blank line before relations - "## Relations\n" - ]) - # Use model_dump to get proper storage format - for rel in entity.relations: - rel_data = rel.model_dump() - relation_line = f"- [{rel_data['to_id']}] {rel_data['relation_type']}" - if rel_data.get('context'): - relation_line += f" | {rel_data['context']}" - content.append(f"{relation_line}\n") - - # Handle atomic write operation - temp_path = entity_path.with_suffix('.tmp') - try: - temp_path.write_text("".join(content)) - except Exception as e: - raise FileOperationError(f"Failed to write temporary entity file: {str(e)}") from e - - try: - temp_path.rename(entity_path) - except Exception as e: - raise FileOperationError(f"Failed to finalize entity file: {str(e)}") from e - - logger.debug(f"Wrote entity {entity_id} file: {entity_path}") - return True - - -async def read_entity_file(project_entities_path: Path, entity_id: str) -> Entity: - """ - Read entity data from filesystem. - - Args: - project_entities_path: Base path to project's entities directory - entity_id: ID of entity to read - - Returns: - Entity object - - Raises: - EntityNotFoundError: If entity file doesn't exist - FileOperationError: If file operations fail - """ - entity_path = get_entity_path(project_entities_path, entity_id) - if not entity_path.exists(): - raise EntityNotFoundError(f"Entity file not found: {entity_id}") - - try: - content = entity_path.read_text().split("\n") - except Exception as e: - raise FileOperationError(f"Failed to read entity file: {str(e)}") from e - - # Parse markdown content - # First line should be "# Name" - name = content[0].lstrip("# ").strip() - - # Parse metadata (type) - entity_type = "" - observations = [] - relations = [] - - # Parse content sections - in_observations = False - in_relations = False - - for line in content[1:]: # Skip the title line - line = line.strip() - if not line: - continue - - if line.startswith("type: "): - entity_type = line.replace("type: ", "").strip() - elif line == "## Observations": - in_observations = True - in_relations = False - elif line == "## Relations": - in_observations = False - in_relations = True - elif in_observations and line.startswith("- "): - # Parse observation line: content | context - line = line[2:] # Remove the "- " - parts = line.split(" | ", 1) - content = parts[0] - context = parts[1] if len(parts) > 1 else None - observations.append(content) - elif in_relations and line.startswith("- "): - # Parse relation line: - [target_id] relation_type | context - line = line[2:] # Remove the bullet point - if "] " not in line: - continue # Skip malformed lines - - # Split on the first "] " to separate ID from relation_type - id_part, rest = line.split("] ", 1) - target_id = id_part[1:] # Remove leading [ - - # Split rest on " | " if there's a context - parts = rest.split(" | ", 1) - relation_type = parts[0] - context = parts[1] if len(parts) > 1 else None - - relations.append(Relation( # pyright: ignore [reportCallIssue] - from_id=entity_id, # pyright: ignore [reportCallIssue] - to_id=target_id, # pyright: ignore [reportCallIssue] - relation_type=relation_type, # pyright: ignore [reportCallIssue] - context=context - )) - - return Entity( # pyright: ignore [reportCallIssue] - id=entity_id, - name=name, - entity_type=entity_type, # pyright: ignore [reportCallIssue] - observations=observations, - relations=relations - ) - - -async def delete_entity_file(project_entities_path: Path, entity_id: str) -> bool: - """ - Delete an entity's file from the filesystem. - - Args: - project_entities_path: Base path to project's entities directory - entity_id: ID of entity to delete - - Returns: - True if successful or file didn't exist - - Raises: - FileOperationError: If file deletion fails - """ - entity_path = get_entity_path(project_entities_path, entity_id) - - if entity_path.exists(): - try: - entity_path.unlink() - except Exception as e: - raise FileOperationError(f"Failed to delete entity file: {str(e)}") from e - - return True \ No newline at end of file diff --git a/src/basic_memory/services/entity_service.py b/src/basic_memory/services/entity_service.py index 6497b0f1..bba9b73f 100644 --- a/src/basic_memory/services/entity_service.py +++ b/src/basic_memory/services/entity_service.py @@ -4,10 +4,10 @@ from typing import Dict, Any, Sequence, List from loguru import logger -from basic_memory.fileio import EntityNotFoundError from basic_memory.models import Entity as EntityModel, Observation from basic_memory.repository.entity_repository import EntityRepository from basic_memory.schemas import Entity as EntitySchema +from basic_memory.services.exceptions import EntityNotFoundError from .service import BaseService diff --git a/src/basic_memory/services/exceptions.py b/src/basic_memory/services/exceptions.py new file mode 100644 index 00000000..8eaccb27 --- /dev/null +++ b/src/basic_memory/services/exceptions.py @@ -0,0 +1,10 @@ +class FileOperationError(Exception): + """Raised when file operations fail""" + + pass + + +class EntityNotFoundError(Exception): + """Raised when an entity cannot be found""" + + pass diff --git a/tests/services/test_entity_service.py b/tests/services/test_entity_service.py index 2b836c3a..5a33d129 100644 --- a/tests/services/test_entity_service.py +++ b/tests/services/test_entity_service.py @@ -4,11 +4,11 @@ import pytest import pytest_asyncio from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker -from basic_memory.fileio import EntityNotFoundError from basic_memory.models import Entity as EntityModel from basic_memory.repository.entity_repository import EntityRepository from basic_memory.schemas import Entity from basic_memory.services.entity_service import EntityService +from basic_memory.services.exceptions import EntityNotFoundError pytestmark = pytest.mark.asyncio