mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
add a flag to handle the legacy hook missing args case
And update a few more hooks.
This commit is contained in:
parent
b86ae31907
commit
d266dcd076
10 changed files with 93 additions and 24 deletions
|
@ -13,7 +13,6 @@ import anki # pylint: disable=unused-import
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.errors import DeckRenameError
|
from anki.errors import DeckRenameError
|
||||||
from anki.hooks import runHook
|
|
||||||
from anki.lang import _
|
from anki.lang import _
|
||||||
from anki.utils import ids2str, intTime
|
from anki.utils import ids2str, intTime
|
||||||
|
|
||||||
|
@ -167,8 +166,6 @@ class DeckManager:
|
||||||
self.save(g)
|
self.save(g)
|
||||||
self.maybeAddToActive()
|
self.maybeAddToActive()
|
||||||
hooks.run_deck_created_hook(g)
|
hooks.run_deck_created_hook(g)
|
||||||
# legacy hook did not pass deck
|
|
||||||
runHook("newDeck")
|
|
||||||
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:
|
||||||
|
|
|
@ -54,6 +54,7 @@ rendered_card_template_filter: List[
|
||||||
str,
|
str,
|
||||||
]
|
]
|
||||||
] = []
|
] = []
|
||||||
|
sync_progress_message_hook: List[Callable[[str], None]] = []
|
||||||
sync_stage_hook: List[Callable[[str], None]] = []
|
sync_stage_hook: List[Callable[[str], None]] = []
|
||||||
tag_created_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
|
# if the hook fails, remove it
|
||||||
deck_created_hook.remove(hook)
|
deck_created_hook.remove(hook)
|
||||||
raise
|
raise
|
||||||
|
# legacy support
|
||||||
|
runHook("newDeck")
|
||||||
|
|
||||||
|
|
||||||
def run_exported_media_files_hook(count: int) -> None:
|
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
|
# if the hook fails, remove it
|
||||||
note_type_created_hook.remove(hook)
|
note_type_created_hook.remove(hook)
|
||||||
raise
|
raise
|
||||||
|
# legacy support
|
||||||
|
runHook("newModel")
|
||||||
|
|
||||||
|
|
||||||
def run_odue_invalid_hook() -> None:
|
def run_odue_invalid_hook() -> None:
|
||||||
|
@ -222,6 +227,18 @@ def run_rendered_card_template_filter(
|
||||||
return text
|
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:
|
def run_sync_stage_hook(stage: str) -> None:
|
||||||
for hook in sync_stage_hook:
|
for hook in sync_stage_hook:
|
||||||
try:
|
try:
|
||||||
|
@ -230,6 +247,8 @@ def run_sync_stage_hook(stage: str) -> None:
|
||||||
# if the hook fails, remove it
|
# if the hook fails, remove it
|
||||||
sync_stage_hook.remove(hook)
|
sync_stage_hook.remove(hook)
|
||||||
raise
|
raise
|
||||||
|
# legacy support
|
||||||
|
runHook("sync", stage)
|
||||||
|
|
||||||
|
|
||||||
def run_tag_created_hook(tag: str) -> None:
|
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
|
# if the hook fails, remove it
|
||||||
tag_created_hook.remove(hook)
|
tag_created_hook.remove(hook)
|
||||||
raise
|
raise
|
||||||
|
# legacy support
|
||||||
|
runHook("newTag")
|
||||||
|
|
||||||
|
|
||||||
# @@AUTOGEN@@
|
# @@AUTOGEN@@
|
||||||
|
|
|
@ -22,6 +22,8 @@ class Hook:
|
||||||
return_type: Optional[str] = None
|
return_type: Optional[str] = None
|
||||||
# if add-ons may be relying on the legacy hook name, add it here
|
# if add-ons may be relying on the legacy hook name, add it here
|
||||||
legacy_hook: Optional[str] = None
|
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:
|
def callable(self) -> str:
|
||||||
"Convert args into a Callable."
|
"Convert args into a Callable."
|
||||||
|
@ -63,6 +65,13 @@ class Hook:
|
||||||
# hook
|
# hook
|
||||||
return self.hook_fire_code()
|
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:
|
def hook_fire_code(self) -> str:
|
||||||
arg_names = self.arg_names()
|
arg_names = self.arg_names()
|
||||||
out = f"""\
|
out = f"""\
|
||||||
|
@ -76,10 +85,9 @@ def run_{self.full_name()}({", ".join(self.args or [])}) -> None:
|
||||||
raise
|
raise
|
||||||
"""
|
"""
|
||||||
if self.legacy_hook:
|
if self.legacy_hook:
|
||||||
args = ", ".join([f'"{self.legacy_hook}"'] + arg_names)
|
|
||||||
out += f"""\
|
out += f"""\
|
||||||
# legacy support
|
# legacy support
|
||||||
runHook({args})
|
runHook({self.legacy_args()})
|
||||||
"""
|
"""
|
||||||
return out + "\n\n"
|
return out + "\n\n"
|
||||||
|
|
||||||
|
@ -96,10 +104,9 @@ def run_{self.full_name()}({", ".join(self.args or [])}) -> {self.return_type}:
|
||||||
raise
|
raise
|
||||||
"""
|
"""
|
||||||
if self.legacy_hook:
|
if self.legacy_hook:
|
||||||
args = ", ".join([f'"{self.legacy_hook}"'] + arg_names)
|
|
||||||
out += f"""\
|
out += f"""\
|
||||||
# legacy support
|
# legacy support
|
||||||
runFilter({args})
|
runFilter({self.legacy_args()})
|
||||||
"""
|
"""
|
||||||
|
|
||||||
out += f"""\
|
out += f"""\
|
||||||
|
|
|
@ -12,7 +12,6 @@ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
||||||
import anki # pylint: disable=unused-import
|
import anki # pylint: disable=unused-import
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.hooks import runHook
|
|
||||||
from anki.lang import _
|
from anki.lang import _
|
||||||
from anki.types import Field, NoteType, Template
|
from anki.types import Field, NoteType, Template
|
||||||
from anki.utils import checksum, ids2str, intTime, joinFields, splitFields
|
from anki.utils import checksum, ids2str, intTime, joinFields, splitFields
|
||||||
|
@ -109,8 +108,6 @@ class ModelManager:
|
||||||
self._syncTemplates(m)
|
self._syncTemplates(m)
|
||||||
self.changed = True
|
self.changed = True
|
||||||
hooks.run_note_type_created_hook(m)
|
hooks.run_note_type_created_hook(m)
|
||||||
# legacy hook did not pass note type
|
|
||||||
runHook("newModel")
|
|
||||||
|
|
||||||
def flush(self) -> None:
|
def flush(self) -> None:
|
||||||
"Flush the registry if any models were changed."
|
"Flush the registry if any models were changed."
|
||||||
|
|
|
@ -19,7 +19,6 @@ from anki.db import DB, DBError
|
||||||
from anki.utils import checksum, devMode, ids2str, intTime, platDesc, versionWithBuild
|
from anki.utils import checksum, devMode, ids2str, intTime, platDesc, versionWithBuild
|
||||||
|
|
||||||
from . import hooks
|
from . import hooks
|
||||||
from .hooks import runHook
|
|
||||||
from .lang import ngettext
|
from .lang import ngettext
|
||||||
|
|
||||||
# syncing vars
|
# syncing vars
|
||||||
|
@ -836,8 +835,7 @@ class MediaSyncer:
|
||||||
if not fnames:
|
if not fnames:
|
||||||
break
|
break
|
||||||
|
|
||||||
runHook(
|
hooks.run_sync_progress_message_hook(
|
||||||
"syncMsg",
|
|
||||||
ngettext(
|
ngettext(
|
||||||
"%d media change to upload", "%d media changes to upload", toSend
|
"%d media change to upload", "%d media changes to upload", toSend
|
||||||
)
|
)
|
||||||
|
@ -888,8 +886,7 @@ class MediaSyncer:
|
||||||
fnames = fnames[cnt:]
|
fnames = fnames[cnt:]
|
||||||
|
|
||||||
n = self.downloadCount
|
n = self.downloadCount
|
||||||
runHook(
|
hooks.run_sync_progress_message_hook(
|
||||||
"syncMsg",
|
|
||||||
ngettext("%d media file downloaded", "%d media files downloaded", n)
|
ngettext("%d media file downloaded", "%d media files downloaded", n)
|
||||||
% n,
|
% n,
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,7 +17,6 @@ from typing import Callable, Dict, List, Tuple
|
||||||
|
|
||||||
import anki # pylint: disable=unused-import
|
import anki # pylint: disable=unused-import
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
from anki.hooks import runHook
|
|
||||||
from anki.utils import ids2str, intTime
|
from anki.utils import ids2str, intTime
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +51,6 @@ class TagManager:
|
||||||
self.changed = True
|
self.changed = True
|
||||||
if found:
|
if found:
|
||||||
hooks.run_tag_created_hook(t) # pylint: disable=undefined-loop-variable
|
hooks.run_tag_created_hook(t) # pylint: disable=undefined-loop-variable
|
||||||
runHook("newTag")
|
|
||||||
|
|
||||||
def all(self) -> List:
|
def all(self) -> List:
|
||||||
return list(self.tags.keys())
|
return list(self.tags.keys())
|
||||||
|
|
|
@ -25,7 +25,12 @@ hooks = [
|
||||||
args=["col: anki.storage._Collection", "ids: List[int]"],
|
args=["col: anki.storage._Collection", "ids: List[int]"],
|
||||||
legacy_hook="remNotes",
|
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="exported_media_files", args=["count: int"]),
|
||||||
Hook(
|
Hook(
|
||||||
name="create_exporters_list",
|
name="create_exporters_list",
|
||||||
|
@ -37,11 +42,19 @@ hooks = [
|
||||||
args=["searches: Dict[str, Callable]"],
|
args=["searches: Dict[str, Callable]"],
|
||||||
legacy_hook="search",
|
legacy_hook="search",
|
||||||
),
|
),
|
||||||
Hook(name="note_type_created", args=["notetype: Dict[str, Any]"]),
|
Hook(
|
||||||
Hook(name="sync_stage", args=["stage: str"]),
|
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_sent", args=["bytes: int"]),
|
||||||
Hook(name="http_data_received", 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(
|
Hook(
|
||||||
name="modify_fields_for_rendering",
|
name="modify_fields_for_rendering",
|
||||||
args=["fields: Dict[str, str]", "notetype: Dict[str, Any]", "data: QAData",],
|
args=["fields: Dict[str, str]", "notetype: Dict[str, Any]", "data: QAData",],
|
||||||
|
|
|
@ -9,6 +9,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any, Callable, Dict, List # pylint: disable=unused-import
|
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
|
from anki.hooks import runFilter, runHook # pylint: disable=unused-import
|
||||||
|
|
||||||
# New hook/filter handling
|
# 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_idle_hook: List[Callable[[], None]] = []
|
||||||
mpv_will_play_hook: List[Callable[[str], 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:
|
def run_mpv_idle_hook() -> None:
|
||||||
|
@ -44,4 +47,28 @@ def run_mpv_will_play_hook(file: str) -> None:
|
||||||
runHook("mpvWillPlay", file)
|
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@@
|
# @@AUTOGEN@@
|
||||||
|
|
|
@ -16,7 +16,7 @@ from anki.cards import Card
|
||||||
from anki.hooks import runFilter, runHook
|
from anki.hooks import runFilter, runHook
|
||||||
from anki.lang import _, ngettext
|
from anki.lang import _, ngettext
|
||||||
from anki.utils import bodyClass, stripHTML
|
from anki.utils import bodyClass, stripHTML
|
||||||
from aqt import AnkiQt
|
from aqt import AnkiQt, gui_hooks
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
from aqt.sound import clearAudioQueue, getAudio, play, playFromText
|
from aqt.sound import clearAudioQueue, getAudio, play, playFromText
|
||||||
from aqt.utils import (
|
from aqt.utils import (
|
||||||
|
@ -200,7 +200,7 @@ The front of this card is empty. Please run Tools>Empty Cards."""
|
||||||
if self.typeCorrect:
|
if self.typeCorrect:
|
||||||
self.mw.web.setFocus()
|
self.mw.web.setFocus()
|
||||||
# user hook
|
# user hook
|
||||||
runHook("showQuestion")
|
gui_hooks.run_reviewer_showing_question_hook(c)
|
||||||
|
|
||||||
def autoplay(self, card):
|
def autoplay(self, card):
|
||||||
return self.mw.col.decks.confForDid(card.odid or card.did)["autoplay"]
|
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.web.eval("_showAnswer(%s);" % json.dumps(a))
|
||||||
self._showEaseButtons()
|
self._showEaseButtons()
|
||||||
# user hook
|
# user hook
|
||||||
runHook("showAnswer")
|
gui_hooks.run_reviewer_showing_answer_hook(c)
|
||||||
|
|
||||||
# Answering a card
|
# Answering a card
|
||||||
############################################################
|
############################################################
|
||||||
|
|
|
@ -15,6 +15,18 @@ from anki.hooks_gen import Hook, update_file
|
||||||
hooks = [
|
hooks = [
|
||||||
Hook(name="mpv_idle"),
|
Hook(name="mpv_idle"),
|
||||||
Hook(name="mpv_will_play", args=["file: str"], legacy_hook="mpvWillPlay"),
|
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__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in a new issue