From 71c697bf6883445ab6c8bb64cd91f90880108bae Mon Sep 17 00:00:00 2001 From: Gros Frumos Date: Mon, 16 Mar 2026 08:50:52 +0200 Subject: [PATCH] =?UTF-8?q?kin:=20KIN-070=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D1=82=D1=8C=20sync=20=D1=81=20Obsidian:=20auto-cre?= =?UTF-8?q?ate=20vault=20dir=20+=20=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=BD=D1=8B=D0=B9=20vault=5Fpath?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - obsidian_sync.py: заменить проверку is_dir() на mkdir(parents=True, exist_ok=True) вместо ошибки при отсутствующей директории — автоматически создаём её - test_obsidian_sync.py: обновить тест #9 под новое поведение (директория создаётся) - БД fix: исправлен obsidian_vault_path (убраны лишние кавычки и /kin суффикс), теперь путь указывает на vault root, а не на подпапку проекта Результат: Exported: 79 decisions, errors: [] Co-Authored-By: Claude Sonnet 4.6 --- core/obsidian_sync.py | 53 ++++++++++++++++++++----------------- tests/test_obsidian_sync.py | 12 ++++----- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/core/obsidian_sync.py b/core/obsidian_sync.py index 1f4d2b6..d536147 100644 --- a/core/obsidian_sync.py +++ b/core/obsidian_sync.py @@ -141,36 +141,39 @@ def sync_obsidian(conn: sqlite3.Connection, project_id: str) -> dict: vault_path = Path(vault_path_str) errors: list[str] = [] + # --- Создаём vault_path если не существует --- + try: + vault_path.mkdir(parents=True, exist_ok=True) + except Exception as e: + errors.append(f"Cannot create vault path {vault_path_str}: {e}") + return {"exported_decisions": 0, "tasks_updated": 0, "errors": errors, "vault_path": vault_path_str} + # --- Export decisions --- exported_count = 0 - if not vault_path.is_dir(): - errors.append(f"Vault path does not exist or is not a directory: {vault_path_str}") - else: - try: - decisions = models.get_decisions(conn, project_id) - created_files = export_decisions_to_md(project_id, decisions, vault_path) - exported_count = len(created_files) - except Exception as e: - errors.append(f"Export error: {e}") + try: + decisions = models.get_decisions(conn, project_id) + created_files = export_decisions_to_md(project_id, decisions, vault_path) + exported_count = len(created_files) + except Exception as e: + errors.append(f"Export error: {e}") # --- Import checkboxes --- tasks_updated = 0 - if vault_path.is_dir(): - try: - checkboxes = parse_task_checkboxes(vault_path, project_id) - for item in checkboxes: - if not item["done"]: - continue - task = models.get_task(conn, item["task_id"]) - if task is None: - continue - if task.get("project_id") != project_id: - continue - if task.get("status") != "done": - models.update_task(conn, item["task_id"], status="done") - tasks_updated += 1 - except Exception as e: - errors.append(f"Import error: {e}") + try: + checkboxes = parse_task_checkboxes(vault_path, project_id) + for item in checkboxes: + if not item["done"]: + continue + task = models.get_task(conn, item["task_id"]) + if task is None: + continue + if task.get("project_id") != project_id: + continue + if task.get("status") != "done": + models.update_task(conn, item["task_id"], status="done") + tasks_updated += 1 + except Exception as e: + errors.append(f"Import error: {e}") return { "exported_decisions": exported_count, diff --git a/tests/test_obsidian_sync.py b/tests/test_obsidian_sync.py index b0e3027..642a24f 100644 --- a/tests/test_obsidian_sync.py +++ b/tests/test_obsidian_sync.py @@ -227,19 +227,19 @@ def test_export_frontmatter_has_yaml_delimiters(tmp_vault): # --------------------------------------------------------------------------- -# 9. sync_obsidian — несуществующий vault_path → ошибка в errors, не исключение +# 9. sync_obsidian — несуществующий vault_path → директория создаётся автоматически # --------------------------------------------------------------------------- -def test_sync_nonexistent_vault_records_error(db, tmp_path): - """Если vault_path не существует, sync возвращает ошибку в errors без raise.""" +def test_sync_nonexistent_vault_creates_directory(db, tmp_path): + """Если vault_path не существует, sync автоматически создаёт директорию.""" nonexistent = tmp_path / "ghost_vault" models.update_project(db, "proj1", obsidian_vault_path=str(nonexistent)) result = sync_obsidian(db, "proj1") - assert len(result["errors"]) > 0 - assert "does not exist" in result["errors"][0].lower() or "not exist" in result["errors"][0].lower() - assert result["exported_decisions"] == 0 + assert result["errors"] == [] + assert nonexistent.is_dir() # директория автоматически создана + assert result["exported_decisions"] == 0 # нет decisions в DB assert result["tasks_updated"] == 0