This changes 'keep existing version' to 'sync project changes'
when changes to the pyproject.toml file have been detected that
are newer than the installer's version.
Also adds a way to temporarily enable the launcher, as we needed some
other trigger than the pyproject.toml file anyway, and this approach
also solves #4165.
And removes the 'quit' option, since it's an uncommon operation, and
the user can just close the window instead.
Short-term caveat: users with older launchers/addon will trigger the old
pyproject.toml mtime bump, leading to a 'sync project changes' message
that will not make much sense to a typical user.
We can't show an AnkiWeb page for a locally-installed add-on, and
having a custom config action is the only way we can easily expose
this for older clients as well.
Re: #4158
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)