From ffefe4dd2154215e1a90866b9792b025e0ad140a Mon Sep 17 00:00:00 2001 From: Andrew Mulbrook Date: Thu, 26 Mar 2026 00:36:01 -0500 Subject: [PATCH] Blob is no more. Notes now always have content. --- trovedb/fs.py | 37 ++++++++++++++----------------- trovedb/qgui/tool_basic_editor.py | 8 +------ trovedb/trove.py | 14 ++++-------- trovedb/trovedb.py | 17 +++++--------- 4 files changed, 28 insertions(+), 48 deletions(-) diff --git a/trovedb/fs.py b/trovedb/fs.py index 3f36792..97ba565 100644 --- a/trovedb/fs.py +++ b/trovedb/fs.py @@ -4,7 +4,9 @@ import tempfile import datetime as dt from pathlib import Path from typing import Optional, Dict, List, Self, Iterable -from .trove import Note, Trove, TreeNote, BlobNote, Blob, Tree, BadNoteType, TreeEntry, NoteNotFound + +from .trove import Note, Trove, TreeNote, BadNoteType, TreeEntry, NoteNotFound +from . import fs_util as fsu class FSNote(Note): @@ -61,22 +63,17 @@ class FSNote(Note): def set_raw_metadata(self, key: str, value: bytes) -> None: self._trove._set_metadata(self._inode, key, value) -class FSBlobNote(FSNote, BlobNote): - def read(self) -> bytes: - if self._inode is None: - return b"" - return self._path.read_bytes() + def read_content(self) -> bytes: + """Read the raw content of the note.""" + content_file = fsu.get_content_path(self._path) + if content_file.exists(): + return content_file.read_bytes() + return b"" - def write(self, data: bytes) -> None: - self._path.write_bytes(data) - # Update cache just in case inode changed (some editors do this) - try: - new_inode = self._path.stat().st_ino - if new_inode != self._inode: - self._trove._update_cache(new_inode, self._path) - self._inode = new_inode - except OSError: - pass + def write_content(self, data:bytes) -> None: + """Write the raw content of the note.""" + content_file = fsu.get_content_path(self._path) + content_file.write_bytes(data) class FSTreeNote(FSNote, TreeNote): @property @@ -85,7 +82,7 @@ class FSTreeNote(FSNote, TreeNote): return "inode/directory" def link(self, name: str, note: Note): - if not isinstance(note, FSBlobNote): + if not isinstance(note, FSNote): raise BadNoteType("Only blob notes can be linked") target_path = self._path / name @@ -239,7 +236,7 @@ class FSTrove(Trove): if target_path.is_dir(): return FSTreeNote(self, inode=note_id, path=target_path) else: - return FSBlobNote(self, inode=note_id, path=target_path) + return FSNote(self, inode=note_id, path=target_path) def get_raw_note(self, note_id: int) -> Note: p = self.get_path_by_inode(note_id) @@ -248,7 +245,7 @@ class FSTrove(Trove): return self.get_raw_note_by_path(p) - def create_blob(self, data: bytes | None = None) -> BlobNote: + def create_blob(self, data: bytes | None = None) -> Note: fd, temp_path = tempfile.mkstemp(dir=self.working) try: if data: @@ -258,7 +255,7 @@ class FSTrove(Trove): p = Path(temp_path) inode = p.stat().st_ino self._update_cache(inode, p) - return FSBlobNote(self, inode=inode, path=p) + return FSNote(self, inode=inode, path=p) def get_root(self) -> TreeNote: return FSTreeNote(self, inode=self._root_inode, path=self.root) diff --git a/trovedb/qgui/tool_basic_editor.py b/trovedb/qgui/tool_basic_editor.py index 530b88c..8c0f408 100644 --- a/trovedb/qgui/tool_basic_editor.py +++ b/trovedb/qgui/tool_basic_editor.py @@ -18,11 +18,5 @@ class ToolBasicEditor(Tool): layout.addWidget(self._text_edit) self.refresh() - def _refresh_blob(self, note: tr.Blob): - self._text_edit.setPlainText(note.read().decode("utf-8")) - def refresh(self): - if isinstance(self.note, tr.Blob): - self._refresh_blob(cast(tr.Blob, self.note)) - - + self._text_edit.setPlainText(self.note.read_content().decode("utf-8")) diff --git a/trovedb/trove.py b/trovedb/trove.py index 924331f..a3a47f8 100644 --- a/trovedb/trove.py +++ b/trovedb/trove.py @@ -56,14 +56,12 @@ class Note(Protocol): """Set metadata value for the given key.""" ... -@runtime_checkable -class Blob(Protocol): - def read(self) -> bytes: + def read_content(self) -> bytes: """Read the raw content of the note.""" ... - def write(self, data: bytes) -> None: - """Write new content to the note.""" + def write_content(self, data:bytes) -> None: + """Write the raw content of the note.""" ... @@ -101,10 +99,6 @@ class Tree(Protocol): """Return all entries as {name: object_id}.""" ... -@runtime_checkable -class BlobNote(Note, Blob, Protocol): - """Blob Note""" - @runtime_checkable class TreeNote(Note, Tree, Protocol): """Tree Note""" @@ -121,7 +115,7 @@ class Trove(Protocol): """Retrieve a note by a object id""" ... - def create_blob(self, data: bytes | None = None) -> BlobNote: + def create_blob(self, data: bytes | None = None) -> Note: """Create a new blob node at the given path with content""" ... diff --git a/trovedb/trovedb.py b/trovedb/trovedb.py index 435ac64..77aaa23 100644 --- a/trovedb/trovedb.py +++ b/trovedb/trovedb.py @@ -13,7 +13,7 @@ from .db import Sqlite3Trove, NOTE_ROOT_ID from . import trove as tr -from .trove import Note, Trove, TreeNote, BlobNote, TreeEntry, NoteNotFound, ObjectId +from .trove import Note, Trove, TreeNote, TreeEntry, NoteNotFound, ObjectId class NoteImpl(Note): @@ -50,16 +50,11 @@ class NoteImpl(Note): def set_raw_metadata(self, key: str, value: bytes) -> None: self._db.write_metadata(self._object_id, key, value) - -class BlobNoteImpl(NoteImpl, BlobNote): - """Concrete BlobNote: a blob object in the store with metadata access.""" - - # Blob protocol - def read(self) -> bytes: + def read_content(self) -> bytes: data = self._db.read_object(self._object_id) return data if data is not None else b"" - def write(self, data: bytes) -> None: + def write_content(self, data: bytes) -> None: self._db.write_content(self._object_id, data) @@ -147,13 +142,13 @@ class TroveImpl: raise NoteNotFound(note_id) if self._db.is_tree(note_id) or info.type == "inode/directory": return TreeNoteImpl(self, note_id) - return BlobNoteImpl(self, note_id) + return NoteImpl(self, note_id) def create_blob(self, data: bytes | None = None, - dtype: str = "application/octet-stream") -> BlobNote: + dtype: str = "application/octet-stream") -> Note: """Create a new blob object and return a BlobNote for it.""" obj_id = self._db.write_blob(data or b"", dtype=dtype) - return BlobNoteImpl(self, obj_id) + return NoteImpl(self, obj_id) def get_root(self) -> TreeNote: """Return the root TreeNote (always id=NOTE_ROOT_ID)."""