add a flag to handle the legacy hook missing args case

And update a few more hooks.
This commit is contained in:
Damien Elmes 2020-01-13 18:37:08 +10:00
parent b86ae31907
commit d266dcd076
10 changed files with 93 additions and 24 deletions

View file

@ -13,7 +13,6 @@ import anki # pylint: disable=unused-import
from anki import hooks
from anki.consts import *
from anki.errors import DeckRenameError
from anki.hooks import runHook
from anki.lang import _
from anki.utils import ids2str, intTime
@ -167,8 +166,6 @@ class DeckManager:
self.save(g)
self.maybeAddToActive()
hooks.run_deck_created_hook(g)
# legacy hook did not pass deck
runHook("newDeck")
return int(id)
def rem(self, did: int, cardsToo: bool = False, childrenToo: bool = True) -> None:

View file

@ -54,6 +54,7 @@ rendered_card_template_filter: List[
str,
]
] = []
sync_progress_message_hook: List[Callable[[str], None]] = []
sync_stage_hook: List[Callable[[str], None]] = []
tag_created_hook: List[Callable[[str], None]] = []
@ -78,6 +79,8 @@ def run_deck_created_hook(deck: Dict[str, Any]) -> None:
# if the hook fails, remove it
deck_created_hook.remove(hook)
raise
# legacy support
runHook("newDeck")
def run_exported_media_files_hook(count: int) -> None:
@ -166,6 +169,8 @@ def run_note_type_created_hook(notetype: Dict[str, Any]) -> None:
# if the hook fails, remove it
note_type_created_hook.remove(hook)
raise
# legacy support
runHook("newModel")
def run_odue_invalid_hook() -> None:
@ -222,6 +227,18 @@ def run_rendered_card_template_filter(
return text
def run_sync_progress_message_hook(msg: str) -> None:
for hook in sync_progress_message_hook:
try:
hook(msg)
except:
# if the hook fails, remove it
sync_progress_message_hook.remove(hook)
raise
# legacy support
runHook("syncMsg", msg)
def run_sync_stage_hook(stage: str) -> None:
for hook in sync_stage_hook:
try:
@ -230,6 +247,8 @@ def run_sync_stage_hook(stage: str) -> None:
# if the hook fails, remove it
sync_stage_hook.remove(hook)
raise
# legacy support
runHook("sync", stage)
def run_tag_created_hook(tag: str) -> None:
@ -240,6 +259,8 @@ def run_tag_created_hook(tag: str) -> None:
# if the hook fails, remove it
tag_created_hook.remove(hook)
raise
# legacy support
runHook("newTag")
# @@AUTOGEN@@

View file

@ -22,6 +22,8 @@ class Hook:
return_type: Optional[str] = None
# if add-ons may be relying on the legacy hook name, add it here
legacy_hook: Optional[str] = None
# if legacy hook takes no arguments but the new hook does, set this
legacy_no_args: bool = False
def callable(self) -> str:
"Convert args into a Callable."
@ -63,6 +65,13 @@ class Hook:
# hook
return self.hook_fire_code()
def legacy_args(self) -> str:
if self.legacy_no_args:
# hook name only
return f'"{self.legacy_hook}"'
else:
return ", ".join([f'"{self.legacy_hook}"'] + self.arg_names())
def hook_fire_code(self) -> str:
arg_names = self.arg_names()
out = f"""\
@ -76,10 +85,9 @@ def run_{self.full_name()}({", ".join(self.args or [])}) -> None:
raise
"""
if self.legacy_hook:
args = ", ".join([f'"{self.legacy_hook}"'] + arg_names)
out += f"""\
# legacy support
runHook({args})
runHook({self.legacy_args()})
"""
return out + "\n\n"
@ -96,10 +104,9 @@ def run_{self.full_name()}({", ".join(self.args or [])}) -> {self.return_type}:
raise
"""
if self.legacy_hook:
args = ", ".join([f'"{self.legacy_hook}"'] + arg_names)
out += f"""\
# legacy support
runFilter({args})
runFilter({self.legacy_args()})
"""
out += f"""\

View file

@ -12,7 +12,6 @@ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
import anki # pylint: disable=unused-import
from anki import hooks
from anki.consts import *
from anki.hooks import runHook
from anki.lang import _
from anki.types import Field, NoteType, Template
from anki.utils import checksum, ids2str, intTime, joinFields, splitFields
@ -109,8 +108,6 @@ class ModelManager:
self._syncTemplates(m)
self.changed = True
hooks.run_note_type_created_hook(m)
# legacy hook did not pass note type
runHook("newModel")
def flush(self) -> None:
"Flush the registry if any models were changed."

View file

@ -19,7 +19,6 @@ from anki.db import DB, DBError
from anki.utils import checksum, devMode, ids2str, intTime, platDesc, versionWithBuild
from . import hooks
from .hooks import runHook
from .lang import ngettext
# syncing vars
@ -836,8 +835,7 @@ class MediaSyncer:
if not fnames:
break
runHook(
"syncMsg",
hooks.run_sync_progress_message_hook(
ngettext(
"%d media change to upload", "%d media changes to upload", toSend
)
@ -888,8 +886,7 @@ class MediaSyncer:
fnames = fnames[cnt:]
n = self.downloadCount
runHook(
"syncMsg",
hooks.run_sync_progress_message_hook(
ngettext("%d media file downloaded", "%d media files downloaded", n)
% n,
)

View file

@ -17,7 +17,6 @@ from typing import Callable, Dict, List, Tuple
import anki # pylint: disable=unused-import
from anki import hooks
from anki.hooks import runHook
from anki.utils import ids2str, intTime
@ -52,7 +51,6 @@ class TagManager:
self.changed = True
if found:
hooks.run_tag_created_hook(t) # pylint: disable=undefined-loop-variable
runHook("newTag")
def all(self) -> List:
return list(self.tags.keys())

View file

@ -25,7 +25,12 @@ hooks = [
args=["col: anki.storage._Collection", "ids: List[int]"],
legacy_hook="remNotes",
),
Hook(name="deck_created", args=["deck: Dict[str, Any]"]),
Hook(
name="deck_created",
args=["deck: Dict[str, Any]"],
legacy_hook="newDeck",
legacy_no_args=True,
),
Hook(name="exported_media_files", args=["count: int"]),
Hook(
name="create_exporters_list",
@ -37,11 +42,19 @@ hooks = [
args=["searches: Dict[str, Callable]"],
legacy_hook="search",
),
Hook(name="note_type_created", args=["notetype: Dict[str, Any]"]),
Hook(name="sync_stage", args=["stage: str"]),
Hook(
name="note_type_created",
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="tag_created", args=["tag: str"]),
Hook(
name="tag_created", args=["tag: str"], legacy_hook="newTag", legacy_no_args=True
),
Hook(
name="modify_fields_for_rendering",
args=["fields: Dict[str, str]", "notetype: Dict[str, Any]", "data: QAData",],

View file

@ -9,6 +9,7 @@ from __future__ import annotations
from typing import Any, Callable, Dict, List # pylint: disable=unused-import
from anki.cards import Card
from anki.hooks import runFilter, runHook # pylint: disable=unused-import
# New hook/filter handling
@ -20,6 +21,8 @@ from anki.hooks import runFilter, runHook # pylint: disable=unused-import
mpv_idle_hook: List[Callable[[], None]] = []
mpv_will_play_hook: List[Callable[[str], None]] = []
reviewer_showing_answer_hook: List[Callable[[Card], None]] = []
reviewer_showing_question_hook: List[Callable[[Card], None]] = []
def run_mpv_idle_hook() -> None:
@ -44,4 +47,28 @@ def run_mpv_will_play_hook(file: str) -> None:
runHook("mpvWillPlay", file)
def run_reviewer_showing_answer_hook(card: Card) -> None:
for hook in reviewer_showing_answer_hook:
try:
hook(card)
except:
# if the hook fails, remove it
reviewer_showing_answer_hook.remove(hook)
raise
# legacy support
runHook("showAnswer")
def run_reviewer_showing_question_hook(card: Card) -> None:
for hook in reviewer_showing_question_hook:
try:
hook(card)
except:
# if the hook fails, remove it
reviewer_showing_question_hook.remove(hook)
raise
# legacy support
runHook("showQuestion")
# @@AUTOGEN@@

View file

@ -16,7 +16,7 @@ from anki.cards import Card
from anki.hooks import runFilter, runHook
from anki.lang import _, ngettext
from anki.utils import bodyClass, stripHTML
from aqt import AnkiQt
from aqt import AnkiQt, gui_hooks
from aqt.qt import *
from aqt.sound import clearAudioQueue, getAudio, play, playFromText
from aqt.utils import (
@ -200,7 +200,7 @@ The front of this card is empty. Please run Tools>Empty Cards."""
if self.typeCorrect:
self.mw.web.setFocus()
# user hook
runHook("showQuestion")
gui_hooks.run_reviewer_showing_question_hook(c)
def autoplay(self, card):
return self.mw.col.decks.confForDid(card.odid or card.did)["autoplay"]
@ -235,7 +235,7 @@ The front of this card is empty. Please run Tools>Empty Cards."""
self.web.eval("_showAnswer(%s);" % json.dumps(a))
self._showEaseButtons()
# user hook
runHook("showAnswer")
gui_hooks.run_reviewer_showing_answer_hook(c)
# Answering a card
############################################################

View file

@ -15,6 +15,18 @@ from anki.hooks_gen import Hook, update_file
hooks = [
Hook(name="mpv_idle"),
Hook(name="mpv_will_play", args=["file: str"], legacy_hook="mpvWillPlay"),
Hook(
name="reviewer_showing_question",
args=["card: Card"],
legacy_hook="showQuestion",
legacy_no_args=True,
),
Hook(
name="reviewer_showing_answer",
args=["card: Card"],
legacy_hook="showAnswer",
legacy_no_args=True,
),
]
if __name__ == "__main__":