tweak the hook names in anki/

still a work in progress
This commit is contained in:
Damien Elmes 2020-01-15 16:43:22 +10:00
parent eb6723a2ee
commit b2f756f1b7
22 changed files with 412 additions and 406 deletions

View file

@ -87,7 +87,7 @@ class Card:
self.usn = self.col.usn() self.usn = self.col.usn()
# bug check # bug check
if self.queue == 2 and self.odue and not self.col.decks.isDyn(self.did): if self.queue == 2 and self.odue and not self.col.decks.isDyn(self.did):
hooks.odue_invalid_hook() hooks.card_odue_was_invalid_hook()
assert self.due < 4294967296 assert self.due < 4294967296
self.col.db.execute( self.col.db.execute(
""" """
@ -119,7 +119,7 @@ insert or replace into cards values
self.usn = self.col.usn() self.usn = self.col.usn()
# bug checks # bug checks
if self.queue == 2 and self.odue and not self.col.decks.isDyn(self.did): if self.queue == 2 and self.odue and not self.col.decks.isDyn(self.did):
hooks.odue_invalid_hook() hooks.card_odue_was_invalid_hook()
assert self.due < 4294967296 assert self.due < 4294967296
self.col.db.execute( self.col.db.execute(
"""update cards set """update cards set

View file

@ -272,7 +272,7 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""",
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."
if not self.schemaChanged(): if not self.schemaChanged():
if check and not hooks.mod_schema_filter(proceed=True): if check and not hooks.schema_will_change_filter(proceed=True):
raise AnkiError("abortSchemaMod") raise AnkiError("abortSchemaMod")
self.scm = intTime(1000) self.scm = intTime(1000)
self.setMod() self.setMod()
@ -372,7 +372,7 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""",
strids = ids2str(ids) strids = ids2str(ids)
# we need to log these independently of cards, as one side may have # we need to log these independently of cards, as one side may have
# more card templates # more card templates
hooks.remove_notes_hook(self, ids) hooks.notes_will_delete_hook(self, ids)
self._logRem(ids, REM_NOTE) self._logRem(ids, REM_NOTE)
self.db.execute("delete from notes where id in %s" % strids) self.db.execute("delete from notes where id in %s" % strids)
@ -665,12 +665,12 @@ where c.nid = n.id and c.id in %s group by nid"""
fields["c%d" % (card_ord + 1)] = "1" fields["c%d" % (card_ord + 1)] = "1"
# allow add-ons to modify the available fields # allow add-ons to modify the available fields
hooks.modify_fields_for_rendering_hook(fields, model, data) hooks.fields_will_render_hook(fields, model, data)
fields = runFilter("mungeFields", fields, model, data, self) # legacy fields = runFilter("mungeFields", fields, model, data, self) # legacy
# and the template prior to rendering # and the template prior to rendering
qfmt = hooks.original_card_template_filter(qfmt, True) qfmt = hooks.card_template_will_render_filter(qfmt, True)
afmt = hooks.original_card_template_filter(afmt, False) afmt = hooks.card_template_will_render_filter(afmt, False)
# render fields # render fields
qatext = render_card(self, qfmt, afmt, fields, card_ord) qatext = render_card(self, qfmt, afmt, fields, card_ord)
@ -678,7 +678,7 @@ where c.nid = n.id and c.id in %s group by nid"""
# allow add-ons to modify the generated result # allow add-ons to modify the generated result
for type in "q", "a": for type in "q", "a":
ret[type] = hooks.rendered_card_template_filter( ret[type] = hooks.card_template_did_render_filter(
ret[type], type, fields, model, data, self ret[type], type, fields, model, data, self
) )

View file

@ -165,7 +165,7 @@ class DeckManager:
self.decks[str(id)] = g self.decks[str(id)] = g
self.save(g) self.save(g)
self.maybeAddToActive() self.maybeAddToActive()
hooks.deck_created_hook(g) hooks.deck_did_create_hook(g)
return int(id) return int(id)
def rem(self, did: int, cardsToo: bool = False, childrenToo: bool = True) -> None: def rem(self, did: int, cardsToo: bool = False, childrenToo: bool = True) -> None:

View file

@ -347,7 +347,7 @@ class AnkiPackageExporter(AnkiExporter):
else: else:
z.write(mpath, cStr, zipfile.ZIP_STORED) z.write(mpath, cStr, zipfile.ZIP_STORED)
media[cStr] = unicodedata.normalize("NFC", file) media[cStr] = unicodedata.normalize("NFC", file)
hooks.exported_media_files_hook(c) hooks.media_files_did_export_hook(c)
return media return media
@ -417,5 +417,5 @@ def exporters() -> List[Tuple[str, Any]]:
id(TextNoteExporter), id(TextNoteExporter),
id(TextCardExporter), id(TextCardExporter),
] ]
hooks.create_exporters_list_hook(exps) hooks.exporters_list_did_create_hook(exps)
return exps return exps

View file

@ -40,7 +40,7 @@ class Finder:
flag=self._findFlag, flag=self._findFlag,
) )
self.search["is"] = self._findCardState self.search["is"] = self._findCardState
hooks.prepare_searches_hook(self.search) hooks.search_terms_did_prepare_hook(self.search)
def findCards(self, query, order=False) -> Any: def findCards(self, query, order=False) -> Any:
"Return a list of card ids for QUERY." "Return a list of card ids for QUERY."

