Skip to content
This repository has been archived by the owner on Mar 6, 2024. It is now read-only.

Commit

Permalink
wildland_bearnotes: use pybear
Browse files Browse the repository at this point in the history
  • Loading branch information
woju authored and marmarek committed Oct 12, 2020
1 parent 124adf4 commit 4c3f61f
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 82 deletions.
3 changes: 2 additions & 1 deletion ci/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ RUN apt-get -qy update && apt-get install -y \
time \
tree \
netcat-openbsd \
moreutils
moreutils \
git

RUN useradd --create-home user

Expand Down
5 changes: 4 additions & 1 deletion plugins/bearnotes/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@
'bear-db = wildland_bearnotes.backend:BearDBStorageBackend',
'bear-note = wildland_bearnotes.backend:BearNoteStorageBackend',
]
}
},
install_requires=[
'pybear @ git+https://github.com/golemfoundation/pybear#egg=0.0.20200914',
],
)
107 changes: 27 additions & 80 deletions plugins/bearnotes/wildland_bearnotes/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,27 @@
Bear storage backend
'''

from pathlib import PurePosixPath, Path
from typing import Iterable, Optional, List, Set, Dict, Tuple
import logging
from dataclasses import dataclass
from functools import partial
import errno
import logging
import os
import threading
import re

import sqlite3
import threading
from functools import partial
from pathlib import PurePosixPath, Path
from typing import Iterable, Optional, List, Set, Dict, Tuple

import bear # pylint: disable=import-error,wrong-import-order
import click

from wildland.storage import Storage
from wildland.container import Container
from wildland.storage_backends.base import StorageBackend
from wildland.storage_backends.generated import \
GeneratedStorageMixin, CachedDirEntry, \
StaticFileEntry
from wildland.storage_backends.generated import (
CachedDirEntry,
GeneratedStorageMixin,
StaticFileEntry,
)
from wildland.storage_backends.watch import SimpleStorageWatcher
from wildland.manifest.manifest import Manifest
from wildland.manifest.schema import Schema
Expand All @@ -48,23 +50,12 @@
logger = logging.getLogger('storage-bear')


@dataclass
class BearNote:
def get_md(note) -> bytes:
'''
Individual Bear note.
Get the contents of note Markdown file.
'''

ident: str
title: str
text: str
tags: List[str]

def get_md(self) -> bytes:
'''
Get the contents of note Markdown file.
'''
content = 'title: ' + self.title + '\n---\n' + self.text + '\n'
return content.encode('utf-8')
return f'title: {note.title}\n---\n{note.text}\n'.encode('utf-8')


def get_note_paths(tags: List[str]) -> List[PurePosixPath]:
Expand Down Expand Up @@ -135,8 +126,8 @@ def connect(self):
self.db_lock = self.conn_locks[self.path]
self.conn_refcount[self.path] += 1
else:
self.db = sqlite3.connect(self.path, check_same_thread=False)
self.db.row_factory = sqlite3.Row
self.db = bear.Bear(self.path, connect=False)
self.db.connect(check_same_thread=False)
self.db_lock = threading.RLock()
self.conn_cache[self.path] = self.db
self.conn_locks[self.path] = self.db_lock
Expand All @@ -155,7 +146,7 @@ def disconnect(self):
del self.conn_refcount[self.path]
del self.conn_cache[self.path]
del self.conn_locks[self.path]
self.db.close()
# self.db.close()
self.db = None
self.db_lock = None

Expand All @@ -167,9 +158,8 @@ def get_note_idents(self) -> Iterable[str]:
assert self.db and self.db_lock

with self.db_lock:
cursor = self.db.cursor()
cursor.execute('SELECT ZUNIQUEIDENTIFIER FROM ZSFNOTE')
return [row['ZUNIQUEIDENTIFIER'] for row in cursor.fetchall()]
for note in self.db.notes():
yield note.id

def get_note_idents_with_tags(self) -> Iterable[Tuple[str, List[str]]]:
'''
Expand All @@ -179,61 +169,18 @@ def get_note_idents_with_tags(self) -> Iterable[Tuple[str, List[str]]]:
assert self.db and self.db_lock

with self.db_lock:
cursor = self.db.cursor()

result: Dict[str, List[str]] = {
ident: []
for ident in self.get_note_idents()
}
cursor.execute('''
SELECT ZUNIQUEIDENTIFIER, ZSFNOTETAG.ZTITLE FROM ZSFNOTE
JOIN Z_7TAGS ON Z_7TAGS.Z_7NOTES = ZSFNOTE.Z_PK
JOIN ZSFNOTETAG ON Z_7TAGS.Z_14TAGS = ZSFNOTETAG.Z_PK
''')
for row in cursor.fetchall():
ident = row['ZUNIQUEIDENTIFIER']
tag = row['ZTITLE']
result.setdefault(ident, []).append(tag)
return result.items()

def get_note(self, ident: str) -> Optional[BearNote]:
'''
Retrieve a single note.
'''
for note in self.db.notes():
yield note.id, [tag.title for tag in note.tags()]

assert self.db and self.db_lock

with self.db_lock:
cursor = self.db.cursor()
cursor.execute('''
SELECT Z_PK, ZTITLE, ZTEXT FROM ZSFNOTE
WHERE ZUNIQUEIDENTIFIER = ?
''', [ident])
row = cursor.fetchone()
if not row:
return None

tags = self.get_tags(row['Z_PK'])
return BearNote(ident=ident, title=row['ZTITLE'], text=row['ZTEXT'],
tags=tags)

def get_tags(self, pk: int) -> List[str]:
def get_note(self, ident: str) -> Optional[bear.Note]:
'''
Retrieve a list of tags for a note.
Retrieve a single note.
'''

assert self.db and self.db_lock

with self.db_lock:
cursor = self.db.cursor()
cursor.execute('''
SELECT ZTITLE FROM ZSFNOTETAG
JOIN Z_7TAGS ON Z_7TAGS.Z_7NOTES = ?
AND Z_7TAGS.Z_14TAGS = ZSFNOTETAG.Z_PK
''', [pk])

return [tag_row['ZTITLE'] for tag_row in cursor.fetchall()]

return self.db.get_note(ident)

class BearDBWatcher(SimpleStorageWatcher):
'''
Expand Down Expand Up @@ -397,7 +344,7 @@ def _get_note(self, ident):
note = self.bear_db.get_note(ident)
if not note:
raise FileNotFoundError(errno.ENOENT, '')
return note.get_md()
return get_md(note)


class BearNoteStorageBackend(GeneratedStorageMixin, StorageBackend):
Expand Down Expand Up @@ -464,4 +411,4 @@ def _dir_root(self):
raise FileNotFoundError(errno.ENOENT, '')

name = re.sub(r'[\0\\/:*?"<>|]', '-', note.title)
yield StaticFileEntry(f'{name}.md', note.get_md())
yield StaticFileEntry(f'{name}.md', get_md(note))

0 comments on commit 4c3f61f

Please sign in to comment.