fetch/set remaining collection properties as required

This commit is contained in:
Damien Elmes 2020-05-15 13:33:37 +10:00
parent 31480be5e7
commit a2b7a30841
3 changed files with 46 additions and 42 deletions

View file

@ -37,10 +37,6 @@ from anki.utils import devMode, ids2str, intTime
class _Collection: class _Collection:
db: Optional[DBProxy] db: Optional[DBProxy]
sched: Union[V1Scheduler, V2Scheduler] sched: Union[V1Scheduler, V2Scheduler]
mod: int
scm: int
_usn: int
ls: int
_undo: List[Any] _undo: List[Any]
def __init__( def __init__(
@ -64,7 +60,6 @@ class _Collection:
self.decks = DeckManager(self) self.decks = DeckManager(self)
self.tags = TagManager(self) self.tags = TagManager(self)
self.conf = ConfigManager(self) self.conf = ConfigManager(self)
self.load()
self._loadScheduler() self._loadScheduler()
def name(self) -> Any: def name(self) -> Any:
@ -129,11 +124,7 @@ class _Collection:
# DB-related # DB-related
########################################################################## ##########################################################################
def load(self) -> None: # legacy properties; these will likely go away in the future
(self.mod, self.scm, self._usn, self.ls,) = self.db.first(
"""
select mod, scm, usn, ls from col"""
)
def _get_crt(self) -> int: def _get_crt(self) -> int:
return self.db.scalar("select crt from col") return self.db.scalar("select crt from col")
@ -141,43 +132,57 @@ select mod, scm, usn, ls from col"""
def _set_crt(self, val: int) -> None: def _set_crt(self, val: int) -> None:
self.db.execute("update col set crt=?", val) self.db.execute("update col set crt=?", val)
def _get_scm(self) -> int:
return self.db.scalar("select scm from col")
def _set_scm(self, val: int) -> None:
self.db.execute("update col set scm=?", val)
def _get_usn(self) -> int:
return self.db.scalar("select usn from col")
def _set_usn(self, val: int) -> None:
self.db.execute("update col set usn=?", val)
def _get_mod(self) -> int:
return self.db.scalar("select mod from col")
def _set_mod(self, val: int) -> None:
self.db.execute("update col set mod=?", val)
def _get_ls(self) -> int:
return self.db.scalar("select ls from col")
def _set_ls(self, val: int) -> None:
self.db.execute("update col set ls=?", val)
crt = property(_get_crt, _set_crt) crt = property(_get_crt, _set_crt)
mod = property(_get_mod, _set_mod)
_usn = property(_get_usn, _set_usn)
scm = property(_get_scm, _set_scm)
ls = property(_get_ls, _set_ls)
def setMod(self) -> None: # legacy
"""Mark DB modified. def setMod(self, mod: Optional[int] = None) -> None:
# this is now a no-op, as modifications to things like the config
# will mark the collection modified automatically
pass
DB operations and the deck/model managers do this automatically, so this flush = setMod
is only necessary if you modify properties of this object."""
self.db.mod = True
def flush(self, mod: Optional[int] = None) -> None: def modified_after_begin(self) -> bool:
"Flush state to DB, updating mod time." # Until we can move away from long-running transactions, the Python
self.mod = intTime(1000) if mod is None else mod # code needs to know if transaction should be committed, so we need
self.db.execute( # to check if the backend updated the modification time.
"""update col set return self.db.last_begin_at < self.mod
mod=?, scm=?, usn=?, ls=?""",
self.mod,
self.scm,
self._usn,
self.ls,
)
def flush_all_changes(self, mod: Optional[int] = None):
self.models.flush()
self.decks.flush()
# set mod flag if mtime changed by backend
if self.db.scalar("select mod from col") != self.mod:
self.db.mod = True
if self.db.mod:
self.flush(mod)
def save( def save(
self, name: Optional[str] = None, mod: Optional[int] = None, trx: bool = True self, name: Optional[str] = None, mod: Optional[int] = None, trx: bool = True
) -> None: ) -> None:
"Flush, commit DB, and take out another write lock if trx=True." "Flush, commit DB, and take out another write lock if trx=True."
self.flush_all_changes(mod) # commit needed?
# and flush deck + bump mod if db has been changed if self.db.mod or self.modified_after_begin():
if self.db.mod: self.mod = intTime(1000) if mod is None else mod
self.db.commit() self.db.commit()
self.db.mod = False self.db.mod = False
if trx: if trx:
@ -213,7 +218,6 @@ mod=?, scm=?, usn=?, ls=?""",
def rollback(self) -> None: def rollback(self) -> None:
self.db.rollback() self.db.rollback()
self.db.begin() self.db.begin()
self.load()
def modSchema(self, check: bool) -> None: def modSchema(self, check: bool) -> None:
"Mark schema modified. Call this first so user can abort if necessary." "Mark schema modified. Call this first so user can abort if necessary."
@ -385,11 +389,9 @@ select id from notes where id in %s and id not in (select nid from cards)"""
def find_cards( def find_cards(
self, query: str, order: Union[bool, str, int] = False, reverse: bool = False, self, query: str, order: Union[bool, str, int] = False, reverse: bool = False,
) -> Sequence[int]: ) -> Sequence[int]:
self.flush_all_changes()
return self.backend.search_cards(query, order, reverse) return self.backend.search_cards(query, order, reverse)
def find_notes(self, query: str) -> Sequence[int]: def find_notes(self, query: str) -> Sequence[int]:
self.flush_all_changes()
return self.backend.search_notes(query) return self.backend.search_notes(query)
def find_and_replace( def find_and_replace(

View file

@ -25,11 +25,13 @@ class DBProxy:
self._backend = backend self._backend = backend
self._path = path self._path = path
self.mod = False self.mod = False
self.last_begin_at = 0
# Transactions # Transactions
############### ###############
def begin(self) -> None: def begin(self) -> None:
self.last_begin_at = anki.utils.intTime(1000)
self._backend.db_begin() self._backend.db_begin()
def commit(self) -> None: def commit(self) -> None:

View file

@ -22,8 +22,8 @@ def test_create_open():
deck = aopen(path) deck = aopen(path)
# for open() # for open()
newPath = deck.path newPath = deck.path
deck.close()
newMod = deck.mod newMod = deck.mod
deck.close()
del deck del deck
# reopen # reopen