View file

@ -25,167 +25,10 @@ from anki.types import QAData
# The code in this section is automatically generated - any edits you make # The code in this section is automatically generated - any edits you make
# will be lost. To add new hooks, see ../tools/genhooks.py # will be lost. To add new hooks, see ../tools/genhooks.py
# #
# To use an existing hook such as leech_hook, you would call the following
# in your code:
#
# from anki import hooks
# hooks.leech_hook.append(myfunc)
#
# @@AUTOGEN@@ # @@AUTOGEN@@
class _CreateExportersListHook: class _CardDidLeechHook:
_hooks: List[Callable[[List[Tuple[str, Any]]], None]] = []
def append(self, cb: Callable[[List[Tuple[str, Any]]], None]) -> None:
"""(exporters: List[Tuple[str, Any]])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[List[Tuple[str, Any]]], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, exporters: List[Tuple[str, Any]]) -> None:
for hook in self._hooks:
try:
hook(exporters)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("exportersList", exporters)
create_exporters_list_hook = _CreateExportersListHook()
class _DeckCreatedHook:
_hooks: List[Callable[[Dict[str, Any]], None]] = []
def append(self, cb: Callable[[Dict[str, Any]], None]) -> None:
"""(deck: Dict[str, Any])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[Dict[str, Any]], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, deck: Dict[str, Any]) -> None:
for hook in self._hooks:
try:
hook(deck)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("newDeck")
deck_created_hook = _DeckCreatedHook()
class _ExportedMediaFilesHook:
_hooks: List[Callable[[int], None]] = []
def append(self, cb: Callable[[int], None]) -> None:
"""(count: int)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[int], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, count: int) -> None:
for hook in self._hooks:
try:
hook(count)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
exported_media_files_hook = _ExportedMediaFilesHook()
class _FieldReplacementFilter:
_hooks: List[Callable[[str, str, str, Dict[str, str]], str]] = []
def append(self, cb: Callable[[str, str, str, Dict[str, str]], str]) -> None:
"""(field_text: str, field_name: str, filter_name: str, fields: Dict[str, str])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[str, str, str, Dict[str, str]], str]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(
self, field_text: str, field_name: str, filter_name: str, fields: Dict[str, str]
) -> str:
for filter in self._hooks:
try:
field_text = filter(field_text, field_name, filter_name, fields)
except:
# if the hook fails, remove it
self._hooks.remove(filter)
raise
return field_text
field_replacement_filter = _FieldReplacementFilter()
class _HttpDataReceivedHook:
_hooks: List[Callable[[int], None]] = []
def append(self, cb: Callable[[int], None]) -> None:
"""(bytes: int)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[int], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, bytes: int) -> None:
for hook in self._hooks:
try:
hook(bytes)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
http_data_received_hook = _HttpDataReceivedHook()
class _HttpDataSentHook:
_hooks: List[Callable[[int], None]] = []
def append(self, cb: Callable[[int], None]) -> None:
"""(bytes: int)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[int], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, bytes: int) -> None:
for hook in self._hooks:
try:
hook(bytes)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
http_data_sent_hook = _HttpDataSentHook()
class _LeechHook:
_hooks: List[Callable[[Card], None]] = [] _hooks: List[Callable[[Card], None]] = []
def append(self, cb: Callable[[Card], None]) -> None: def append(self, cb: Callable[[Card], None]) -> None:
@ -208,91 +51,10 @@ class _LeechHook:
runHook("leech", card) runHook("leech", card)
leech_hook = _LeechHook() card_did_leech_hook = _CardDidLeechHook()
class _ModSchemaFilter: class _CardOdueWasInvalidHook:
_hooks: List[Callable[[bool], bool]] = []
def append(self, cb: Callable[[bool], bool]) -> None:
"""(proceed: bool)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[bool], bool]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, proceed: bool) -> bool:
for filter in self._hooks:
try:
proceed = filter(proceed)
except:
# if the hook fails, remove it
self._hooks.remove(filter)
raise
return proceed
mod_schema_filter = _ModSchemaFilter()
class _ModifyFieldsForRenderingHook:
_hooks: List[Callable[[Dict[str, str], Dict[str, Any], QAData], None]] = []
def append(
self, cb: Callable[[Dict[str, str], Dict[str, Any], QAData], None]
) -> None:
"""(fields: Dict[str, str], notetype: Dict[str, Any], data: QAData)"""
self._hooks.append(cb)
def remove(
self, cb: Callable[[Dict[str, str], Dict[str, Any], QAData], None]
) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(
self, fields: Dict[str, str], notetype: Dict[str, Any], data: QAData
) -> None:
for hook in self._hooks:
try:
hook(fields, notetype, data)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
modify_fields_for_rendering_hook = _ModifyFieldsForRenderingHook()
class _NoteTypeCreatedHook:
_hooks: List[Callable[[Dict[str, Any]], None]] = []
def append(self, cb: Callable[[Dict[str, Any]], None]) -> None:
"""(notetype: Dict[str, Any])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[Dict[str, Any]], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, notetype: Dict[str, Any]) -> None:
for hook in self._hooks:
try:
hook(notetype)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("newModel")
note_type_created_hook = _NoteTypeCreatedHook()
class _OdueInvalidHook:
_hooks: List[Callable[[], None]] = [] _hooks: List[Callable[[], None]] = []
def append(self, cb: Callable[[], None]) -> None: def append(self, cb: Callable[[], None]) -> None:
@ -313,91 +75,12 @@ class _OdueInvalidHook:
raise raise
odue_invalid_hook = _OdueInvalidHook() card_odue_was_invalid_hook = _CardOdueWasInvalidHook()
class _OriginalCardTemplateFilter: class _CardTemplateDidRenderFilter:
_hooks: List[Callable[[str, bool], str]] = [] """Can modify the resulting text after rendering completes."""
def append(self, cb: Callable[[str, bool], str]) -> None:
"""(template: str, question_side: bool)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[str, bool], str]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, template: str, question_side: bool) -> str:
for filter in self._hooks:
try:
template = filter(template, question_side)
except:
# if the hook fails, remove it
self._hooks.remove(filter)
raise
return template
original_card_template_filter = _OriginalCardTemplateFilter()
class _PrepareSearchesHook:
_hooks: List[Callable[[Dict[str, Callable]], None]] = []
def append(self, cb: Callable[[Dict[str, Callable]], None]) -> None:
"""(searches: Dict[str, Callable])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[Dict[str, Callable]], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, searches: Dict[str, Callable]) -> None:
for hook in self._hooks:
try:
hook(searches)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("search", searches)
prepare_searches_hook = _PrepareSearchesHook()
class _RemoveNotesHook:
_hooks: List[Callable[["anki.storage._Collection", List[int]], None]] = []
def append(
self, cb: Callable[["anki.storage._Collection", List[int]], None]
) -> None:
"""(col: anki.storage._Collection, ids: List[int])"""
self._hooks.append(cb)
def remove(
self, cb: Callable[["anki.storage._Collection", List[int]], None]
) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, col: anki.storage._Collection, ids: List[int]) -> None:
for hook in self._hooks:
try:
hook(col, ids)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("remNotes", col, ids)
remove_notes_hook = _RemoveNotesHook()
class _RenderedCardTemplateFilter:
_hooks: List[ _hooks: List[
Callable[ Callable[
[ [
@ -467,10 +150,327 @@ class _RenderedCardTemplateFilter:
return text return text
rendered_card_template_filter = _RenderedCardTemplateFilter() card_template_did_render_filter = _CardTemplateDidRenderFilter()
class _SyncProgressMessageHook: class _CardTemplateFilterWillApplyFilter:
_hooks: List[Callable[[str, str, str, Dict[str, str]], str]] = []
def append(self, cb: Callable[[str, str, str, Dict[str, str]], str]) -> None:
"""(field_text: str, field_name: str, filter_name: str, fields: Dict[str, str])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[str, str, str, Dict[str, str]], str]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(
self, field_text: str, field_name: str, filter_name: str, fields: Dict[str, str]
) -> str:
for filter in self._hooks:
try:
field_text = filter(field_text, field_name, filter_name, fields)
except:
# if the hook fails, remove it
self._hooks.remove(filter)
raise
return field_text
card_template_filter_will_apply_filter = _CardTemplateFilterWillApplyFilter()
class _CardTemplateWillRenderFilter:
"""Can modify the the card template used for rendering."""
_hooks: List[Callable[[str, bool], str]] = []
def append(self, cb: Callable[[str, bool], str]) -> None:
"""(template: str, question_side: bool)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[str, bool], str]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, template: str, question_side: bool) -> str:
for filter in self._hooks:
try:
template = filter(template, question_side)
except:
# if the hook fails, remove it
self._hooks.remove(filter)
raise
return template
card_template_will_render_filter = _CardTemplateWillRenderFilter()
class _DeckDidCreateHook:
_hooks: List[Callable[[Dict[str, Any]], None]] = []
def append(self, cb: Callable[[Dict[str, Any]], None]) -> None:
"""(deck: Dict[str, Any])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[Dict[str, Any]], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, deck: Dict[str, Any]) -> None:
for hook in self._hooks:
try:
hook(deck)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("newDeck")
deck_did_create_hook = _DeckDidCreateHook()
class _ExportersListDidCreateHook:
_hooks: List[Callable[[List[Tuple[str, Any]]], None]] = []
def append(self, cb: Callable[[List[Tuple[str, Any]]], None]) -> None:
"""(exporters: List[Tuple[str, Any]])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[List[Tuple[str, Any]]], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, exporters: List[Tuple[str, Any]]) -> None:
for hook in self._hooks:
try:
hook(exporters)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("exportersList", exporters)
exporters_list_did_create_hook = _ExportersListDidCreateHook()
class _FieldsWillRenderHook:
"""Can modify the available fields prior to rendering."""
_hooks: List[Callable[[Dict[str, str], Dict[str, Any], QAData], None]] = []
def append(
self, cb: Callable[[Dict[str, str], Dict[str, Any], QAData], None]
) -> None:
"""(fields: Dict[str, str], notetype: Dict[str, Any], data: QAData)"""
self._hooks.append(cb)
def remove(
self, cb: Callable[[Dict[str, str], Dict[str, Any], QAData], None]
) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(
self, fields: Dict[str, str], notetype: Dict[str, Any], data: QAData
) -> None:
for hook in self._hooks:
try:
hook(fields, notetype, data)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
fields_will_render_hook = _FieldsWillRenderHook()
class _HttpDataDidReceiveHook:
_hooks: List[Callable[[int], None]] = []
def append(self, cb: Callable[[int], None]) -> None:
"""(bytes: int)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[int], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, bytes: int) -> None:
for hook in self._hooks:
try:
hook(bytes)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
http_data_did_receive_hook = _HttpDataDidReceiveHook()
class _HttpDataDidSendHook:
_hooks: List[Callable[[int], None]] = []
def append(self, cb: Callable[[int], None]) -> None:
"""(bytes: int)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[int], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, bytes: int) -> None:
for hook in self._hooks:
try:
hook(bytes)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
http_data_did_send_hook = _HttpDataDidSendHook()
class _MediaFilesDidExportHook:
_hooks: List[Callable[[int], None]] = []
def append(self, cb: Callable[[int], None]) -> None:
"""(count: int)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[int], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, count: int) -> None:
for hook in self._hooks:
try:
hook(count)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
media_files_did_export_hook = _MediaFilesDidExportHook()
class _NoteTypeDidCreateHook:
_hooks: List[Callable[[Dict[str, Any]], None]] = []
def append(self, cb: Callable[[Dict[str, Any]], None]) -> None:
"""(notetype: Dict[str, Any])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[Dict[str, Any]], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, notetype: Dict[str, Any]) -> None:
for hook in self._hooks:
try:
hook(notetype)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("newModel")
note_type_did_create_hook = _NoteTypeDidCreateHook()
class _NotesWillDeleteHook:
_hooks: List[Callable[["anki.storage._Collection", List[int]], None]] = []
def append(
self, cb: Callable[["anki.storage._Collection", List[int]], None]
) -> None:
"""(col: anki.storage._Collection, ids: List[int])"""
self._hooks.append(cb)
def remove(
self, cb: Callable[["anki.storage._Collection", List[int]], None]
) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, col: anki.storage._Collection, ids: List[int]) -> None:
for hook in self._hooks:
try:
hook(col, ids)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("remNotes", col, ids)
notes_will_delete_hook = _NotesWillDeleteHook()
class _SchemaWillChangeFilter:
_hooks: List[Callable[[bool], bool]] = []
def append(self, cb: Callable[[bool], bool]) -> None:
"""(proceed: bool)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[bool], bool]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, proceed: bool) -> bool:
for filter in self._hooks:
try:
proceed = filter(proceed)
except:
# if the hook fails, remove it
self._hooks.remove(filter)
raise
return proceed
schema_will_change_filter = _SchemaWillChangeFilter()
class _SearchTermsDidPrepareHook:
_hooks: List[Callable[[Dict[str, Callable]], None]] = []
def append(self, cb: Callable[[Dict[str, Callable]], None]) -> None:
"""(searches: Dict[str, Callable])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[Dict[str, Callable]], None]) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(self, searches: Dict[str, Callable]) -> None:
for hook in self._hooks:
try:
hook(searches)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("search", searches)
search_terms_did_prepare_hook = _SearchTermsDidPrepareHook()
class _SyncProgressDidChangeHook:
_hooks: List[Callable[[str], None]] = [] _hooks: List[Callable[[str], None]] = []
def append(self, cb: Callable[[str], None]) -> None: def append(self, cb: Callable[[str], None]) -> None:
@ -493,10 +493,10 @@ class _SyncProgressMessageHook:
runHook("syncMsg", msg) runHook("syncMsg", msg)
sync_progress_message_hook = _SyncProgressMessageHook() sync_progress_did_change_hook = _SyncProgressDidChangeHook()
class _SyncStageHook: class _SyncStageDidChangeHook:
_hooks: List[Callable[[str], None]] = [] _hooks: List[Callable[[str], None]] = []
def append(self, cb: Callable[[str], None]) -> None: def append(self, cb: Callable[[str], None]) -> None:
@ -519,10 +519,10 @@ class _SyncStageHook:
runHook("sync", stage) runHook("sync", stage)
sync_stage_hook = _SyncStageHook() sync_stage_did_change_hook = _SyncStageDidChangeHook()
class _TagCreatedHook: class _TagDidCreateHook:
_hooks: List[Callable[[str], None]] = [] _hooks: List[Callable[[str], None]] = []
def append(self, cb: Callable[[str], None]) -> None: def append(self, cb: Callable[[str], None]) -> None:
@ -545,7 +545,7 @@ class _TagCreatedHook:
runHook("newTag") runHook("newTag")
tag_created_hook = _TagCreatedHook() tag_did_create_hook = _TagDidCreateHook()
# @@AUTOGEN@@ # @@AUTOGEN@@
# Legacy hook handling # Legacy hook handling

