2121Bear storage backend
2222'''
2323
24- from pathlib import PurePosixPath , Path
25- from typing import Iterable , Optional , List , Set , Dict , Tuple
26- import logging
27- from dataclasses import dataclass
28- from functools import partial
2924import errno
25+ import logging
3026import os
31- import threading
3227import re
33-
3428import sqlite3
29+ import threading
30+ from functools import partial
31+ from pathlib import PurePosixPath , Path
32+ from typing import Iterable , Optional , List , Set , Dict , Tuple
33+
34+ import bear # pylint: disable=import-error,wrong-import-order
3535import click
3636
3737from wildland .storage import Storage
3838from wildland .container import Container
3939from wildland .storage_backends .base import StorageBackend
40- from wildland .storage_backends .generated import \
41- GeneratedStorageMixin , CachedDirEntry , \
42- StaticFileEntry
40+ from wildland .storage_backends .generated import (
41+ CachedDirEntry ,
42+ GeneratedStorageMixin ,
43+ StaticFileEntry ,
44+ )
4345from wildland .storage_backends .watch import SimpleStorageWatcher
4446from wildland .manifest .manifest import Manifest
4547from wildland .manifest .schema import Schema
4850logger = logging .getLogger ('storage-bear' )
4951
5052
51- @dataclass
52- class BearNote :
53+ def get_md (note ) -> bytes :
5354 '''
54- Individual Bear note.
55+ Get the contents of note Markdown file .
5556 '''
5657
57- ident : str
58- title : str
59- text : str
60- tags : List [str ]
61-
62- def get_md (self ) -> bytes :
63- '''
64- Get the contents of note Markdown file.
65- '''
66- content = 'title: ' + self .title + '\n ---\n ' + self .text + '\n '
67- return content .encode ('utf-8' )
58+ return f'title: { note .title } \n ---\n { note .text } \n ' .encode ('utf-8' )
6859
6960
7061def get_note_paths (tags : List [str ]) -> List [PurePosixPath ]:
@@ -135,8 +126,8 @@ def connect(self):
135126 self .db_lock = self .conn_locks [self .path ]
136127 self .conn_refcount [self .path ] += 1
137128 else :
138- self .db = sqlite3 . connect (self .path , check_same_thread = False )
139- self .db .row_factory = sqlite3 . Row
129+ self .db = bear . Bear (self .path , connect = False )
130+ self .db .connect ( check_same_thread = False )
140131 self .db_lock = threading .RLock ()
141132 self .conn_cache [self .path ] = self .db
142133 self .conn_locks [self .path ] = self .db_lock
@@ -155,7 +146,7 @@ def disconnect(self):
155146 del self .conn_refcount [self .path ]
156147 del self .conn_cache [self .path ]
157148 del self .conn_locks [self .path ]
158- self .db .close ()
149+ # self.db.close()
159150 self .db = None
160151 self .db_lock = None
161152
@@ -167,9 +158,8 @@ def get_note_idents(self) -> Iterable[str]:
167158 assert self .db and self .db_lock
168159
169160 with self .db_lock :
170- cursor = self .db .cursor ()
171- cursor .execute ('SELECT ZUNIQUEIDENTIFIER FROM ZSFNOTE' )
172- return [row ['ZUNIQUEIDENTIFIER' ] for row in cursor .fetchall ()]
161+ for note in self .db .notes ():
162+ yield note .id
173163
174164 def get_note_idents_with_tags (self ) -> Iterable [Tuple [str , List [str ]]]:
175165 '''
@@ -179,61 +169,18 @@ def get_note_idents_with_tags(self) -> Iterable[Tuple[str, List[str]]]:
179169 assert self .db and self .db_lock
180170
181171 with self .db_lock :
182- cursor = self .db .cursor ()
183-
184- result : Dict [str , List [str ]] = {
185- ident : []
186- for ident in self .get_note_idents ()
187- }
188- cursor .execute ('''
189- SELECT ZUNIQUEIDENTIFIER, ZSFNOTETAG.ZTITLE FROM ZSFNOTE
190- JOIN Z_7TAGS ON Z_7TAGS.Z_7NOTES = ZSFNOTE.Z_PK
191- JOIN ZSFNOTETAG ON Z_7TAGS.Z_14TAGS = ZSFNOTETAG.Z_PK
192- ''' )
193- for row in cursor .fetchall ():
194- ident = row ['ZUNIQUEIDENTIFIER' ]
195- tag = row ['ZTITLE' ]
196- result .setdefault (ident , []).append (tag )
197- return result .items ()
198-
199- def get_note (self , ident : str ) -> Optional [BearNote ]:
200- '''
201- Retrieve a single note.
202- '''
172+ for note in self .db .notes ():
173+ yield note .id , [tag .title for tag in note .tags ()]
203174
204- assert self .db and self .db_lock
205-
206- with self .db_lock :
207- cursor = self .db .cursor ()
208- cursor .execute ('''
209- SELECT Z_PK, ZTITLE, ZTEXT FROM ZSFNOTE
210- WHERE ZUNIQUEIDENTIFIER = ?
211- ''' , [ident ])
212- row = cursor .fetchone ()
213- if not row :
214- return None
215-
216- tags = self .get_tags (row ['Z_PK' ])
217- return BearNote (ident = ident , title = row ['ZTITLE' ], text = row ['ZTEXT' ],
218- tags = tags )
219-
220- def get_tags (self , pk : int ) -> List [str ]:
175+ def get_note (self , ident : str ) -> Optional [bear .Note ]:
221176 '''
222- Retrieve a list of tags for a note.
177+ Retrieve a single note.
223178 '''
224179
225180 assert self .db and self .db_lock
226181
227182 with self .db_lock :
228- cursor = self .db .cursor ()
229- cursor .execute ('''
230- SELECT ZTITLE FROM ZSFNOTETAG
231- JOIN Z_7TAGS ON Z_7TAGS.Z_7NOTES = ?
232- AND Z_7TAGS.Z_14TAGS = ZSFNOTETAG.Z_PK
233- ''' , [pk ])
234-
235- return [tag_row ['ZTITLE' ] for tag_row in cursor .fetchall ()]
236-
183+ return self .db .get_note (ident )
237184
238185class BearDBWatcher (SimpleStorageWatcher ):
239186 '''
@@ -397,7 +344,7 @@ def _get_note(self, ident):
397344 note = self .bear_db .get_note (ident )
398345 if not note :
399346 raise FileNotFoundError (errno .ENOENT , '' )
400- return note . get_md ()
347+ return get_md (note )
401348
402349
403350class BearNoteStorageBackend (GeneratedStorageMixin , StorageBackend ):
@@ -464,4 +411,4 @@ def _dir_root(self):
464411 raise FileNotFoundError (errno .ENOENT , '' )
465412
466413 name = re .sub (r'[\0\\/:*?"<>|]' , '-' , note .title )
467- yield StaticFileEntry (f'{ name } .md' , note . get_md ())
414+ yield StaticFileEntry (f'{ name } .md' , get_md (note ))
0 commit comments