tenseleyflow/dlm-lsp / a48dce4

Browse files

Auto-create store on document open when no manifest exists

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
a48dce432c6e3964457b93e9915c08489cf1b76e
Parents
5270574
Tree
f0f2261

3 changed files

StatusFile+-
M src/dlm_lsp/doc_state.py 34 0
M src/dlm_lsp/server.py 2 1
M tests/unit/test_doc_state.py 27 0
src/dlm_lsp/doc_state.pymodified
@@ -45,6 +45,40 @@ class DocumentState:
4545
             _log.debug("parse failed for %s: %s", self.uri, exc)
4646
         return self.parsed
4747
 
48
+    def ensure_store(self) -> bool:
49
+        """Create the store layout + manifest if it doesn't exist yet.
50
+
51
+        Returns True if a store was created, False if it already existed
52
+        or if the document couldn't be parsed.
53
+        """
54
+        parsed = self.ensure_parsed()
55
+        if parsed is None:
56
+            return False
57
+        try:
58
+            from dlm.store.manifest import Manifest, save_manifest
59
+            from dlm.store.paths import for_dlm
60
+
61
+            store = for_dlm(parsed.frontmatter.dlm_id)
62
+            if store.manifest.exists():
63
+                return False
64
+            store.ensure_layout()
65
+            save_manifest(
66
+                store.manifest,
67
+                Manifest(
68
+                    dlm_id=parsed.frontmatter.dlm_id,
69
+                    base_model=parsed.frontmatter.base_model,
70
+                ),
71
+            )
72
+            _log.info(
73
+                "auto-created store for %s at %s",
74
+                parsed.frontmatter.dlm_id,
75
+                store.root,
76
+            )
77
+            return True
78
+        except Exception as exc:
79
+            _log.debug("store auto-create failed for %s: %s", self.uri, exc)
80
+            return False
81
+
4882
     def ensure_base_model_spec(self) -> dict[str, Any] | None:
4983
         if self.base_model_spec is not None:
5084
             return self.base_model_spec
src/dlm_lsp/server.pymodified
@@ -53,7 +53,8 @@ def _on_did_open(ls: DlmLanguageServer, params: lsp.DidOpenTextDocumentParams) -
5353
     uri = params.text_document.uri
5454
     text = params.text_document.text
5555
     version = params.text_document.version
56
-    ls.state.open(uri, text, version)
56
+    state = ls.state.open(uri, text, version)
57
+    state.ensure_store()
5758
     _publish_diagnostics(ls, uri)
5859
 
5960
 
tests/unit/test_doc_state.pymodified
@@ -2,6 +2,10 @@
22
 
33
 from __future__ import annotations
44
 
5
+from pathlib import Path
6
+
7
+import pytest
8
+
59
 from dlm_lsp.doc_state import DocumentState, StateStore
610
 
711
 _MINIMAL_DLM = """\
@@ -41,6 +45,29 @@ class TestDocumentState:
4145
         assert state.ensure_parsed() is None
4246
         assert state.parse_error is None
4347
 
48
+    def test_ensure_store_creates_store_on_first_call(
49
+        self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
50
+    ) -> None:
51
+        monkeypatch.setenv("DLM_HOME", str(tmp_path))
52
+        state = DocumentState(uri="file:///a.dlm", text=_MINIMAL_DLM)
53
+        created = state.ensure_store()
54
+        assert created is True
55
+        manifest = tmp_path / "store" / "01KPQ9M3000000000000000000" / "manifest.json"
56
+        assert manifest.exists()
57
+
58
+    def test_ensure_store_skips_if_already_exists(
59
+        self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
60
+    ) -> None:
61
+        monkeypatch.setenv("DLM_HOME", str(tmp_path))
62
+        state = DocumentState(uri="file:///a.dlm", text=_MINIMAL_DLM)
63
+        state.ensure_store()
64
+        created_again = state.ensure_store()
65
+        assert created_again is False
66
+
67
+    def test_ensure_store_returns_false_on_bad_doc(self) -> None:
68
+        state = DocumentState(uri="file:///a.dlm", text="not a dlm file")
69
+        assert state.ensure_store() is False
70
+
4471
     def test_ensure_base_model_spec_resolves_registry_key(self) -> None:
4572
         state = DocumentState(uri="file:///a.dlm", text=_MINIMAL_DLM)
4673
         spec = state.ensure_base_model_spec()