View file

@ -184,4 +184,4 @@ def _errMsg(type: str, texpath: str) -> Any:
# setup q/a filter - type ignored due to import cycle # setup q/a filter - type ignored due to import cycle
hooks.rendered_card_template_filter.append(mungeQA) # type: ignore hooks.card_template_did_render_filter.append(mungeQA) # type: ignore

View file

@ -107,7 +107,7 @@ class ModelManager:
if templates: if templates:
self._syncTemplates(m) self._syncTemplates(m)
self.changed = True self.changed = True
hooks.note_type_created_hook(m) hooks.note_type_did_create_hook(m)
def flush(self) -> None: def flush(self) -> None:
"Flush the registry if any models were changed." "Flush the registry if any models were changed."

View file

@ -1150,7 +1150,7 @@ did = ?, queue = %s, due = ?, usn = ? where id = ?"""
card.odue = card.odid = 0 card.odue = card.odid = 0
card.queue = -1 card.queue = -1
# notify UI # notify UI
hooks.leech_hook(card) hooks.card_did_leech_hook(card)
return True return True
# Tools # Tools

View file

@ -1270,7 +1270,7 @@ where id = ?
if a == 0: if a == 0:
card.queue = -1 card.queue = -1
# notify UI # notify UI
hooks.leech_hook(card) hooks.card_did_leech_hook(card)
return True return True
return None return None

View file

@ -55,7 +55,7 @@ class Syncer:
self.col.save() self.col.save()
# step 1: login & metadata # step 1: login & metadata
hooks.sync_stage_hook("login") hooks.sync_stage_did_change_hook("login")
meta = self.server.meta() meta = self.server.meta()
self.col.log("rmeta", meta) self.col.log("rmeta", meta)
if not meta: if not meta:
@ -95,7 +95,7 @@ class Syncer:
self.col.log("basic check") self.col.log("basic check")
return "basicCheckFailed" return "basicCheckFailed"
# step 2: startup and deletions # step 2: startup and deletions
hooks.sync_stage_hook("meta") hooks.sync_stage_did_change_hook("meta")
rrem = self.server.start( rrem = self.server.start(
minUsn=self.minUsn, lnewer=self.lnewer, offset=self.col.localOffset() minUsn=self.minUsn, lnewer=self.lnewer, offset=self.col.localOffset()
) )
@ -118,31 +118,31 @@ class Syncer:
self.server.abort() self.server.abort()
return self._forceFullSync() return self._forceFullSync()
# step 3: stream large tables from server # step 3: stream large tables from server
hooks.sync_stage_hook("server") hooks.sync_stage_did_change_hook("server")
while 1: while 1:
hooks.sync_stage_hook("stream") hooks.sync_stage_did_change_hook("stream")
chunk = self.server.chunk() chunk = self.server.chunk()
self.col.log("server chunk", chunk) self.col.log("server chunk", chunk)
self.applyChunk(chunk=chunk) self.applyChunk(chunk=chunk)
if chunk["done"]: if chunk["done"]:
break break
# step 4: stream to server # step 4: stream to server
hooks.sync_stage_hook("client") hooks.sync_stage_did_change_hook("client")
while 1: while 1:
hooks.sync_stage_hook("stream") hooks.sync_stage_did_change_hook("stream")
chunk = self.chunk() chunk = self.chunk()
self.col.log("client chunk", chunk) self.col.log("client chunk", chunk)
self.server.applyChunk(chunk=chunk) self.server.applyChunk(chunk=chunk)
if chunk["done"]: if chunk["done"]:
break break
# step 5: sanity check # step 5: sanity check
hooks.sync_stage_hook("sanity") hooks.sync_stage_did_change_hook("sanity")
c = self.sanityCheck() c = self.sanityCheck()
ret = self.server.sanityCheck2(client=c) ret = self.server.sanityCheck2(client=c)
if ret["status"] != "ok": if ret["status"] != "ok":
return self._forceFullSync() return self._forceFullSync()
# finalize # finalize
hooks.sync_stage_hook("finalize") hooks.sync_stage_did_change_hook("finalize")
mod = self.server.finish() mod = self.server.finish()
self.finish(mod) self.finish(mod)
return "success" return "success"
@ -501,7 +501,7 @@ class AnkiRequestsClient:
buf = io.BytesIO() buf = io.BytesIO()
for chunk in resp.iter_content(chunk_size=HTTP_BUF_SIZE): for chunk in resp.iter_content(chunk_size=HTTP_BUF_SIZE):
hooks.http_data_received_hook(len(chunk)) hooks.http_data_did_receive_hook(len(chunk))
buf.write(chunk) buf.write(chunk)
return buf.getvalue() return buf.getvalue()
@ -523,7 +523,7 @@ if os.environ.get("ANKI_NOVERIFYSSL"):
class _MonitoringFile(io.BufferedReader): class _MonitoringFile(io.BufferedReader):
def read(self, size=-1) -> bytes: def read(self, size=-1) -> bytes:
data = io.BufferedReader.read(self, HTTP_BUF_SIZE) data = io.BufferedReader.read(self, HTTP_BUF_SIZE)
hooks.http_data_sent_hook(len(data)) hooks.http_data_did_send_hook(len(data))
return data return data
@ -707,13 +707,13 @@ class FullSyncer(HttpSyncer):
self.col = col self.col = col
def download(self) -> Optional[str]: def download(self) -> Optional[str]:
hooks.sync_stage_hook("download") hooks.sync_stage_did_change_hook("download")
localNotEmpty = self.col.db.scalar("select 1 from cards") localNotEmpty = self.col.db.scalar("select 1 from cards")
self.col.close() self.col.close()
cont = self.req("download") cont = self.req("download")
tpath = self.col.path + ".tmp" tpath = self.col.path + ".tmp"
if cont == "upgradeRequired": if cont == "upgradeRequired":
hooks.sync_stage_hook("upgradeRequired") hooks.sync_stage_did_change_hook("upgradeRequired")
return None return None
open(tpath, "wb").write(cont) open(tpath, "wb").write(cont)
# check the received file is ok # check the received file is ok
@ -733,7 +733,7 @@ class FullSyncer(HttpSyncer):
def upload(self) -> bool: def upload(self) -> bool:
"True if upload successful." "True if upload successful."
hooks.sync_stage_hook("upload") hooks.sync_stage_did_change_hook("upload")
# make sure it's ok before we try to upload # make sure it's ok before we try to upload
if self.col.db.scalar("pragma integrity_check") != "ok": if self.col.db.scalar("pragma integrity_check") != "ok":
return False return False
@ -765,7 +765,7 @@ class MediaSyncer:
def sync(self) -> Any: def sync(self) -> Any:
# check if there have been any changes # check if there have been any changes
hooks.sync_stage_hook("findMedia") hooks.sync_stage_did_change_hook("findMedia")
self.col.log("findChanges") self.col.log("findChanges")
try: try:
self.col.media.findChanges() self.col.media.findChanges()
@ -835,7 +835,7 @@ class MediaSyncer:
if not fnames: if not fnames:
break break
hooks.sync_progress_message_hook( hooks.sync_progress_did_change_hook(
ngettext( ngettext(
"%d media change to upload", "%d media changes to upload", toSend "%d media change to upload", "%d media changes to upload", toSend
) )
@ -886,7 +886,7 @@ class MediaSyncer:
fnames = fnames[cnt:] fnames = fnames[cnt:]
n = self.downloadCount n = self.downloadCount
hooks.sync_progress_message_hook( hooks.sync_progress_did_change_hook(
ngettext("%d media file downloaded", "%d media files downloaded", n) ngettext("%d media file downloaded", "%d media files downloaded", n)
% n, % n,
) )

View file

@ -50,7 +50,7 @@ class TagManager:
self.tags[t] = self.col.usn() if usn is None else usn self.tags[t] = self.col.usn() if usn is None else usn
self.changed = True self.changed = True
if found: if found:
hooks.tag_created_hook(t) # pylint: disable=undefined-loop-variable hooks.tag_did_create_hook(t) # pylint: disable=undefined-loop-variable
def all(self) -> List: def all(self) -> List:
return list(self.tags.keys()) return list(self.tags.keys())

View file

@ -72,7 +72,7 @@ def apply_custom_filters(
field_text = node.current_text field_text = node.current_text
for filter_name in node.filters: for filter_name in node.filters:
field_text = hooks.field_replacement_filter( field_text = hooks.card_template_filter_will_apply_filter(
field_text, node.field_name, filter_name, fields field_text, node.field_name, filter_name, fields
) )
# legacy hook - the second and fifth argument are no longer used # legacy hook - the second and fifth argument are no longer used

View file

@ -373,7 +373,7 @@ def test_reviews():
def onLeech(card): def onLeech(card):
hooked.append(1) hooked.append(1)
hooks.leech_hook.append(onLeech) hooks.card_did_leech_hook.append(onLeech)
d.sched.answerCard(c, 1) d.sched.answerCard(c, 1)
assert hooked assert hooked
assert c.queue == -1 assert c.queue == -1

View file

@ -395,7 +395,7 @@ def test_reviews():
def onLeech(card): def onLeech(card):
hooked.append(1) hooked.append(1)
hooks.leech_hook.append(onLeech) hooks.card_did_leech_hook.append(onLeech)
d.sched.answerCard(c, 1) d.sched.answerCard(c, 1)
assert hooked assert hooked
assert c.queue == -1 assert c.queue == -1

View file

@ -17,55 +17,60 @@ from hookslib import Hook, update_file
###################################################################### ######################################################################
hooks = [ hooks = [
Hook(name="leech", args=["card: Card"], legacy_hook="leech"), Hook(name="card_did_leech", args=["card: Card"], legacy_hook="leech"),
Hook(name="odue_invalid"), Hook(name="card_odue_was_invalid"),
Hook(name="mod_schema", args=["proceed: bool"], return_type="bool"), Hook(name="schema_will_change", args=["proceed: bool"], return_type="bool"),
Hook( Hook(
name="remove_notes", name="notes_will_delete",
args=["col: anki.storage._Collection", "ids: List[int]"], args=["col: anki.storage._Collection", "ids: List[int]"],
legacy_hook="remNotes", legacy_hook="remNotes",
), ),
Hook( Hook(
name="deck_created", name="deck_did_create",
args=["deck: Dict[str, Any]"], args=["deck: Dict[str, Any]"],
legacy_hook="newDeck", legacy_hook="newDeck",
legacy_no_args=True, legacy_no_args=True,
), ),
Hook(name="exported_media_files", args=["count: int"]), Hook(name="media_files_did_export", args=["count: int"]),
Hook( Hook(
name="create_exporters_list", name="exporters_list_did_create",
args=["exporters: List[Tuple[str, Any]]"], args=["exporters: List[Tuple[str, Any]]"],
legacy_hook="exportersList", legacy_hook="exportersList",
), ),
Hook( Hook(
name="prepare_searches", name="search_terms_did_prepare",
args=["searches: Dict[str, Callable]"], args=["searches: Dict[str, Callable]"],
legacy_hook="search", legacy_hook="search",
), ),
Hook( Hook(
name="note_type_created", name="note_type_did_create",
args=["notetype: Dict[str, Any]"], args=["notetype: Dict[str, Any]"],
legacy_hook="newModel", legacy_hook="newModel",
legacy_no_args=True, legacy_no_args=True,
), ),
Hook(name="sync_stage", args=["stage: str"], legacy_hook="sync"), Hook(name="sync_stage_did_change", args=["stage: str"], legacy_hook="sync"),
Hook(name="sync_progress_message", args=["msg: str"], legacy_hook="syncMsg"), Hook(name="sync_progress_did_change", args=["msg: str"], legacy_hook="syncMsg"),
Hook(name="http_data_sent", args=["bytes: int"]), Hook(name="http_data_did_send", args=["bytes: int"]),
Hook(name="http_data_received", args=["bytes: int"]), Hook(name="http_data_did_receive", args=["bytes: int"]),
Hook( Hook(
name="tag_created", args=["tag: str"], legacy_hook="newTag", legacy_no_args=True name="tag_did_create",
args=["tag: str"],
legacy_hook="newTag",
legacy_no_args=True,
), ),
Hook( Hook(
name="modify_fields_for_rendering", name="fields_will_render",
args=["fields: Dict[str, str]", "notetype: Dict[str, Any]", "data: QAData",], args=["fields: Dict[str, str]", "notetype: Dict[str, Any]", "data: QAData",],
doc="Can modify the available fields prior to rendering.",
), ),
Hook( Hook(
name="original_card_template", name="card_template_will_render",
args=["template: str", "question_side: bool"], args=["template: str", "question_side: bool"],
return_type="str", return_type="str",
doc="Can modify the the card template used for rendering.",
), ),
Hook( Hook(
name="rendered_card_template", name="card_template_did_render",
args=[ args=[
"text: str", "text: str",
"side: str", "side: str",
@ -78,9 +83,10 @@ hooks = [
], ],
return_type="str", return_type="str",
legacy_hook="mungeQA", legacy_hook="mungeQA",
doc="Can modify the resulting text after rendering completes.",
), ),
Hook( Hook(
name="field_replacement", name="card_template_filter_will_apply",
args=[ args=[
"field_text: str", "field_text: str",
"field_name: str", "field_name: str",

View file

@ -2025,9 +2025,9 @@ update cards set usn=?, mod=?, did=? where id in """
gui_hooks.editor_typing_timer_did_fire_hook.append(self.refreshCurrentCard) gui_hooks.editor_typing_timer_did_fire_hook.append(self.refreshCurrentCard)
gui_hooks.editor_note_did_load_hook.append(self.onLoadNote) gui_hooks.editor_note_did_load_hook.append(self.onLoadNote)
gui_hooks.editor_field_did_lose_focus_filter.append(self.refreshCurrentCard) gui_hooks.editor_field_did_lose_focus_filter.append(self.refreshCurrentCard)
hooks.tag_created_hook.append(self.maybeRefreshSidebar) hooks.tag_did_create_hook.append(self.maybeRefreshSidebar)
hooks.note_type_created_hook.append(self.maybeRefreshSidebar) hooks.note_type_did_create_hook.append(self.maybeRefreshSidebar)
hooks.deck_created_hook.append(self.maybeRefreshSidebar) hooks.deck_did_create_hook.append(self.maybeRefreshSidebar)
def teardownHooks(self): def teardownHooks(self):
gui_hooks.undo_state_did_change_hook.remove(self.onUndoState) gui_hooks.undo_state_did_change_hook.remove(self.onUndoState)
@ -2035,9 +2035,9 @@ update cards set usn=?, mod=?, did=? where id in """
gui_hooks.editor_typing_timer_did_fire_hook.remove(self.refreshCurrentCard) gui_hooks.editor_typing_timer_did_fire_hook.remove(self.refreshCurrentCard)
gui_hooks.editor_note_did_load_hook.remove(self.onLoadNote) gui_hooks.editor_note_did_load_hook.remove(self.onLoadNote)
gui_hooks.editor_field_did_lose_focus_filter.remove(self.refreshCurrentCard) gui_hooks.editor_field_did_lose_focus_filter.remove(self.refreshCurrentCard)
hooks.tag_created_hook.remove(self.maybeRefreshSidebar) hooks.tag_did_create_hook.remove(self.maybeRefreshSidebar)
hooks.note_type_created_hook.remove(self.maybeRefreshSidebar) hooks.note_type_did_create_hook.remove(self.maybeRefreshSidebar)
hooks.deck_created_hook.remove(self.maybeRefreshSidebar) hooks.deck_did_create_hook.remove(self.maybeRefreshSidebar)
def onUndoState(self, on): def onUndoState(self, on):
self.form.actionUndo.setEnabled(on) self.form.actionUndo.setEnabled(on)

View file

@ -57,7 +57,7 @@ class Downloader(QThread):
self.recvTotal += bytes self.recvTotal += bytes
self.recv.emit() self.recv.emit()
hooks.http_data_received_hook.append(recvEvent) hooks.http_data_did_receive_hook.append(recvEvent)
client = AnkiRequestsClient() client = AnkiRequestsClient()
try: try:
resp = client.get(aqt.appShared + "download/%s?v=2.1" % self.code) resp = client.get(aqt.appShared + "download/%s?v=2.1" % self.code)
@ -75,7 +75,7 @@ class Downloader(QThread):
self.error = _("Please check your internet connection.") + "\n\n" + str(e) self.error = _("Please check your internet connection.") + "\n\n" + str(e)
return return
finally: finally:
hooks.http_data_received_hook.remove(recvEvent) hooks.http_data_did_receive_hook.remove(recvEvent)
self.fname = re.match( self.fname = re.match(
"attachment; filename=(.+)", resp.headers["content-disposition"] "attachment; filename=(.+)", resp.headers["content-disposition"]

View file

@ -132,9 +132,9 @@ class ExportDialog(QDialog):
) )
% cnt % cnt
) )
hooks.exported_media_files_hook.append(exportedMedia) hooks.media_files_did_export_hook.append(exportedMedia)
self.exporter.exportInto(file) self.exporter.exportInto(file)
hooks.exported_media_files_hook.remove(exportedMedia) hooks.media_files_did_export_hook.remove(exportedMedia)
period = 3000 period = 3000
if self.isVerbatim: if self.isVerbatim:
msg = _("Collection exported.") msg = _("Collection exported.")

View file

@ -1153,9 +1153,9 @@ Difference to correct time: %s."""
########################################################################## ##########################################################################
def setupHooks(self) -> None: def setupHooks(self) -> None:
hooks.mod_schema_filter.append(self.onSchemaMod) hooks.schema_will_change_filter.append(self.onSchemaMod)
hooks.remove_notes_hook.append(self.onRemNotes) hooks.notes_will_delete_hook.append(self.onRemNotes)
hooks.odue_invalid_hook.append(self.onOdueInvalid) hooks.card_odue_was_invalid_hook.append(self.onOdueInvalid)
gui_hooks.mpv_will_play_hook.append(self.on_mpv_will_play) gui_hooks.mpv_will_play_hook.append(self.on_mpv_will_play)
gui_hooks.mpv_did_idle_hook.append(self.on_mpv_idle) gui_hooks.mpv_did_idle_hook.append(self.on_mpv_idle)

