From b2f756f1b7b58d70c511330fb442485a8c505d26 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Wed, 15 Jan 2020 16:43:22 +1000 Subject: [PATCH] tweak the hook names in anki/ still a work in progress --- pylib/anki/cards.py | 4 +- pylib/anki/collection.py | 12 +- pylib/anki/decks.py | 2 +- pylib/anki/exporting.py | 4 +- pylib/anki/find.py | 2 +- pylib/anki/hooks.py | 660 ++++++++++++++++++------------------ pylib/anki/latex.py | 2 +- pylib/anki/models.py | 2 +- pylib/anki/sched.py | 2 +- pylib/anki/schedv2.py | 2 +- pylib/anki/sync.py | 32 +- pylib/anki/tags.py | 2 +- pylib/anki/template.py | 2 +- pylib/tests/test_schedv1.py | 2 +- pylib/tests/test_schedv2.py | 2 +- pylib/tools/genhooks.py | 42 ++- qt/aqt/browser.py | 12 +- qt/aqt/downloader.py | 4 +- qt/aqt/exporting.py | 4 +- qt/aqt/main.py | 6 +- qt/aqt/reviewer.py | 2 +- qt/aqt/sync.py | 16 +- 22 files changed, 412 insertions(+), 406 deletions(-) diff --git a/pylib/anki/cards.py b/pylib/anki/cards.py index 1edc9733a..d477bd5c1 100644 --- a/pylib/anki/cards.py +++ b/pylib/anki/cards.py @@ -87,7 +87,7 @@ class Card: self.usn = self.col.usn() # bug check 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 self.col.db.execute( """ @@ -119,7 +119,7 @@ insert or replace into cards values self.usn = self.col.usn() # bug checks 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 self.col.db.execute( """update cards set diff --git a/pylib/anki/collection.py b/pylib/anki/collection.py index 9113bb54f..66eea91ef 100644 --- a/pylib/anki/collection.py +++ b/pylib/anki/collection.py @@ -272,7 +272,7 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""", def modSchema(self, check: bool) -> None: "Mark schema modified. Call this first so user can abort if necessary." 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") self.scm = intTime(1000) self.setMod() @@ -372,7 +372,7 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""", strids = ids2str(ids) # we need to log these independently of cards, as one side may have # more card templates - hooks.remove_notes_hook(self, ids) + hooks.notes_will_delete_hook(self, ids) self._logRem(ids, REM_NOTE) 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" # 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 # and the template prior to rendering - qfmt = hooks.original_card_template_filter(qfmt, True) - afmt = hooks.original_card_template_filter(afmt, False) + qfmt = hooks.card_template_will_render_filter(qfmt, True) + afmt = hooks.card_template_will_render_filter(afmt, False) # render fields 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 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 ) diff --git a/pylib/anki/decks.py b/pylib/anki/decks.py index 3f70feeb1..a412acbb8 100644 --- a/pylib/anki/decks.py +++ b/pylib/anki/decks.py @@ -165,7 +165,7 @@ class DeckManager: self.decks[str(id)] = g self.save(g) self.maybeAddToActive() - hooks.deck_created_hook(g) + hooks.deck_did_create_hook(g) return int(id) def rem(self, did: int, cardsToo: bool = False, childrenToo: bool = True) -> None: diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index fad457301..974f63978 100644 --- a/pylib/anki/exporting.py +++ b/pylib/anki/exporting.py @@ -347,7 +347,7 @@ class AnkiPackageExporter(AnkiExporter): else: z.write(mpath, cStr, zipfile.ZIP_STORED) media[cStr] = unicodedata.normalize("NFC", file) - hooks.exported_media_files_hook(c) + hooks.media_files_did_export_hook(c) return media @@ -417,5 +417,5 @@ def exporters() -> List[Tuple[str, Any]]: id(TextNoteExporter), id(TextCardExporter), ] - hooks.create_exporters_list_hook(exps) + hooks.exporters_list_did_create_hook(exps) return exps diff --git a/pylib/anki/find.py b/pylib/anki/find.py index 3d1d4d8e4..acf8e42da 100644 --- a/pylib/anki/find.py +++ b/pylib/anki/find.py @@ -40,7 +40,7 @@ class Finder: flag=self._findFlag, ) 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: "Return a list of card ids for QUERY." diff --git a/pylib/anki/hooks.py b/pylib/anki/hooks.py index a7a419335..c1d9af307 100644 --- a/pylib/anki/hooks.py +++ b/pylib/anki/hooks.py @@ -25,167 +25,10 @@ from anki.types import QAData # The code in this section is automatically generated - any edits you make # 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@@ -class _CreateExportersListHook: - _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: +class _CardDidLeechHook: _hooks: List[Callable[[Card], None]] = [] def append(self, cb: Callable[[Card], None]) -> None: @@ -208,91 +51,10 @@ class _LeechHook: runHook("leech", card) -leech_hook = _LeechHook() +card_did_leech_hook = _CardDidLeechHook() -class _ModSchemaFilter: - _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: +class _CardOdueWasInvalidHook: _hooks: List[Callable[[], None]] = [] def append(self, cb: Callable[[], None]) -> None: @@ -313,91 +75,12 @@ class _OdueInvalidHook: raise -odue_invalid_hook = _OdueInvalidHook() +card_odue_was_invalid_hook = _CardOdueWasInvalidHook() -class _OriginalCardTemplateFilter: - _hooks: List[Callable[[str, bool], str]] = [] +class _CardTemplateDidRenderFilter: + """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[ Callable[ [ @@ -467,10 +150,327 @@ class _RenderedCardTemplateFilter: 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]] = [] def append(self, cb: Callable[[str], None]) -> None: @@ -493,10 +493,10 @@ class _SyncProgressMessageHook: runHook("syncMsg", msg) -sync_progress_message_hook = _SyncProgressMessageHook() +sync_progress_did_change_hook = _SyncProgressDidChangeHook() -class _SyncStageHook: +class _SyncStageDidChangeHook: _hooks: List[Callable[[str], None]] = [] def append(self, cb: Callable[[str], None]) -> None: @@ -519,10 +519,10 @@ class _SyncStageHook: runHook("sync", stage) -sync_stage_hook = _SyncStageHook() +sync_stage_did_change_hook = _SyncStageDidChangeHook() -class _TagCreatedHook: +class _TagDidCreateHook: _hooks: List[Callable[[str], None]] = [] def append(self, cb: Callable[[str], None]) -> None: @@ -545,7 +545,7 @@ class _TagCreatedHook: runHook("newTag") -tag_created_hook = _TagCreatedHook() +tag_did_create_hook = _TagDidCreateHook() # @@AUTOGEN@@ # Legacy hook handling diff --git a/pylib/anki/latex.py b/pylib/anki/latex.py index ee096e8d2..a9b3718be 100644 --- a/pylib/anki/latex.py +++ b/pylib/anki/latex.py @@ -184,4 +184,4 @@ def _errMsg(type: str, texpath: str) -> Any: # 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 diff --git a/pylib/anki/models.py b/pylib/anki/models.py index c9667343a..accb9ea71 100644 --- a/pylib/anki/models.py +++ b/pylib/anki/models.py @@ -107,7 +107,7 @@ class ModelManager: if templates: self._syncTemplates(m) self.changed = True - hooks.note_type_created_hook(m) + hooks.note_type_did_create_hook(m) def flush(self) -> None: "Flush the registry if any models were changed." diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index e0825c7e9..bc8584e30 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -1150,7 +1150,7 @@ did = ?, queue = %s, due = ?, usn = ? where id = ?""" card.odue = card.odid = 0 card.queue = -1 # notify UI - hooks.leech_hook(card) + hooks.card_did_leech_hook(card) return True # Tools diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 9048bd879..a3ee88ed9 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -1270,7 +1270,7 @@ where id = ? if a == 0: card.queue = -1 # notify UI - hooks.leech_hook(card) + hooks.card_did_leech_hook(card) return True return None diff --git a/pylib/anki/sync.py b/pylib/anki/sync.py index 8ea9953c1..c597beebe 100644 --- a/pylib/anki/sync.py +++ b/pylib/anki/sync.py @@ -55,7 +55,7 @@ class Syncer: self.col.save() # step 1: login & metadata - hooks.sync_stage_hook("login") + hooks.sync_stage_did_change_hook("login") meta = self.server.meta() self.col.log("rmeta", meta) if not meta: @@ -95,7 +95,7 @@ class Syncer: self.col.log("basic check") return "basicCheckFailed" # step 2: startup and deletions - hooks.sync_stage_hook("meta") + hooks.sync_stage_did_change_hook("meta") rrem = self.server.start( minUsn=self.minUsn, lnewer=self.lnewer, offset=self.col.localOffset() ) @@ -118,31 +118,31 @@ class Syncer: self.server.abort() return self._forceFullSync() # step 3: stream large tables from server - hooks.sync_stage_hook("server") + hooks.sync_stage_did_change_hook("server") while 1: - hooks.sync_stage_hook("stream") + hooks.sync_stage_did_change_hook("stream") chunk = self.server.chunk() self.col.log("server chunk", chunk) self.applyChunk(chunk=chunk) if chunk["done"]: break # step 4: stream to server - hooks.sync_stage_hook("client") + hooks.sync_stage_did_change_hook("client") while 1: - hooks.sync_stage_hook("stream") + hooks.sync_stage_did_change_hook("stream") chunk = self.chunk() self.col.log("client chunk", chunk) self.server.applyChunk(chunk=chunk) if chunk["done"]: break # step 5: sanity check - hooks.sync_stage_hook("sanity") + hooks.sync_stage_did_change_hook("sanity") c = self.sanityCheck() ret = self.server.sanityCheck2(client=c) if ret["status"] != "ok": return self._forceFullSync() # finalize - hooks.sync_stage_hook("finalize") + hooks.sync_stage_did_change_hook("finalize") mod = self.server.finish() self.finish(mod) return "success" @@ -501,7 +501,7 @@ class AnkiRequestsClient: buf = io.BytesIO() 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) return buf.getvalue() @@ -523,7 +523,7 @@ if os.environ.get("ANKI_NOVERIFYSSL"): class _MonitoringFile(io.BufferedReader): def read(self, size=-1) -> bytes: 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 @@ -707,13 +707,13 @@ class FullSyncer(HttpSyncer): self.col = col 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") self.col.close() cont = self.req("download") tpath = self.col.path + ".tmp" if cont == "upgradeRequired": - hooks.sync_stage_hook("upgradeRequired") + hooks.sync_stage_did_change_hook("upgradeRequired") return None open(tpath, "wb").write(cont) # check the received file is ok @@ -733,7 +733,7 @@ class FullSyncer(HttpSyncer): def upload(self) -> bool: "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 if self.col.db.scalar("pragma integrity_check") != "ok": return False @@ -765,7 +765,7 @@ class MediaSyncer: def sync(self) -> Any: # check if there have been any changes - hooks.sync_stage_hook("findMedia") + hooks.sync_stage_did_change_hook("findMedia") self.col.log("findChanges") try: self.col.media.findChanges() @@ -835,7 +835,7 @@ class MediaSyncer: if not fnames: break - hooks.sync_progress_message_hook( + hooks.sync_progress_did_change_hook( ngettext( "%d media change to upload", "%d media changes to upload", toSend ) @@ -886,7 +886,7 @@ class MediaSyncer: fnames = fnames[cnt:] n = self.downloadCount - hooks.sync_progress_message_hook( + hooks.sync_progress_did_change_hook( ngettext("%d media file downloaded", "%d media files downloaded", n) % n, ) diff --git a/pylib/anki/tags.py b/pylib/anki/tags.py index 05e2e2ee8..db769523b 100644 --- a/pylib/anki/tags.py +++ b/pylib/anki/tags.py @@ -50,7 +50,7 @@ class TagManager: self.tags[t] = self.col.usn() if usn is None else usn self.changed = True 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: return list(self.tags.keys()) diff --git a/pylib/anki/template.py b/pylib/anki/template.py index 96795989e..e37eb0781 100644 --- a/pylib/anki/template.py +++ b/pylib/anki/template.py @@ -72,7 +72,7 @@ def apply_custom_filters( field_text = node.current_text 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 ) # legacy hook - the second and fifth argument are no longer used diff --git a/pylib/tests/test_schedv1.py b/pylib/tests/test_schedv1.py index e2c662039..f52327e96 100644 --- a/pylib/tests/test_schedv1.py +++ b/pylib/tests/test_schedv1.py @@ -373,7 +373,7 @@ def test_reviews(): def onLeech(card): hooked.append(1) - hooks.leech_hook.append(onLeech) + hooks.card_did_leech_hook.append(onLeech) d.sched.answerCard(c, 1) assert hooked assert c.queue == -1 diff --git a/pylib/tests/test_schedv2.py b/pylib/tests/test_schedv2.py index c4e199b40..7c07cfa1f 100644 --- a/pylib/tests/test_schedv2.py +++ b/pylib/tests/test_schedv2.py @@ -395,7 +395,7 @@ def test_reviews(): def onLeech(card): hooked.append(1) - hooks.leech_hook.append(onLeech) + hooks.card_did_leech_hook.append(onLeech) d.sched.answerCard(c, 1) assert hooked assert c.queue == -1 diff --git a/pylib/tools/genhooks.py b/pylib/tools/genhooks.py index 63767d8ea..09ede6153 100644 --- a/pylib/tools/genhooks.py +++ b/pylib/tools/genhooks.py @@ -17,55 +17,60 @@ from hookslib import Hook, update_file ###################################################################### hooks = [ - Hook(name="leech", args=["card: Card"], legacy_hook="leech"), - Hook(name="odue_invalid"), - Hook(name="mod_schema", args=["proceed: bool"], return_type="bool"), + Hook(name="card_did_leech", args=["card: Card"], legacy_hook="leech"), + Hook(name="card_odue_was_invalid"), + Hook(name="schema_will_change", args=["proceed: bool"], return_type="bool"), Hook( - name="remove_notes", + name="notes_will_delete", args=["col: anki.storage._Collection", "ids: List[int]"], legacy_hook="remNotes", ), Hook( - name="deck_created", + name="deck_did_create", args=["deck: Dict[str, Any]"], legacy_hook="newDeck", legacy_no_args=True, ), - Hook(name="exported_media_files", args=["count: int"]), + Hook(name="media_files_did_export", args=["count: int"]), Hook( - name="create_exporters_list", + name="exporters_list_did_create", args=["exporters: List[Tuple[str, Any]]"], legacy_hook="exportersList", ), Hook( - name="prepare_searches", + name="search_terms_did_prepare", args=["searches: Dict[str, Callable]"], legacy_hook="search", ), Hook( - name="note_type_created", + name="note_type_did_create", args=["notetype: Dict[str, Any]"], legacy_hook="newModel", legacy_no_args=True, ), - Hook(name="sync_stage", args=["stage: str"], legacy_hook="sync"), - Hook(name="sync_progress_message", args=["msg: str"], legacy_hook="syncMsg"), - Hook(name="http_data_sent", args=["bytes: int"]), - Hook(name="http_data_received", args=["bytes: int"]), + Hook(name="sync_stage_did_change", args=["stage: str"], legacy_hook="sync"), + Hook(name="sync_progress_did_change", args=["msg: str"], legacy_hook="syncMsg"), + Hook(name="http_data_did_send", args=["bytes: int"]), + Hook(name="http_data_did_receive", args=["bytes: int"]), 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( - name="modify_fields_for_rendering", + name="fields_will_render", args=["fields: Dict[str, str]", "notetype: Dict[str, Any]", "data: QAData",], + doc="Can modify the available fields prior to rendering.", ), Hook( - name="original_card_template", + name="card_template_will_render", args=["template: str", "question_side: bool"], return_type="str", + doc="Can modify the the card template used for rendering.", ), Hook( - name="rendered_card_template", + name="card_template_did_render", args=[ "text: str", "side: str", @@ -78,9 +83,10 @@ hooks = [ ], return_type="str", legacy_hook="mungeQA", + doc="Can modify the resulting text after rendering completes.", ), Hook( - name="field_replacement", + name="card_template_filter_will_apply", args=[ "field_text: str", "field_name: str", diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py index 19f2f2f7b..b8ba10417 100644 --- a/qt/aqt/browser.py +++ b/qt/aqt/browser.py @@ -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_note_did_load_hook.append(self.onLoadNote) gui_hooks.editor_field_did_lose_focus_filter.append(self.refreshCurrentCard) - hooks.tag_created_hook.append(self.maybeRefreshSidebar) - hooks.note_type_created_hook.append(self.maybeRefreshSidebar) - hooks.deck_created_hook.append(self.maybeRefreshSidebar) + hooks.tag_did_create_hook.append(self.maybeRefreshSidebar) + hooks.note_type_did_create_hook.append(self.maybeRefreshSidebar) + hooks.deck_did_create_hook.append(self.maybeRefreshSidebar) def teardownHooks(self): 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_note_did_load_hook.remove(self.onLoadNote) gui_hooks.editor_field_did_lose_focus_filter.remove(self.refreshCurrentCard) - hooks.tag_created_hook.remove(self.maybeRefreshSidebar) - hooks.note_type_created_hook.remove(self.maybeRefreshSidebar) - hooks.deck_created_hook.remove(self.maybeRefreshSidebar) + hooks.tag_did_create_hook.remove(self.maybeRefreshSidebar) + hooks.note_type_did_create_hook.remove(self.maybeRefreshSidebar) + hooks.deck_did_create_hook.remove(self.maybeRefreshSidebar) def onUndoState(self, on): self.form.actionUndo.setEnabled(on) diff --git a/qt/aqt/downloader.py b/qt/aqt/downloader.py index 0e01a8e4e..f2ed8c85e 100644 --- a/qt/aqt/downloader.py +++ b/qt/aqt/downloader.py @@ -57,7 +57,7 @@ class Downloader(QThread): self.recvTotal += bytes self.recv.emit() - hooks.http_data_received_hook.append(recvEvent) + hooks.http_data_did_receive_hook.append(recvEvent) client = AnkiRequestsClient() try: 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) return finally: - hooks.http_data_received_hook.remove(recvEvent) + hooks.http_data_did_receive_hook.remove(recvEvent) self.fname = re.match( "attachment; filename=(.+)", resp.headers["content-disposition"] diff --git a/qt/aqt/exporting.py b/qt/aqt/exporting.py index 8f84fc093..82558573b 100644 --- a/qt/aqt/exporting.py +++ b/qt/aqt/exporting.py @@ -132,9 +132,9 @@ class ExportDialog(QDialog): ) % cnt ) - hooks.exported_media_files_hook.append(exportedMedia) + hooks.media_files_did_export_hook.append(exportedMedia) self.exporter.exportInto(file) - hooks.exported_media_files_hook.remove(exportedMedia) + hooks.media_files_did_export_hook.remove(exportedMedia) period = 3000 if self.isVerbatim: msg = _("Collection exported.") diff --git a/qt/aqt/main.py b/qt/aqt/main.py index 072710f75..cb05f2a1a 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -1153,9 +1153,9 @@ Difference to correct time: %s.""" ########################################################################## def setupHooks(self) -> None: - hooks.mod_schema_filter.append(self.onSchemaMod) - hooks.remove_notes_hook.append(self.onRemNotes) - hooks.odue_invalid_hook.append(self.onOdueInvalid) + hooks.schema_will_change_filter.append(self.onSchemaMod) + hooks.notes_will_delete_hook.append(self.onRemNotes) + hooks.card_odue_was_invalid_hook.append(self.onOdueInvalid) gui_hooks.mpv_will_play_hook.append(self.on_mpv_will_play) gui_hooks.mpv_did_idle_hook.append(self.on_mpv_idle) diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 30f16f04c..6dcff1d8d 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -41,7 +41,7 @@ class Reviewer: self.typeCorrect = None # web init happens before this is set self.state = None 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): self.mw.col.reset() diff --git a/qt/aqt/sync.py b/qt/aqt/sync.py index 9cbbe0881..7642bf398 100644 --- a/qt/aqt/sync.py +++ b/qt/aqt/sync.py @@ -406,10 +406,10 @@ class SyncThread(QThread): self._abort = 2 raise Exception("sync cancelled") - hooks.sync_stage_hook.append(syncEvent) - hooks.sync_progress_message_hook.append(syncMsg) - hooks.http_data_sent_hook.append(sendEvent) - hooks.http_data_received_hook.append(recvEvent) + hooks.sync_stage_did_change_hook.append(syncEvent) + hooks.sync_progress_did_change_hook.append(syncMsg) + hooks.http_data_did_send_hook.append(sendEvent) + hooks.http_data_did_receive_hook.append(recvEvent) # run sync and catch any errors try: self._sync() @@ -419,10 +419,10 @@ class SyncThread(QThread): finally: # don't bump mod time unless we explicitly save self.col.close(save=False) - hooks.sync_stage_hook.remove(syncEvent) - hooks.sync_progress_message_hook.remove(syncMsg) - hooks.http_data_sent_hook.remove(sendEvent) - hooks.http_data_received_hook.remove(recvEvent) + hooks.sync_stage_did_change_hook.remove(syncEvent) + hooks.sync_progress_did_change_hook.remove(syncMsg) + hooks.http_data_did_send_hook.remove(sendEvent) + hooks.http_data_did_receive_hook.remove(recvEvent) def _abortingSync(self): try: