mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
convert invariant assertions to if statements
The packaged builds of 2.1.50 use python -OO, which means our assertion statements won't be run. This is not an issue for unit tests (as we don't run them from a packaged build), or for type assertions (which are added for mypy's benefit), but we do need to ensure that invariant checks are still run.
This commit is contained in:
parent
88392634a8
commit
9ed13eee80
15 changed files with 53 additions and 30 deletions
|
@ -40,7 +40,8 @@ from .fluent import GeneratedTranslations, LegacyTranslationEnum
|
||||||
# the following comment is required to suppress a warning that only shows up
|
# the following comment is required to suppress a warning that only shows up
|
||||||
# when there are other pylint failures
|
# when there are other pylint failures
|
||||||
# pylint: disable=c-extension-no-member
|
# pylint: disable=c-extension-no-member
|
||||||
assert rsbridge.buildhash() == anki.buildinfo.buildhash
|
if rsbridge.buildhash() != anki.buildinfo.buildhash:
|
||||||
|
raise Exception("rsbridge and anki build hashes do not match")
|
||||||
|
|
||||||
|
|
||||||
class RustBackend(RustBackendGenerated):
|
class RustBackend(RustBackendGenerated):
|
||||||
|
|
|
@ -201,7 +201,8 @@ class Card(DeprecatedNamesMixin):
|
||||||
|
|
||||||
def set_user_flag(self, flag: int) -> None:
|
def set_user_flag(self, flag: int) -> None:
|
||||||
print("use col.set_user_flag_for_cards() instead")
|
print("use col.set_user_flag_for_cards() instead")
|
||||||
assert 0 <= flag <= 7
|
if not 0 <= flag <= 7:
|
||||||
|
raise Exception("invalid flag")
|
||||||
self.flags = (self.flags & ~0b111) | flag
|
self.flags = (self.flags & ~0b111) | flag
|
||||||
|
|
||||||
@deprecated(info="use card.render_output() directly")
|
@deprecated(info="use card.render_output() directly")
|
||||||
|
|
|
@ -264,8 +264,8 @@ class Collection(DeprecatedNamesMixin):
|
||||||
self.models._clear_cache()
|
self.models._clear_cache()
|
||||||
|
|
||||||
def reopen(self, after_full_sync: bool = False) -> None:
|
def reopen(self, after_full_sync: bool = False) -> None:
|
||||||
assert not self.db
|
if self.db:
|
||||||
assert self.path.endswith(".anki2")
|
raise Exception("reopen() called with open db")
|
||||||
|
|
||||||
self._last_checkpoint_at = time.time()
|
self._last_checkpoint_at = time.time()
|
||||||
self._undo: _UndoInfo = None
|
self._undo: _UndoInfo = None
|
||||||
|
|
|
@ -109,7 +109,8 @@ class DeckManager(DeprecatedNamesMixin):
|
||||||
|
|
||||||
def add_deck_legacy(self, deck: DeckDict) -> OpChangesWithId:
|
def add_deck_legacy(self, deck: DeckDict) -> OpChangesWithId:
|
||||||
"Add a deck created with new_deck_legacy(). Must have id of 0."
|
"Add a deck created with new_deck_legacy(). Must have id of 0."
|
||||||
assert deck["id"] == 0
|
if not deck["id"] == 0:
|
||||||
|
raise Exception("id should be 0")
|
||||||
return self.col._backend.add_deck_legacy(to_json_bytes(deck))
|
return self.col._backend.add_deck_legacy(to_json_bytes(deck))
|
||||||
|
|
||||||
def id(
|
def id(
|
||||||
|
|
|
@ -117,7 +117,8 @@ class NoteImporter(Importer):
|
||||||
|
|
||||||
def importNotes(self, notes: list[ForeignNote]) -> None:
|
def importNotes(self, notes: list[ForeignNote]) -> None:
|
||||||
"Convert each card into a note, apply attributes and add to col."
|
"Convert each card into a note, apply attributes and add to col."
|
||||||
assert self.mappingOk()
|
if not self.mappingOk():
|
||||||
|
raise Exception("mapping not ok")
|
||||||
# note whether tags are mapped
|
# note whether tags are mapped
|
||||||
self._tagsMapped = False
|
self._tagsMapped = False
|
||||||
for f in self.mapping:
|
for f in self.mapping:
|
||||||
|
|
|
@ -304,12 +304,14 @@ class ModelManager(DeprecatedNamesMixin):
|
||||||
def rename_field(
|
def rename_field(
|
||||||
self, notetype: NotetypeDict, field: FieldDict, new_name: str
|
self, notetype: NotetypeDict, field: FieldDict, new_name: str
|
||||||
) -> None:
|
) -> None:
|
||||||
assert field in notetype["flds"]
|
if not field in notetype["flds"]:
|
||||||
|
raise Exception("invalid field")
|
||||||
field["name"] = new_name
|
field["name"] = new_name
|
||||||
|
|
||||||
def set_sort_index(self, notetype: NotetypeDict, idx: int) -> None:
|
def set_sort_index(self, notetype: NotetypeDict, idx: int) -> None:
|
||||||
"Modifies schema."
|
"Modifies schema."
|
||||||
assert 0 <= idx < len(notetype["flds"])
|
if not 0 <= idx < len(notetype["flds"]):
|
||||||
|
raise Exception("invalid sort index")
|
||||||
notetype["sortf"] = idx
|
notetype["sortf"] = idx
|
||||||
|
|
||||||
# Adding & changing templates
|
# Adding & changing templates
|
||||||
|
@ -332,7 +334,8 @@ class ModelManager(DeprecatedNamesMixin):
|
||||||
|
|
||||||
def remove_template(self, notetype: NotetypeDict, template: TemplateDict) -> None:
|
def remove_template(self, notetype: NotetypeDict, template: TemplateDict) -> None:
|
||||||
"Modifies schema."
|
"Modifies schema."
|
||||||
assert len(notetype["tmpls"]) > 1
|
if not len(notetype["tmpls"]) > 1:
|
||||||
|
raise Exception("must have 1 template")
|
||||||
notetype["tmpls"].remove(template)
|
notetype["tmpls"].remove(template)
|
||||||
|
|
||||||
def reposition_template(
|
def reposition_template(
|
||||||
|
|
|
@ -34,7 +34,8 @@ class Note(DeprecatedNamesMixin):
|
||||||
model: NotetypeDict | NotetypeId | None = None,
|
model: NotetypeDict | NotetypeId | None = None,
|
||||||
id: NoteId | None = None,
|
id: NoteId | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
assert not (model and id)
|
if model and id:
|
||||||
|
raise Exception("only model or id should be provided")
|
||||||
notetype_id = model["id"] if isinstance(model, dict) else model
|
notetype_id = model["id"] if isinstance(model, dict) else model
|
||||||
self.col = col.weakref()
|
self.col = col.weakref()
|
||||||
|
|
||||||
|
@ -76,7 +77,8 @@ class Note(DeprecatedNamesMixin):
|
||||||
def flush(self) -> None:
|
def flush(self) -> None:
|
||||||
"""This preserves any current checkpoint.
|
"""This preserves any current checkpoint.
|
||||||
For an undo entry, use col.update_note() instead."""
|
For an undo entry, use col.update_note() instead."""
|
||||||
assert self.id != 0
|
if self.id == 0:
|
||||||
|
raise Exception("can't flush a new note")
|
||||||
self.col._backend.update_notes(
|
self.col._backend.update_notes(
|
||||||
notes=[self._to_backend_note()], skip_undo_entry=True
|
notes=[self._to_backend_note()], skip_undo_entry=True
|
||||||
)
|
)
|
||||||
|
|
|
@ -449,8 +449,8 @@ limit ?"""
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def answerCard(self, card: Card, ease: int) -> None:
|
def answerCard(self, card: Card, ease: int) -> None:
|
||||||
assert 1 <= ease <= 4
|
if (not 1 <= ease <= 4) or (not 0 <= card.queue <= 4):
|
||||||
assert 0 <= card.queue <= 4
|
raise Exception("invalid ease or queue")
|
||||||
self.col.save_card_review_undo_info(card)
|
self.col.save_card_review_undo_info(card)
|
||||||
if self._burySiblingsOnAnswer:
|
if self._burySiblingsOnAnswer:
|
||||||
self._burySiblings(card)
|
self._burySiblings(card)
|
||||||
|
@ -772,7 +772,8 @@ limit ?"""
|
||||||
# note: when adding revlog entries in the future, make sure undo
|
# note: when adding revlog entries in the future, make sure undo
|
||||||
# code deletes the entries
|
# code deletes the entries
|
||||||
def _answerCardPreview(self, card: Card, ease: int) -> None:
|
def _answerCardPreview(self, card: Card, ease: int) -> None:
|
||||||
assert 1 <= ease <= 2
|
if not 1 <= ease <= 2:
|
||||||
|
raise Exception("invalid ease")
|
||||||
|
|
||||||
if ease == BUTTON_ONE:
|
if ease == BUTTON_ONE:
|
||||||
# repeat after delay
|
# repeat after delay
|
||||||
|
@ -799,7 +800,8 @@ limit ?"""
|
||||||
card.odid = DeckId(0)
|
card.odid = DeckId(0)
|
||||||
|
|
||||||
def _restorePreviewCard(self, card: Card) -> None:
|
def _restorePreviewCard(self, card: Card) -> None:
|
||||||
assert card.odid
|
if not card.odid:
|
||||||
|
raise Exception("card should have odid set")
|
||||||
|
|
||||||
card.due = card.odue
|
card.due = card.odue
|
||||||
|
|
||||||
|
@ -965,9 +967,12 @@ limit ?"""
|
||||||
|
|
||||||
# next interval for card when answered early+correctly
|
# next interval for card when answered early+correctly
|
||||||
def _earlyReviewIvl(self, card: Card, ease: int) -> int:
|
def _earlyReviewIvl(self, card: Card, ease: int) -> int:
|
||||||
assert card.odid and card.type == CARD_TYPE_REV
|
if (
|
||||||
assert card.factor
|
not (card.odid and card.type == CARD_TYPE_REV)
|
||||||
assert ease > 1
|
or not card.factor
|
||||||
|
or not ease > 1
|
||||||
|
):
|
||||||
|
raise Exception("invalid input to earlyReviewIvl")
|
||||||
|
|
||||||
elapsed = card.ivl - (card.odue - self.today)
|
elapsed = card.ivl - (card.odue - self.today)
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
||||||
elif rating == CardAnswer.EASY:
|
elif rating == CardAnswer.EASY:
|
||||||
new_state = states.easy
|
new_state = states.easy
|
||||||
else:
|
else:
|
||||||
assert False, "invalid rating"
|
raise Exception("invalid rating")
|
||||||
|
|
||||||
return CardAnswer(
|
return CardAnswer(
|
||||||
card_id=card.id,
|
card_id=card.id,
|
||||||
|
@ -157,7 +157,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
||||||
elif ease == BUTTON_FOUR:
|
elif ease == BUTTON_FOUR:
|
||||||
rating = CardAnswer.EASY
|
rating = CardAnswer.EASY
|
||||||
else:
|
else:
|
||||||
assert False, "invalid ease"
|
raise Exception("invalid ease")
|
||||||
|
|
||||||
states = self.col._backend.get_next_card_states(card.id)
|
states = self.col._backend.get_next_card_states(card.id)
|
||||||
changes = self.answer_card(
|
changes = self.answer_card(
|
||||||
|
@ -223,7 +223,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
||||||
elif ease == BUTTON_FOUR:
|
elif ease == BUTTON_FOUR:
|
||||||
new_state = states.easy
|
new_state = states.easy
|
||||||
else:
|
else:
|
||||||
assert False, "invalid ease"
|
raise Exception("invalid ease")
|
||||||
|
|
||||||
return self._interval_for_state(new_state)
|
return self._interval_for_state(new_state)
|
||||||
|
|
||||||
|
|
|
@ -267,7 +267,8 @@ class DeckConf(QDialog):
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
i = float(item)
|
i = float(item)
|
||||||
assert i > 0
|
if not i > 0:
|
||||||
|
raise Exception("0 invalid")
|
||||||
if i == int(i):
|
if i == int(i):
|
||||||
i = int(i)
|
i = int(i)
|
||||||
ret.append(i)
|
ret.append(i)
|
||||||
|
|
|
@ -333,7 +333,8 @@ class FilteredDeckConfigDialog(QDialog):
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
i = float(item)
|
i = float(item)
|
||||||
assert i > 0
|
if not i > 0:
|
||||||
|
raise Exception("0 invalid")
|
||||||
ret.append(i)
|
ret.append(i)
|
||||||
except:
|
except:
|
||||||
# invalid, don't update
|
# invalid, don't update
|
||||||
|
|
|
@ -608,7 +608,8 @@ class AnkiQt(QMainWindow):
|
||||||
|
|
||||||
def backup(self) -> None:
|
def backup(self) -> None:
|
||||||
"Read data into memory, and complete backup on a background thread."
|
"Read data into memory, and complete backup on a background thread."
|
||||||
assert not self.col or not self.col.db
|
if self.col and self.col.db:
|
||||||
|
raise Exception("collection must be closed")
|
||||||
|
|
||||||
nbacks = self.pm.profile["numBackups"]
|
nbacks = self.pm.profile["numBackups"]
|
||||||
if not nbacks or dev_mode:
|
if not nbacks or dev_mode:
|
||||||
|
@ -706,7 +707,8 @@ class AnkiQt(QMainWindow):
|
||||||
self._background_op_count -= 1
|
self._background_op_count -= 1
|
||||||
if not self._background_op_count:
|
if not self._background_op_count:
|
||||||
gui_hooks.backend_did_block()
|
gui_hooks.backend_did_block()
|
||||||
assert self._background_op_count >= 0
|
if not self._background_op_count >= 0:
|
||||||
|
raise Exception("no background ops active")
|
||||||
|
|
||||||
def _synthesize_op_did_execute_from_reset(self) -> None:
|
def _synthesize_op_did_execute_from_reset(self) -> None:
|
||||||
"""Fire the `operation_did_execute` hook with everything marked as changed,
|
"""Fire the `operation_did_execute` hook with everything marked as changed,
|
||||||
|
@ -1357,7 +1359,8 @@ title="{}" {}>{}</button>""".format(
|
||||||
|
|
||||||
# this will gradually be phased out
|
# this will gradually be phased out
|
||||||
def onSchemaMod(self, arg: bool) -> bool:
|
def onSchemaMod(self, arg: bool) -> bool:
|
||||||
assert self.inMainThread()
|
if not self.inMainThread():
|
||||||
|
raise Exception("not in main thread")
|
||||||
progress_shown = self.progress.busy()
|
progress_shown = self.progress.busy()
|
||||||
if progress_shown:
|
if progress_shown:
|
||||||
self.progress.finish()
|
self.progress.finish()
|
||||||
|
|
|
@ -199,7 +199,8 @@ class ProfileManager:
|
||||||
return pickle.dumps(obj, protocol=4)
|
return pickle.dumps(obj, protocol=4)
|
||||||
|
|
||||||
def load(self, name: str) -> bool:
|
def load(self, name: str) -> bool:
|
||||||
assert name != "_global"
|
if name == "_global":
|
||||||
|
raise Exception("_global is not a valid name")
|
||||||
data = self.db.scalar(
|
data = self.db.scalar(
|
||||||
"select cast(data as blob) from profiles where name = ?", name
|
"select cast(data as blob) from profiles where name = ?", name
|
||||||
)
|
)
|
||||||
|
@ -381,7 +382,8 @@ class ProfileManager:
|
||||||
# open DB file and read data
|
# open DB file and read data
|
||||||
try:
|
try:
|
||||||
self.db = DB(path)
|
self.db = DB(path)
|
||||||
assert self.db.scalar("pragma integrity_check") == "ok"
|
if not self.db.scalar("pragma integrity_check") == "ok":
|
||||||
|
raise Exception("corrupt db")
|
||||||
self.db.execute(
|
self.db.execute(
|
||||||
"""
|
"""
|
||||||
create table if not exists profiles
|
create table if not exists profiles
|
||||||
|
|
|
@ -88,7 +88,8 @@ def on_normal_sync_timer(mw: aqt.main.AnkiQt) -> None:
|
||||||
|
|
||||||
def sync_collection(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
def sync_collection(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
||||||
auth = mw.pm.sync_auth()
|
auth = mw.pm.sync_auth()
|
||||||
assert auth
|
if not auth:
|
||||||
|
raise Exception("expected auth")
|
||||||
|
|
||||||
def on_timer() -> None:
|
def on_timer() -> None:
|
||||||
on_normal_sync_timer(mw)
|
on_normal_sync_timer(mw)
|
||||||
|
|
|
@ -431,7 +431,8 @@ def getFile(
|
||||||
multi: bool = False, # controls whether a single or multiple files is returned
|
multi: bool = False, # controls whether a single or multiple files is returned
|
||||||
) -> Sequence[str] | str | None:
|
) -> Sequence[str] | str | None:
|
||||||
"Ask the user for a file."
|
"Ask the user for a file."
|
||||||
assert not dir or not key
|
if dir and key:
|
||||||
|
raise Exception("expected dir or key")
|
||||||
if not dir:
|
if not dir:
|
||||||
dirkey = f"{key}Directory"
|
dirkey = f"{key}Directory"
|
||||||
dir = aqt.mw.pm.profile.get(dirkey, "")
|
dir = aqt.mw.pm.profile.get(dirkey, "")
|
||||||
|
|
Loading…
Reference in a new issue