View file

@ -41,7 +41,7 @@ class Reviewer:
self.typeCorrect = None # web init happens before this is set self.typeCorrect = None # web init happens before this is set
self.state = None self.state = None
self.bottom = aqt.toolbar.BottomBar(mw, mw.bottomWeb) self.bottom = aqt.toolbar.BottomBar(mw, mw.bottomWeb)
hooks.leech_hook.append(self.onLeech) hooks.card_did_leech_hook.append(self.onLeech)
def show(self): def show(self):
self.mw.col.reset() self.mw.col.reset()

View file

@ -406,10 +406,10 @@ class SyncThread(QThread):
self._abort = 2 self._abort = 2
raise Exception("sync cancelled") raise Exception("sync cancelled")
hooks.sync_stage_hook.append(syncEvent) hooks.sync_stage_did_change_hook.append(syncEvent)
hooks.sync_progress_message_hook.append(syncMsg) hooks.sync_progress_did_change_hook.append(syncMsg)
hooks.http_data_sent_hook.append(sendEvent) hooks.http_data_did_send_hook.append(sendEvent)
hooks.http_data_received_hook.append(recvEvent) hooks.http_data_did_receive_hook.append(recvEvent)
# run sync and catch any errors # run sync and catch any errors
try: try:
self._sync() self._sync()
@ -419,10 +419,10 @@ class SyncThread(QThread):
finally: finally:
# don't bump mod time unless we explicitly save # don't bump mod time unless we explicitly save
self.col.close(save=False) self.col.close(save=False)
hooks.sync_stage_hook.remove(syncEvent) hooks.sync_stage_did_change_hook.remove(syncEvent)
hooks.sync_progress_message_hook.remove(syncMsg) hooks.sync_progress_did_change_hook.remove(syncMsg)
hooks.http_data_sent_hook.remove(sendEvent) hooks.http_data_did_send_hook.remove(sendEvent)
hooks.http_data_received_hook.remove(recvEvent) hooks.http_data_did_receive_hook.remove(recvEvent)
def _abortingSync(self): def _abortingSync(self):
try: try: