basic-memory 0.12.1__tar.gz → 0.12.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of basic-memory might be problematic. Click here for more details.
- {basic_memory-0.12.1 → basic_memory-0.12.2}/CHANGELOG.md +11 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/PKG-INFO +1 -1
- {basic_memory-0.12.1 → basic_memory-0.12.2}/installer/installer.py +1 -1
- {basic_memory-0.12.1 → basic_memory-0.12.2}/pyproject.toml +1 -1
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/__init__.py +1 -1
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/import_memory_json.py +1 -1
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/markdown/entity_parser.py +1 -1
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/sync/sync_service.py +3 -5
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/api/test_resource_router.py +3 -3
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/test_import_chatgpt.py +8 -7
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/test_import_claude_conversations.py +5 -4
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/test_import_claude_projects.py +5 -4
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/test_import_memory_json.py +4 -3
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/markdown/test_markdown_processor.py +5 -5
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/test_tool_canvas.py +4 -4
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/sync/test_tmp_files.py +2 -2
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/sync/test_watch_service.py +1 -1
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/utils/test_file_utils.py +10 -10
- {basic_memory-0.12.1 → basic_memory-0.12.2}/uv.lock +1 -1
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.github/dependabot.yml +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.github/workflows/claude-code-actions.yml +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.github/workflows/pr-title.yml +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.github/workflows/release.yml +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.github/workflows/test.yml +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.gitignore +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/.python-version +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/CITATION.cff +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/CLA.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/CLAUDE.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/CODE_OF_CONDUCT.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/CONTRIBUTING.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/Dockerfile +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/LICENSE +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/Makefile +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/README.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/SECURITY.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/basic-memory.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/AI Assistant Guide.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/CLI Reference.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/Canvas.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/Getting Started with Basic Memory.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/Knowledge Format.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/Obsidian Integration.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/Technical Information.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/User Guide.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/Welcome to Basic memory.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/attachments/Canvas.png +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/attachments/Claude-Obsidian-Demo.mp4 +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/attachments/Prompt.png +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/attachments/disk-ai-logo-400x400.png +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/attachments/disk-ai-logo.png +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/attachments/prompt 1.png +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/attachments/prompt2.png +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/attachments/prompt3.png +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/attachments/prompt4.png +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/docs/publish.js +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/examples/Coffee Notes/Brewing Equipment.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/examples/Coffee Notes/Coffee Bean Origins.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/examples/Coffee Notes/Coffee Brewing Methods.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/examples/Coffee Notes/Coffee Flavor Map.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/examples/Coffee Notes/Coffee Knowledge Base.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/examples/Coffee Notes/Flavor Extraction.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/examples/Coffee Notes/Perfect Pour Over Coffee Method.canvas +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/examples/Coffee Notes/Tasting Notes.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/installer/Basic.icns +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/installer/README.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/installer/icon.svg +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/installer/make_icons.sh +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/installer/setup.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/llms-install.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/memory.json +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/scripts/install.sh +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/smithery.yaml +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/alembic/alembic.ini +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/alembic/env.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/alembic/migrations.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/alembic/script.py.mako +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/api/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/api/app.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/api/routers/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/api/routers/knowledge_router.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/api/routers/memory_router.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/api/routers/project_info_router.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/api/routers/resource_router.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/api/routers/search_router.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/app.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/db.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/import_chatgpt.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/import_claude_conversations.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/import_claude_projects.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/mcp.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/project.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/status.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/sync.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/tool.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/main.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/config.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/db.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/deps.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/file_utils.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/markdown/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/markdown/markdown_processor.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/markdown/plugins.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/markdown/schemas.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/markdown/utils.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/async_client.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/main.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/prompts/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/prompts/search.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/prompts/utils.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/server.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/build_context.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/canvas.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/delete_note.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/project_info.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/read_content.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/read_note.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/search.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/utils.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/mcp/tools/write_note.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/models/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/models/base.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/models/knowledge.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/models/search.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/repository/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/repository/entity_repository.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/repository/observation_repository.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/repository/project_info_repository.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/repository/relation_repository.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/repository/repository.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/repository/search_repository.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/schemas/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/schemas/base.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/schemas/delete.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/schemas/memory.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/schemas/project_info.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/schemas/request.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/schemas/response.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/schemas/search.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/services/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/services/context_service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/services/entity_service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/services/exceptions.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/services/file_service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/services/initialization.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/services/link_resolver.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/services/search_service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/services/service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/sync/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/sync/watch_service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/utils.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/static/ai_assistant_guide.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/static/json_canvas_spec_1_0.md +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/Non-MarkdownFileSupport.pdf +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/Screenshot.png +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/api/conftest.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/api/test_knowledge_router.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/api/test_memory_router.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/api/test_project_info_router.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/api/test_search_router.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/conftest.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/test_cli_tools.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/test_project_commands.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/test_project_info.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/test_status.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/test_sync.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/cli/test_version.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/conftest.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/edit_file_test.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/markdown/__init__.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/markdown/test_entity_parser.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/markdown/test_markdown_plugins.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/markdown/test_observation_edge_cases.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/markdown/test_parser_edge_cases.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/markdown/test_relation_edge_cases.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/markdown/test_task_detection.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/conftest.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/test_prompts.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/test_resources.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/test_tool_memory.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/test_tool_project_info.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/test_tool_read_note.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/test_tool_resource.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/test_tool_search.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/test_tool_utils.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/mcp/test_tool_write_note.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/repository/test_entity_repository.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/repository/test_observation_repository.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/repository/test_relation_repository.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/repository/test_repository.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/schemas/test_memory_url.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/schemas/test_schemas.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/schemas/test_search.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/services/test_context_service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/services/test_entity_service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/services/test_file_service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/services/test_initialization.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/services/test_link_resolver.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/services/test_search_service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/sync/test_sync_service.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/sync/test_sync_wikilink_issue.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/sync/test_watch_service_edge_cases.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/test_basic_memory.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/test_config.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/utils/test_parse_tags.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/utils/test_permalink_formatting.py +0 -0
- {basic_memory-0.12.1 → basic_memory-0.12.2}/tests/utils/test_utf8_handling.py +0 -0
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v0.12.2 (2025-04-08)
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
- Utf8 for all file reads/write/open instead of default platform encoding
|
|
9
|
+
([#91](https://github.com/basicmachines-co/basic-memory/pull/91),
|
|
10
|
+
[`2934176`](https://github.com/basicmachines-co/basic-memory/commit/29341763318408ea8f1e954a41046c4185f836c6))
|
|
11
|
+
|
|
12
|
+
Signed-off-by: phernandez <paul@basicmachines.co>
|
|
13
|
+
|
|
14
|
+
|
|
4
15
|
## v0.12.1 (2025-04-07)
|
|
5
16
|
|
|
6
17
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: basic-memory
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.2
|
|
4
4
|
Summary: Local-first knowledge management combining Zettelkasten with knowledge graphs
|
|
5
5
|
Project-URL: Homepage, https://github.com/basicmachines-co/basic-memory
|
|
6
6
|
Project-URL: Repository, https://github.com/basicmachines-co/basic-memory
|
{basic_memory-0.12.1 → basic_memory-0.12.2}/src/basic_memory/cli/commands/import_memory_json.py
RENAMED
|
@@ -38,7 +38,7 @@ async def process_memory_json(
|
|
|
38
38
|
read_task = progress.add_task("Reading memory.json...", total=None)
|
|
39
39
|
|
|
40
40
|
# First pass - collect entities and relations
|
|
41
|
-
with open(json_path) as f:
|
|
41
|
+
with open(json_path, encoding="utf-8") as f:
|
|
42
42
|
lines = f.readlines()
|
|
43
43
|
progress.update(read_task, total=len(lines))
|
|
44
44
|
|
|
@@ -104,7 +104,7 @@ class EntityParser:
|
|
|
104
104
|
absolute_path = self.base_path / path
|
|
105
105
|
|
|
106
106
|
# Parse frontmatter and content using python-frontmatter
|
|
107
|
-
file_content = absolute_path.read_text()
|
|
107
|
+
file_content = absolute_path.read_text(encoding="utf-8")
|
|
108
108
|
return await self.parse_file_content(absolute_path, file_content)
|
|
109
109
|
|
|
110
110
|
async def parse_file_content(self, absolute_path, file_content):
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"""Service for syncing files between filesystem and database."""
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
|
|
5
|
-
from dataclasses import dataclass
|
|
6
|
-
from dataclasses import field
|
|
4
|
+
import time
|
|
5
|
+
from dataclasses import dataclass, field
|
|
7
6
|
from datetime import datetime
|
|
8
7
|
from pathlib import Path
|
|
9
8
|
from typing import Dict, Optional, Set, Tuple
|
|
@@ -18,7 +17,6 @@ from basic_memory.models import Entity
|
|
|
18
17
|
from basic_memory.repository import EntityRepository, RelationRepository
|
|
19
18
|
from basic_memory.services import EntityService, FileService
|
|
20
19
|
from basic_memory.services.search_service import SearchService
|
|
21
|
-
import time
|
|
22
20
|
|
|
23
21
|
|
|
24
22
|
@dataclass
|
|
@@ -237,7 +235,7 @@ class SyncService:
|
|
|
237
235
|
logger.debug(f"Parsing markdown file, path: {path}, new: {new}")
|
|
238
236
|
|
|
239
237
|
file_path = self.entity_parser.base_path / path
|
|
240
|
-
file_content = file_path.read_text()
|
|
238
|
+
file_content = file_path.read_text(encoding="utf-8")
|
|
241
239
|
file_contains_frontmatter = has_frontmatter(file_content)
|
|
242
240
|
|
|
243
241
|
# entity markdown will always contain front matter, so it can be used up create/update the entity
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
from datetime import datetime, timezone
|
|
5
|
+
from pathlib import Path
|
|
5
6
|
|
|
6
7
|
import pytest
|
|
7
|
-
from pathlib import Path
|
|
8
8
|
|
|
9
9
|
from basic_memory.schemas import EntityResponse
|
|
10
10
|
|
|
@@ -346,7 +346,7 @@ async def test_put_resource_new_file(client, test_config, entity_repository, sea
|
|
|
346
346
|
assert full_path.exists()
|
|
347
347
|
|
|
348
348
|
# Verify file content
|
|
349
|
-
file_content = full_path.read_text()
|
|
349
|
+
file_content = full_path.read_text(encoding="utf-8")
|
|
350
350
|
assert json.loads(file_content) == canvas_data
|
|
351
351
|
|
|
352
352
|
# Verify entity was created in DB
|
|
@@ -420,7 +420,7 @@ async def test_put_resource_update_existing(client, test_config, entity_reposito
|
|
|
420
420
|
assert response.status_code == 200
|
|
421
421
|
|
|
422
422
|
# Verify file was updated
|
|
423
|
-
updated_content = full_path.read_text()
|
|
423
|
+
updated_content = full_path.read_text(encoding="utf-8")
|
|
424
424
|
assert json.loads(updated_content) == updated_data
|
|
425
425
|
|
|
426
426
|
# Verify entity was updated
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"""Tests for import_chatgpt command."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
|
|
4
5
|
import pytest
|
|
5
6
|
from typer.testing import CliRunner
|
|
6
7
|
|
|
7
|
-
from basic_memory.cli.app import
|
|
8
|
+
from basic_memory.cli.app import app, import_app
|
|
8
9
|
from basic_memory.cli.commands import import_chatgpt
|
|
9
10
|
from basic_memory.config import config
|
|
10
11
|
from basic_memory.markdown import EntityParser, MarkdownProcessor
|
|
@@ -144,7 +145,7 @@ def sample_conversation_with_hidden():
|
|
|
144
145
|
def sample_chatgpt_json(tmp_path, sample_conversation):
|
|
145
146
|
"""Create a sample ChatGPT JSON file."""
|
|
146
147
|
json_file = tmp_path / "conversations.json"
|
|
147
|
-
with open(json_file, "w") as f:
|
|
148
|
+
with open(json_file, "w", encoding="utf-8") as f:
|
|
148
149
|
json.dump([sample_conversation], f)
|
|
149
150
|
return json_file
|
|
150
151
|
|
|
@@ -167,7 +168,7 @@ async def test_process_chatgpt_json(tmp_path, sample_chatgpt_json):
|
|
|
167
168
|
assert conv_path.exists()
|
|
168
169
|
|
|
169
170
|
# Check content formatting
|
|
170
|
-
content = conv_path.read_text()
|
|
171
|
+
content = conv_path.read_text(encoding="utf-8")
|
|
171
172
|
assert "# Test Conversation" in content
|
|
172
173
|
assert "### User" in content
|
|
173
174
|
assert "Hello, this is a test message" in content
|
|
@@ -183,14 +184,14 @@ async def test_process_code_blocks(tmp_path, sample_conversation_with_code):
|
|
|
183
184
|
|
|
184
185
|
# Create test file
|
|
185
186
|
json_file = tmp_path / "code_test.json"
|
|
186
|
-
with open(json_file, "w") as f:
|
|
187
|
+
with open(json_file, "w", encoding="utf-8") as f:
|
|
187
188
|
json.dump([sample_conversation_with_code], f)
|
|
188
189
|
|
|
189
190
|
await import_chatgpt.process_chatgpt_json(json_file, tmp_path, processor)
|
|
190
191
|
|
|
191
192
|
# Check content
|
|
192
193
|
conv_path = tmp_path / "20250111-code-test.md"
|
|
193
|
-
content = conv_path.read_text()
|
|
194
|
+
content = conv_path.read_text(encoding="utf-8")
|
|
194
195
|
assert "```python" in content
|
|
195
196
|
assert "def hello():" in content
|
|
196
197
|
assert "```" in content
|
|
@@ -204,7 +205,7 @@ async def test_hidden_messages(tmp_path, sample_conversation_with_hidden):
|
|
|
204
205
|
|
|
205
206
|
# Create test file
|
|
206
207
|
json_file = tmp_path / "hidden_test.json"
|
|
207
|
-
with open(json_file, "w") as f:
|
|
208
|
+
with open(json_file, "w", encoding="utf-8") as f:
|
|
208
209
|
json.dump([sample_conversation_with_hidden], f)
|
|
209
210
|
|
|
210
211
|
results = await import_chatgpt.process_chatgpt_json(json_file, tmp_path, processor)
|
|
@@ -214,7 +215,7 @@ async def test_hidden_messages(tmp_path, sample_conversation_with_hidden):
|
|
|
214
215
|
|
|
215
216
|
# Check content
|
|
216
217
|
conv_path = tmp_path / "20250111-hidden-test.md"
|
|
217
|
-
content = conv_path.read_text()
|
|
218
|
+
content = conv_path.read_text(encoding="utf-8")
|
|
218
219
|
assert "Visible message" in content
|
|
219
220
|
assert "Hidden message" not in content
|
|
220
221
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Tests for import_claude command (chat conversations)."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
|
|
4
5
|
import pytest
|
|
5
6
|
from typer.testing import CliRunner
|
|
6
7
|
|
|
@@ -44,7 +45,7 @@ def sample_conversation():
|
|
|
44
45
|
def sample_conversations_json(tmp_path, sample_conversation):
|
|
45
46
|
"""Create a sample conversations.json file."""
|
|
46
47
|
json_file = tmp_path / "conversations.json"
|
|
47
|
-
with open(json_file, "w") as f:
|
|
48
|
+
with open(json_file, "w", encoding="utf-8") as f:
|
|
48
49
|
json.dump([sample_conversation], f)
|
|
49
50
|
return json_file
|
|
50
51
|
|
|
@@ -65,7 +66,7 @@ async def test_process_chat_json(tmp_path, sample_conversations_json):
|
|
|
65
66
|
# Check conversation file
|
|
66
67
|
conv_path = tmp_path / "20250105-test-conversation.md"
|
|
67
68
|
assert conv_path.exists()
|
|
68
|
-
content = conv_path.read_text()
|
|
69
|
+
content = conv_path.read_text(encoding="utf-8")
|
|
69
70
|
|
|
70
71
|
# Check content formatting
|
|
71
72
|
assert "### Human" in content
|
|
@@ -156,7 +157,7 @@ def test_import_conversation_with_attachments(tmp_path):
|
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
json_file = tmp_path / "with_attachments.json"
|
|
159
|
-
with open(json_file, "w") as f:
|
|
160
|
+
with open(json_file, "w", encoding="utf-8") as f:
|
|
160
161
|
json.dump([conversation], f)
|
|
161
162
|
|
|
162
163
|
# Set up environment
|
|
@@ -168,7 +169,7 @@ def test_import_conversation_with_attachments(tmp_path):
|
|
|
168
169
|
|
|
169
170
|
# Check attachment formatting
|
|
170
171
|
conv_path = tmp_path / "conversations/20250105-test-with-attachments.md"
|
|
171
|
-
content = conv_path.read_text()
|
|
172
|
+
content = conv_path.read_text(encoding="utf-8")
|
|
172
173
|
assert "**Attachment: test.txt**" in content
|
|
173
174
|
assert "```" in content
|
|
174
175
|
assert "Test file content" in content
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Tests for import_claude_projects command."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
|
|
4
5
|
import pytest
|
|
5
6
|
from typer.testing import CliRunner
|
|
6
7
|
|
|
@@ -43,7 +44,7 @@ def sample_project():
|
|
|
43
44
|
def sample_projects_json(tmp_path, sample_project):
|
|
44
45
|
"""Create a sample projects.json file."""
|
|
45
46
|
json_file = tmp_path / "projects.json"
|
|
46
|
-
with open(json_file, "w") as f:
|
|
47
|
+
with open(json_file, "w", encoding="utf-8") as f:
|
|
47
48
|
json.dump([sample_project], f)
|
|
48
49
|
return json_file
|
|
49
50
|
|
|
@@ -70,14 +71,14 @@ async def test_process_projects_json(tmp_path, sample_projects_json):
|
|
|
70
71
|
# Check document files
|
|
71
72
|
doc1 = project_dir / "docs/test-document.md"
|
|
72
73
|
assert doc1.exists()
|
|
73
|
-
content1 = doc1.read_text()
|
|
74
|
+
content1 = doc1.read_text(encoding="utf-8")
|
|
74
75
|
assert "# Test Document" in content1
|
|
75
76
|
assert "This is test content" in content1
|
|
76
77
|
|
|
77
78
|
# Check prompt template
|
|
78
79
|
prompt = project_dir / "prompt-template.md"
|
|
79
80
|
assert prompt.exists()
|
|
80
|
-
prompt_content = prompt.read_text()
|
|
81
|
+
prompt_content = prompt.read_text(encoding="utf-8")
|
|
81
82
|
assert "# Test Prompt" in prompt_content
|
|
82
83
|
assert "This is a test prompt" in prompt_content
|
|
83
84
|
|
|
@@ -160,7 +161,7 @@ def test_import_project_without_prompt(tmp_path):
|
|
|
160
161
|
}
|
|
161
162
|
|
|
162
163
|
json_file = tmp_path / "no_prompt.json"
|
|
163
|
-
with open(json_file, "w") as f:
|
|
164
|
+
with open(json_file, "w", encoding="utf-8") as f:
|
|
164
165
|
json.dump([project], f)
|
|
165
166
|
|
|
166
167
|
# Set up environment
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Tests for import_memory_json command."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
|
|
4
5
|
import pytest
|
|
5
6
|
from typer.testing import CliRunner
|
|
6
7
|
|
|
@@ -35,7 +36,7 @@ def sample_entities():
|
|
|
35
36
|
def sample_json_file(tmp_path, sample_entities):
|
|
36
37
|
"""Create a sample memory.json file."""
|
|
37
38
|
json_file = tmp_path / "memory.json"
|
|
38
|
-
with open(json_file, "w") as f:
|
|
39
|
+
with open(json_file, "w", encoding="utf-8") as f:
|
|
39
40
|
for entity in sample_entities:
|
|
40
41
|
f.write(json.dumps(entity) + "\n")
|
|
41
42
|
return json_file
|
|
@@ -55,7 +56,7 @@ async def test_process_memory_json(tmp_path, sample_json_file):
|
|
|
55
56
|
# Check file was created
|
|
56
57
|
entity_file = tmp_path / "test/test_entity.md"
|
|
57
58
|
assert entity_file.exists()
|
|
58
|
-
content = entity_file.read_text()
|
|
59
|
+
content = entity_file.read_text(encoding="utf-8")
|
|
59
60
|
assert "Test observation 1" in content
|
|
60
61
|
assert "Test observation 2" in content
|
|
61
62
|
assert "test_relation [[related_entity]]" in content
|
|
@@ -120,7 +121,7 @@ def test_import_json_command_handle_old_format(tmp_path):
|
|
|
120
121
|
]
|
|
121
122
|
|
|
122
123
|
json_file = tmp_path / "old_format.json"
|
|
123
|
-
with open(json_file, "w") as f:
|
|
124
|
+
with open(json_file, "w", encoding="utf-8") as f:
|
|
124
125
|
for item in old_format:
|
|
125
126
|
f.write(json.dumps(item) + "\n")
|
|
126
127
|
|
|
@@ -8,10 +8,10 @@ from pathlib import Path
|
|
|
8
8
|
|
|
9
9
|
import pytest
|
|
10
10
|
|
|
11
|
-
from basic_memory.markdown.markdown_processor import
|
|
11
|
+
from basic_memory.markdown.markdown_processor import DirtyFileError, MarkdownProcessor
|
|
12
12
|
from basic_memory.markdown.schemas import (
|
|
13
|
-
EntityMarkdown,
|
|
14
13
|
EntityFrontmatter,
|
|
14
|
+
EntityMarkdown,
|
|
15
15
|
Observation,
|
|
16
16
|
Relation,
|
|
17
17
|
)
|
|
@@ -41,7 +41,7 @@ async def test_write_new_minimal_file(markdown_processor: MarkdownProcessor, tmp
|
|
|
41
41
|
await markdown_processor.write_file(path, markdown)
|
|
42
42
|
|
|
43
43
|
# Read back and verify
|
|
44
|
-
content = path.read_text()
|
|
44
|
+
content = path.read_text(encoding="utf-8")
|
|
45
45
|
assert "---" in content # Has frontmatter
|
|
46
46
|
assert "type: note" in content
|
|
47
47
|
assert "permalink: test" in content
|
|
@@ -90,7 +90,7 @@ async def test_write_new_file_with_content(markdown_processor: MarkdownProcessor
|
|
|
90
90
|
await markdown_processor.write_file(path, markdown)
|
|
91
91
|
|
|
92
92
|
# Read back and verify
|
|
93
|
-
content = path.read_text()
|
|
93
|
+
content = path.read_text(encoding="utf-8")
|
|
94
94
|
|
|
95
95
|
# Check content preserved exactly
|
|
96
96
|
assert "# Custom Title" in content
|
|
@@ -169,7 +169,7 @@ async def test_dirty_file_detection(markdown_processor: MarkdownProcessor, tmp_p
|
|
|
169
169
|
checksum = await markdown_processor.write_file(path, initial)
|
|
170
170
|
|
|
171
171
|
# Modify file directly
|
|
172
|
-
path.write_text(path.read_text() + "\nModified!")
|
|
172
|
+
path.write_text(path.read_text(encoding="utf-8") + "\nModified!")
|
|
173
173
|
|
|
174
174
|
# Try to update with old checksum
|
|
175
175
|
update = EntityMarkdown(
|
|
@@ -46,7 +46,7 @@ async def test_create_canvas(app, test_config):
|
|
|
46
46
|
assert file_path.exists()
|
|
47
47
|
|
|
48
48
|
# Verify content is correct
|
|
49
|
-
content = json.loads(file_path.read_text())
|
|
49
|
+
content = json.loads(file_path.read_text(encoding="utf-8"))
|
|
50
50
|
assert content["nodes"] == nodes
|
|
51
51
|
assert content["edges"] == edges
|
|
52
52
|
|
|
@@ -81,7 +81,7 @@ async def test_create_canvas_with_extension(app, test_config):
|
|
|
81
81
|
assert file_path.exists()
|
|
82
82
|
|
|
83
83
|
# Verify content
|
|
84
|
-
content = json.loads(file_path.read_text())
|
|
84
|
+
content = json.loads(file_path.read_text(encoding="utf-8"))
|
|
85
85
|
assert content["nodes"] == nodes
|
|
86
86
|
|
|
87
87
|
|
|
@@ -134,7 +134,7 @@ async def test_update_existing_canvas(app, test_config):
|
|
|
134
134
|
assert "Updated: visualizations/update-test.canvas" in result
|
|
135
135
|
|
|
136
136
|
# Verify content was updated
|
|
137
|
-
content = json.loads(file_path.read_text())
|
|
137
|
+
content = json.loads(file_path.read_text(encoding="utf-8"))
|
|
138
138
|
assert content["nodes"] == updated_nodes
|
|
139
139
|
assert content["edges"] == updated_edges
|
|
140
140
|
|
|
@@ -252,7 +252,7 @@ async def test_create_canvas_complex_content(app, test_config):
|
|
|
252
252
|
assert file_path.exists()
|
|
253
253
|
|
|
254
254
|
# Verify content is correct with all complex structures
|
|
255
|
-
content = json.loads(file_path.read_text())
|
|
255
|
+
content = json.loads(file_path.read_text(encoding="utf-8"))
|
|
256
256
|
assert len(content["nodes"]) == 4
|
|
257
257
|
assert len(content["edges"]) == 2
|
|
258
258
|
|
|
@@ -144,14 +144,14 @@ async def test_rapid_atomic_writes(watch_service, test_config):
|
|
|
144
144
|
await asyncio.sleep(0.1)
|
|
145
145
|
|
|
146
146
|
# Read content to verify
|
|
147
|
-
content1 = final_path.read_text()
|
|
147
|
+
content1 = final_path.read_text(encoding="utf-8")
|
|
148
148
|
assert content1 == "First version"
|
|
149
149
|
|
|
150
150
|
# Simulate the second atomic write
|
|
151
151
|
tmp2_path.rename(final_path)
|
|
152
152
|
|
|
153
153
|
# Verify content was updated
|
|
154
|
-
content2 = final_path.read_text()
|
|
154
|
+
content2 = final_path.read_text(encoding="utf-8")
|
|
155
155
|
assert content2 == "Second version"
|
|
156
156
|
|
|
157
157
|
# Create a batch of changes that might arrive in mixed order
|
|
@@ -63,7 +63,7 @@ async def test_write_status(watch_service):
|
|
|
63
63
|
await watch_service.write_status()
|
|
64
64
|
|
|
65
65
|
assert watch_service.status_path.exists()
|
|
66
|
-
data = json.loads(watch_service.status_path.read_text())
|
|
66
|
+
data = json.loads(watch_service.status_path.read_text(encoding="utf-8"))
|
|
67
67
|
assert not data["running"]
|
|
68
68
|
assert data["error_count"] == 0
|
|
69
69
|
|
|
@@ -5,16 +5,16 @@ from pathlib import Path
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
7
|
from basic_memory.file_utils import (
|
|
8
|
+
FileError,
|
|
9
|
+
FileWriteError,
|
|
10
|
+
ParseError,
|
|
8
11
|
compute_checksum,
|
|
9
12
|
ensure_directory,
|
|
10
|
-
write_file_atomic,
|
|
11
|
-
parse_frontmatter,
|
|
12
13
|
has_frontmatter,
|
|
14
|
+
parse_frontmatter,
|
|
13
15
|
remove_frontmatter,
|
|
14
|
-
FileError,
|
|
15
|
-
FileWriteError,
|
|
16
|
-
ParseError,
|
|
17
16
|
update_frontmatter,
|
|
17
|
+
write_file_atomic,
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
|
|
@@ -52,7 +52,7 @@ async def test_write_file_atomic(tmp_path: Path):
|
|
|
52
52
|
|
|
53
53
|
await write_file_atomic(test_file, content)
|
|
54
54
|
assert test_file.exists()
|
|
55
|
-
assert test_file.read_text() == content
|
|
55
|
+
assert test_file.read_text(encoding="utf-8") == content
|
|
56
56
|
|
|
57
57
|
# Temp file should be cleaned up
|
|
58
58
|
assert not test_file.with_suffix(".tmp").exists()
|
|
@@ -185,7 +185,7 @@ async def test_update_frontmatter(tmp_path: Path):
|
|
|
185
185
|
checksum = await update_frontmatter(test_file, updates)
|
|
186
186
|
|
|
187
187
|
# Verify content
|
|
188
|
-
updated = test_file.read_text()
|
|
188
|
+
updated = test_file.read_text(encoding="utf-8")
|
|
189
189
|
assert "title: Test" in updated
|
|
190
190
|
assert "type: note" in updated
|
|
191
191
|
assert "Test Content" in updated
|
|
@@ -204,13 +204,13 @@ async def test_update_frontmatter(tmp_path: Path):
|
|
|
204
204
|
assert new_checksum != checksum
|
|
205
205
|
|
|
206
206
|
# Verify content
|
|
207
|
-
updated = test_file.read_text()
|
|
207
|
+
updated = test_file.read_text(encoding="utf-8")
|
|
208
208
|
fm = parse_frontmatter(updated)
|
|
209
209
|
assert fm == {"title": "Test", "type": "doc", "tags": ["test"]}
|
|
210
210
|
assert "Test Content" in updated
|
|
211
211
|
|
|
212
212
|
# Test 3: Update with empty dict shouldn't change anything
|
|
213
|
-
checksum_before = await compute_checksum(test_file.read_text())
|
|
213
|
+
checksum_before = await compute_checksum(test_file.read_text(encoding="utf-8"))
|
|
214
214
|
new_checksum = await update_frontmatter(test_file, {})
|
|
215
215
|
assert new_checksum == checksum_before
|
|
216
216
|
|
|
@@ -229,7 +229,7 @@ More content here"""
|
|
|
229
229
|
test_file.write_text(content)
|
|
230
230
|
await update_frontmatter(test_file, {"title": "Test"})
|
|
231
231
|
|
|
232
|
-
updated = test_file.read_text()
|
|
232
|
+
updated = test_file.read_text(encoding="utf-8")
|
|
233
233
|
assert remove_frontmatter(updated).strip() == content
|
|
234
234
|
|
|
235
235
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|