Anki/qt/aqt
Damien Elmes bb1b289690 Add some helpers to allow add-ons to install packages into the venv
While something we probably don't want to encourage much of, this
may enable some previously-unshared add-ons.

https://forums.ankiweb.net/t/bundling-numpy-in-an-add-on/62669/5

The 'uv add' command is transaction, so if an add-on tries to inject
incompatible dependencies into the environment, the venv will be
left as-is. And each Anki upgrade/downgrade resets the requirements,
so the requested packages shouldn't cause errors down the line.

Sample add-on:

import subprocess
from aqt import mw
from aqt.operations import QueryOp
from aqt.qt import QAction
from aqt.utils import showInfo

def ensure_spacy(col):
    print("trying to import spacy")
    try:
        import spacy
        print("successful import")
        return
    except Exception as e:
        print("error importing:", e)

    print("attempting add")
    try:
        from aqt.package import add_python_requirements as add
    except Exception as e:
        raise Exception(f"package unavailable, can't install: {e}")
    # be explicit about version, or Anki beta users will get
    # a beta wheel that may break
    (success, output) = add(["spacy==3.8.7", "https://github.com/explosion/spacy-models/releases/download/ko_core_news_sm-3.8.0/ko_core_news_sm-3.8.0-py3-none-any.whl"])
    if not success:
        raise Exception(f"adding failed: {output}")

    print("success")

    # alterantively:
    # from aqt.package import venv_binary
    # subprocess.run([venv_binary("spacy"), "download", "ko_core_news_sm"], check=True)
    # print("model added")

    # large packages will freeze for a while on first import on macOS
    import spacy
    print("spacy import successful")

def activate_spacy():
    def on_success(res):
        mw.progress.single_shot(1000, lambda: showInfo("Spacy installed"))

    QueryOp(parent=mw, op=ensure_spacy, success=on_success).with_progress("Installing spacy...").run_in_background()

action = QAction("Activate Spacy", mw)
action.triggered.connect(activate_spacy)
mw.form.menuTools.addAction(action)
2025-07-04 14:23:04 +07:00
..
browser Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
data Revert "Fix ease button alignment (#3474)" (#3522) 2024-10-26 18:50:02 +10:00
forms Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
import_export Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
operations Fix unescaped deck names missing from tooltips when deleted (#3960) 2025-04-29 02:18:56 +03:00
qt Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
__init__.py Fix taskbar pinning on Windows 2025-06-29 20:53:43 +07:00
_macos_helper.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
about.py Add a trademark symbol to the readme and about screens 2025-07-01 11:40:03 +07:00
addcards.py only change notetype/deck when reopening if no changes to discard (#3798) 2025-02-09 15:58:21 +03:00
addons.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
ankihub.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
changenotetype.py Add Cmd+W close shortcut (on Mac) to more dialogs (#3905) 2025-04-24 18:53:01 +10:00
clayout.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
colors.py Move away from Bazel (#2202) 2022-11-27 15:24:20 +10:00
customstudy.py Add Cmd+W close shortcut (on Mac) to more dialogs (#3905) 2025-04-24 18:53:01 +10:00
dbcheck.py Ensure DB check tooltip appears in main window 2024-04-30 23:21:41 +10:00
debug_console.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
deckbrowser.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
deckchooser.py Allow choosing filtered decks in stats (#3687) 2025-01-04 17:39:16 +03:00
deckconf.py Improve exception handling (#3290) 2024-08-04 20:51:13 +07:00
deckdescription.py Add Cmd+W close shortcut (on Mac) to more dialogs (#3905) 2025-04-24 18:53:01 +10:00
deckoptions.py Add Cmd+W close shortcut (on Mac) to more dialogs (#3905) 2025-04-24 18:53:01 +10:00
editcurrent.py Add Cmd+W close shortcut (on Mac) to more dialogs (#3905) 2025-04-24 18:53:01 +10:00
editor.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
emptycards.py Fix AnkiWebPage not being initialized for default web view kinds (e.g. in add-ons) (#3933) 2025-04-22 21:22:40 +10:00
errors.py add "copy debug info" button to show_exception's dialog (#4146) 2025-07-01 15:35:50 +07:00
exporting.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
fields.py Add Cmd+W close shortcut (on Mac) to more dialogs (#3905) 2025-04-24 18:53:01 +10:00
filtered_deck.py Enable strict_optional for aqt/deckoptions, editcurrent, filtered_deck (#3556) 2024-11-07 08:33:41 +10:00
flags.py Use default flag name when flag is renamed to empty string (#3826) 2025-02-21 16:38:04 +07:00
gui_hooks.py Move away from Bazel (#2202) 2022-11-27 15:24:20 +10:00
importing.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
legacy.py Import submodules directly (#1662) 2022-02-13 13:40:47 +10:00
log.py Add support for python logging (#2969) 2024-02-11 16:41:50 +10:00
main.py Add some helpers to allow add-ons to install packages into the venv 2025-07-04 14:23:04 +07:00
mediacheck.py Enable strict_optional for aqt/mediacheck, theme, toolbar (#3569) 2024-11-12 19:47:04 +03:00
mediasrv.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
mediasync.py Enable strict_optional for aqt/mediasync, package, progress (#3577) 2024-11-15 16:24:50 +03:00
modelchooser.py Enable strict_optional for aqt/modelchooser.py (#3539) 2024-10-28 14:19:31 +10:00
models.py Fix "Note Types" dialog moving down each time it is opened (#3718) 2025-01-12 15:33:37 +11:00
mpv.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
notetypechooser.py Enable strict_optional for aqt/notetypechooser, stats, switch (#3558) 2024-11-08 13:42:42 +03:00
overview.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
package.py Add some helpers to allow add-ons to install packages into the venv 2025-07-04 14:23:04 +07:00
preferences.py Add URL scheme whitelist (#3994) 2025-05-15 15:37:49 +10:00
profiles.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
progress.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
props.py Move away from Bazel (#2202) 2022-11-27 15:24:20 +10:00
py.typed mark anki and aqt modules as having typing info 2020-01-13 13:03:37 +10:00
reviewer.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
schema_change_tracker.py Add ability to restore a notetype to its original configuration (#2472) 2023-04-18 14:07:51 +10:00
sound.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
stats.py Add Cmd+W close shortcut (on Mac) to more dialogs (#3905) 2025-04-24 18:53:01 +10:00
studydeck.py Add Cmd+W close shortcut (on Mac) to more dialogs (#3905) 2025-04-24 18:53:01 +10:00
stylesheets.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
switch.py Remove hardcoded note/card colours from switch.py (#3629) 2024-12-14 21:30:28 +11:00
sync.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
tagedit.py Enable strict_optional for aqt/tagedit, utils, sync (#3578) 2024-11-15 16:29:19 +03:00
taglimit.py Fix mypy errors 2024-10-26 19:33:04 -07:00
taskman.py Revert "Ignore TaskManager's on_done callback if collection unloaded (#4076)" 2025-06-19 13:17:30 +07:00
theme.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
toolbar.py adjust top toolbar height on body class update (#4120) 2025-06-25 14:20:31 +03:00
tts.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
undo.py Dependency updates (#3040) 2024-02-28 16:28:04 +07:00
update.py Add some helpers to allow add-ons to install packages into the venv 2025-07-04 14:23:04 +07:00
url_schemes.py Make URL schemes dialog more ergonomic (#4002) 2025-05-15 16:17:33 +10:00
utils.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
webview.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00
widgetgallery.py Improve debug console (#2435) 2023-03-15 15:29:05 +10:00
winpaths.py Switch to Ruff (#4119) 2025-06-29 14:38:35 +07:00