diff --git a/.run/TalkBotAI (27).run.xml b/.run/TalkBotAI (27).run.xml
new file mode 100644
index 00000000..ae38223c
--- /dev/null
+++ b/.run/TalkBotAI (27).run.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.run/TalkBotAI.run.xml b/.run/TalkBotAI (28).run.xml
similarity index 92%
rename from .run/TalkBotAI.run.xml
rename to .run/TalkBotAI (28).run.xml
index e65a81d9..43e78023 100644
--- a/.run/TalkBotAI.run.xml
+++ b/.run/TalkBotAI (28).run.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/.run/ToGif(28).run.xml b/.run/ToGif (28).run.xml
similarity index 92%
rename from .run/ToGif(28).run.xml
rename to .run/ToGif (28).run.xml
index 2e0f7e97..896de8bd 100644
--- a/.run/ToGif(28).run.xml
+++ b/.run/ToGif (28).run.xml
@@ -1,15 +1,15 @@
-
+
+
-
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b6176b5a..3ec800f5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,16 @@
All notable changes to this project will be documented in this file.
+## [0.4.1 - 2023-10-17]
+
+### Added
+
+- Support for the new AppAPI endpoint `/init` and automatically downloading models from `huggingface`. #151
+
+### Changed
+
+- All examples were adjusted to changes in AppAPI.
+
## [0.4.0 - 2023-10-15]
As the project moves closer to `beta`, final unification changes are being made.
diff --git a/examples/as_app/skeleton/Makefile b/examples/as_app/skeleton/Makefile
index ed957c28..fe87572d 100644
--- a/examples/as_app/skeleton/Makefile
+++ b/examples/as_app/skeleton/Makefile
@@ -32,13 +32,13 @@ deploy:
.PHONY: run28
run28:
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister skeleton --silent || true
- docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register skeleton docker_dev -e --force-scopes \
+ docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register skeleton docker_dev --force-scopes \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
.PHONY: run27
run27:
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister skeleton --silent || true
- docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register skeleton docker_dev -e --force-scopes \
+ docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register skeleton docker_dev --force-scopes \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/skeleton/appinfo/info.xml
.PHONY: manual_register
@@ -46,4 +46,4 @@ manual_register:
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister skeleton --silent || true
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register skeleton manual_install --json-info \
"{\"appid\":\"skeleton\",\"name\":\"App Skeleton\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"host\":\"host.docker.internal\",\"port\":9030,\"scopes\":{\"required\":[],\"optional\":[]},\"protocol\":\"http\",\"system_app\":0}" \
- -e --force-scopes
+ --force-scopes
diff --git a/examples/as_app/skeleton/requirements.txt b/examples/as_app/skeleton/requirements.txt
index 3fac8ce1..20e27d1b 100644
--- a/examples/as_app/skeleton/requirements.txt
+++ b/examples/as_app/skeleton/requirements.txt
@@ -1 +1 @@
-nc_py_api[app]>=0.3.0
+nc_py_api[app]>=0.4.1
diff --git a/examples/as_app/talk_bot/Makefile b/examples/as_app/talk_bot/Makefile
index 47ac5a9b..31fbe694 100644
--- a/examples/as_app/talk_bot/Makefile
+++ b/examples/as_app/talk_bot/Makefile
@@ -32,13 +32,13 @@ deploy:
.PHONY: run28
run28:
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister talk_bot --silent || true
- docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot docker_dev -e --force-scopes \
+ docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot docker_dev --force-scopes \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/talk_bot/appinfo/info.xml
.PHONY: run27
run27:
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister talk_bot --silent || true
- docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register talk_bot docker_dev -e --force-scopes \
+ docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register talk_bot docker_dev --force-scopes \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/talk_bot/appinfo/info.xml
.PHONY: manual_register
@@ -46,4 +46,4 @@ manual_register:
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister talk_bot --silent || true
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot manual_install --json-info \
"{\"appid\":\"talk_bot\",\"name\":\"TalkBot\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"host\":\"host.docker.internal\",\"port\":9032,\"scopes\":{\"required\":[\"TALK\", \"TALK_BOT\"],\"optional\":[]},\"protocol\":\"http\",\"system_app\":0}" \
- -e --force-scopes
+ --force-scopes
diff --git a/examples/as_app/talk_bot/requirements.txt b/examples/as_app/talk_bot/requirements.txt
index 3fac8ce1..20e27d1b 100644
--- a/examples/as_app/talk_bot/requirements.txt
+++ b/examples/as_app/talk_bot/requirements.txt
@@ -1 +1 @@
-nc_py_api[app]>=0.3.0
+nc_py_api[app]>=0.4.1
diff --git a/examples/as_app/talk_bot_ai/Makefile b/examples/as_app/talk_bot_ai/Makefile
index ac836fb8..dca709bd 100644
--- a/examples/as_app/talk_bot_ai/Makefile
+++ b/examples/as_app/talk_bot_ai/Makefile
@@ -17,7 +17,8 @@ help:
@echo " For development of this example use PyCharm run configurations. Development is always set for last Nextcloud."
@echo " First run 'TalkBotAI' and then 'make manual_register', after that you can use/debug/develop it and easy test."
@echo " "
- @echo " manual_register perform registration of running 'TalkBotAI' into the 'manual_install' deploy daemon."
+ @echo " manual_register28 perform registration of running 'TalkBotAI' into the 'manual_install' deploy daemon."
+ @echo " manual_register27 perform registration of running 'TalkBotAI' into the 'manual_install' deploy daemon."
.PHONY: build-push
build-push:
@@ -32,18 +33,25 @@ deploy:
.PHONY: run28
run28:
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister talk_bot_ai --silent || true
- docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot_ai docker_dev -e --force-scopes \
+ docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot_ai docker_dev --force-scopes \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/talk_bot_ai/appinfo/info.xml
+.PHONY: manual_register28
+manual_register28:
+ docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister talk_bot_ai --silent || true
+ docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot_ai manual_install --json-info \
+ "{\"appid\":\"talk_bot_ai\",\"name\":\"TalkBotAI\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"host\":\"host.docker.internal\",\"port\":9034,\"scopes\":{\"required\":[\"TALK\", \"TALK_BOT\"],\"optional\":[]},\"protocol\":\"http\",\"system_app\":0}" \
+ --force-scopes
+
.PHONY: run27
run27:
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister talk_bot_ai --silent || true
- docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register talk_bot_ai docker_dev -e --force-scopes \
+ docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register talk_bot_ai docker_dev --force-scopes \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/talk_bot_ai/appinfo/info.xml
-.PHONY: manual_register
-manual_register:
- docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister talk_bot_ai --silent || true
- docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot_ai manual_install --json-info \
+.PHONY: manual_register27
+manual_register27:
+ docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister talk_bot_ai --silent || true
+ docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register talk_bot_ai manual_install --json-info \
"{\"appid\":\"talk_bot_ai\",\"name\":\"TalkBotAI\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"host\":\"host.docker.internal\",\"port\":9034,\"scopes\":{\"required\":[\"TALK\", \"TALK_BOT\"],\"optional\":[]},\"protocol\":\"http\",\"system_app\":0}" \
- -e --force-scopes
+ --force-scopes
diff --git a/examples/as_app/talk_bot_ai/requirements.txt b/examples/as_app/talk_bot_ai/requirements.txt
index 3d9fc12c..dfa5a75e 100644
--- a/examples/as_app/talk_bot_ai/requirements.txt
+++ b/examples/as_app/talk_bot_ai/requirements.txt
@@ -1,4 +1,4 @@
-nc_py_api[app]>=0.3.0
+nc_py_api[app]>=0.4.1
transformers>=4.33
torch
torchvision
diff --git a/examples/as_app/talk_bot_ai/src/main.py b/examples/as_app/talk_bot_ai/src/main.py
index 65d27d3b..68f3e40d 100644
--- a/examples/as_app/talk_bot_ai/src/main.py
+++ b/examples/as_app/talk_bot_ai/src/main.py
@@ -1,13 +1,10 @@
"""Example of an application that uses Python Transformers library with Talk Bot APIs."""
-
-# This line should be on top before any import of the "Transformers" library.
-from nc_py_api.ex_app import persist_transformers_cache # noqa # isort:skip
import re
-from threading import Thread
from typing import Annotated
import requests
from fastapi import BackgroundTasks, Depends, FastAPI
+from huggingface_hub import snapshot_download
from transformers import pipeline
from nc_py_api import NextcloudApp, talk_bot
@@ -15,15 +12,14 @@
APP = FastAPI()
AI_BOT = talk_bot.TalkBot("/ai_talk_bot", "AI talk bot", "Usage: `@assistant What sounds do cats make?`")
-MODEL_NAME = "MBZUAI/LaMini-Flan-T5-77M"
-MODEL_INIT_THREAD = None
+MODEL_NAME = "MBZUAI/LaMini-Flan-T5-783M"
def ai_talk_bot_process_request(message: talk_bot.TalkBotMessage):
r = re.search(r"@assistant\s(.*)", message.object_content["message"], re.IGNORECASE)
if r is None:
return
- model = pipeline("text2text-generation", model=MODEL_NAME)
+ model = pipeline("text2text-generation", model=snapshot_download(MODEL_NAME, local_files_only=True))
response_text = model(r.group(1), max_length=64, do_sample=True)[0]["generated_text"]
AI_BOT.send_message(response_text, message)
@@ -47,25 +43,9 @@ def enabled_handler(enabled: bool, nc: NextcloudApp) -> str:
return ""
-def download_models():
- pipeline("text2text-generation", model=MODEL_NAME)
-
-
-def heartbeat_handler() -> str:
- global MODEL_INIT_THREAD
- print("heartbeat_handler: called")
- if MODEL_INIT_THREAD is None:
- MODEL_INIT_THREAD = Thread(target=download_models)
- MODEL_INIT_THREAD.start()
- print("heartbeat_handler: started initialization thread")
- r = "init" if MODEL_INIT_THREAD.is_alive() else "ok"
- print(f"heartbeat_handler: result={r}")
- return r
-
-
@APP.on_event("startup")
def initialization():
- set_handlers(APP, enabled_handler, heartbeat_handler)
+ set_handlers(APP, enabled_handler, models_to_fetch=[MODEL_NAME])
if __name__ == "__main__":
diff --git a/examples/as_app/talk_bot_multi/Makefile b/examples/as_app/talk_bot_multi/Makefile
index 2b88f971..13109a77 100644
--- a/examples/as_app/talk_bot_multi/Makefile
+++ b/examples/as_app/talk_bot_multi/Makefile
@@ -32,13 +32,13 @@ deploy:
.PHONY: run28
run28:
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister talk_bot_multi --silent || true
- docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot_multi docker_dev -e --force-scopes \
+ docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot_multi docker_dev --force-scopes \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/talk_bot_multi/appinfo/info.xml
.PHONY: run27
run27:
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister talk_bot_multi --silent || true
- docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register talk_bot_multi docker_dev -e --force-scopes \
+ docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register talk_bot_multi docker_dev --force-scopes \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/talk_bot_multi/appinfo/info.xml
.PHONY: manual_register
@@ -46,4 +46,4 @@ manual_register:
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister talk_bot_multi --silent || true
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot_multi manual_install --json-info \
"{\"appid\":\"talk_bot_multi\",\"name\":\"TalkBotMulti\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"host\":\"host.docker.internal\",\"port\":9033,\"scopes\":{\"required\":[\"TALK\", \"TALK_BOT\"],\"optional\":[]},\"protocol\":\"http\",\"system_app\":0}" \
- -e --force-scopes
+ --force-scopes
diff --git a/examples/as_app/talk_bot_multi/requirements.txt b/examples/as_app/talk_bot_multi/requirements.txt
index 3fac8ce1..20e27d1b 100644
--- a/examples/as_app/talk_bot_multi/requirements.txt
+++ b/examples/as_app/talk_bot_multi/requirements.txt
@@ -1 +1 @@
-nc_py_api[app]>=0.3.0
+nc_py_api[app]>=0.4.1
diff --git a/examples/as_app/to_gif/Makefile b/examples/as_app/to_gif/Makefile
index df567ad9..dd0b3de3 100644
--- a/examples/as_app/to_gif/Makefile
+++ b/examples/as_app/to_gif/Makefile
@@ -33,7 +33,7 @@ deploy:
.PHONY: run28
run28:
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister to_gif --silent || true
- docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register to_gif docker_dev -e --force-scopes \
+ docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register to_gif docker_dev --force-scopes \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/to_gif/appinfo/info.xml
.PHONY: manual_register28
@@ -41,12 +41,12 @@ manual_register28:
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister to_gif --silent || true
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register to_gif manual_install --json-info \
"{\"appid\":\"to_gif\",\"name\":\"to_gif\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"host\":\"host.docker.internal\",\"port\":9031,\"scopes\":{\"required\":[\"FILES\", \"NOTIFICATIONS\"],\"optional\":[]},\"protocol\":\"http\",\"system_app\":0}" \
- -e --force-scopes
+ --force-scopes
.PHONY: run27
run27:
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister to_gif --silent || true
- docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register to_gif docker_dev -e --force-scopes \
+ docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register to_gif docker_dev --force-scopes \
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/to_gif/appinfo/info.xml
.PHONY: manual_register27
@@ -54,4 +54,4 @@ manual_register27:
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister to_gif --silent || true
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register to_gif manual_install --json-info \
"{\"appid\":\"to_gif\",\"name\":\"to_gif\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"host\":\"host.docker.internal\",\"port\":9031,\"scopes\":{\"required\":[\"FILES\", \"NOTIFICATIONS\"],\"optional\":[]},\"protocol\":\"http\",\"system_app\":0}" \
- -e --force-scopes
+ --force-scopes
diff --git a/examples/as_app/to_gif/requirements.txt b/examples/as_app/to_gif/requirements.txt
index a98523bb..e7bab5ea 100644
--- a/examples/as_app/to_gif/requirements.txt
+++ b/examples/as_app/to_gif/requirements.txt
@@ -1,4 +1,4 @@
-nc_py_api[app]>=0.3.0
+nc_py_api[app]>=0.4.1
pygifsicle
imageio
opencv-python
diff --git a/nc_py_api/_version.py b/nc_py_api/_version.py
index 84a58560..f70a7d3b 100644
--- a/nc_py_api/_version.py
+++ b/nc_py_api/_version.py
@@ -1,3 +1,3 @@
"""Version of nc_py_api."""
-__version__ = "0.4.0"
+__version__ = "0.4.1.dev0"
diff --git a/nc_py_api/ex_app/integration_fastapi.py b/nc_py_api/ex_app/integration_fastapi.py
index 8ea19d9a..fc645b5e 100644
--- a/nc_py_api/ex_app/integration_fastapi.py
+++ b/nc_py_api/ex_app/integration_fastapi.py
@@ -6,11 +6,20 @@
import json
import typing
-from fastapi import Depends, FastAPI, HTTPException, Request, responses, status
+from fastapi import (
+ BackgroundTasks,
+ Depends,
+ FastAPI,
+ HTTPException,
+ Request,
+ responses,
+ status,
+)
from .._misc import get_username_secret_from_headers
from ..nextcloud import NextcloudApp
from ..talk_bot import TalkBotMessage, get_bot_secret
+from .misc import persistent_storage
def nc_app(request: Request) -> NextcloudApp:
@@ -45,14 +54,50 @@ def set_handlers(
fast_api_app: FastAPI,
enabled_handler: typing.Callable[[bool, NextcloudApp], str],
heartbeat_handler: typing.Optional[typing.Callable[[], str]] = None,
+ init_handler: typing.Optional[typing.Callable[[], None]] = None,
+ models_to_fetch: typing.Optional[list[str]] = None,
+ models_download_params: typing.Optional[dict] = None,
):
"""Defines handlers for the application.
:param fast_api_app: FastAPI() call return value.
:param enabled_handler: ``Required``, callback which will be called for `enabling`/`disabling` app event.
:param heartbeat_handler: Optional, callback that will be called for the `heartbeat` deploy event.
+ :param init_handler: Optional, callback that will be called for the `init` event.
+
+ .. note:: If ``init_handler`` is specified, it is up to a developer to set the application init progress status.
+ AppAPI will only call `enabled_handler` after it receives ``100`` as initialization status progress.
+
+ :param models_to_fetch: Dictionary describing which models should be downloaded during `init`.
+
+ .. note:: ```huggingface_hub`` package should be present for automatic models fetching.
+
+ :param models_download_params: Parameters to pass to ``snapshot_download`` function from **huggingface_hub**.
"""
+ def fetch_models_task(models: dict):
+ if models:
+ from huggingface_hub import snapshot_download # noqa isort:skip pylint: disable=C0415 disable=E0401
+ from tqdm import tqdm # noqa isort:skip pylint: disable=C0415 disable=E0401
+
+ class TqdmProgress(tqdm):
+ def display(self, msg=None, pos=None):
+ if init_handler is None:
+ NextcloudApp().set_init_status(min(int((self.n * 100 / self.total) / len(models)), 100))
+ return super().display(msg, pos)
+
+ params = models_download_params if models_download_params else {}
+ if "max_workers" not in params:
+ params["max_workers"] = 2
+ if "cache_dir" not in params:
+ params["cache_dir"] = persistent_storage()
+ for model in models:
+ snapshot_download(model, tqdm_class=TqdmProgress, **params) # noqa
+ if init_handler is None:
+ NextcloudApp().set_init_status(100)
+ else:
+ init_handler()
+
@fast_api_app.put("/enabled")
def enabled_callback(
enabled: bool,
@@ -67,3 +112,8 @@ def heartbeat_callback():
if heartbeat_handler is not None:
return_status = heartbeat_handler()
return responses.JSONResponse(content={"status": return_status}, status_code=200)
+
+ @fast_api_app.post("/init")
+ def init_callback(background_tasks: BackgroundTasks):
+ background_tasks.add_task(fetch_models_task, models_to_fetch if models_to_fetch else {})
+ return responses.JSONResponse(content={}, status_code=200)
diff --git a/nc_py_api/nextcloud.py b/nc_py_api/nextcloud.py
index d1a8f17b..0efa2a1a 100644
--- a/nc_py_api/nextcloud.py
+++ b/nc_py_api/nextcloud.py
@@ -255,3 +255,20 @@ def request_sign_check(self, request: Request) -> bool:
print(e)
return False
return True
+
+ def set_init_status(self, progress: int, error: str = "") -> None:
+ """Sets state of the app initialization.
+
+ :param progress: a number from ``0`` to ``100`` indicating the percentage of application readiness for work.
+ After sending ``100`` AppAPI will enable the application.
+ :param error: if non-empty, signals to AppAPI that the application cannot be initialized successfully.
+ """
+ self._session.ocs(
+ method="PUT",
+ path=f"/ocs/v1.php/apps/app_api/apps/status/{self._session.cfg.app_name}",
+ json={
+ "progress": progress,
+ "error": error,
+ },
+ not_parse=True,
+ )
diff --git a/pyproject.toml b/pyproject.toml
index 58179f06..0860b894 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -69,6 +69,7 @@ dev = [
]
dev-min = [
"coverage",
+ "huggingface_hub",
"pillow",
"pre-commit",
"pylint",
diff --git a/scripts/ci_register.sh b/scripts/ci_register.sh
index b7cce6d5..32eef1aa 100755
--- a/scripts/ci_register.sh
+++ b/scripts/ci_register.sh
@@ -6,4 +6,4 @@
php occ app_api:daemon:register manual_install "Manual Install" manual-install 0 0 0
php occ app_api:app:register "$1" manual_install --json-info \
"{\"appid\":\"$1\",\"name\":\"$1\",\"daemon_config_name\":\"manual_install\",\"version\":\"$2\",\"secret\":\"$3\",\"host\":\"$4\",\"scopes\":{\"required\":[\"SYSTEM\", \"FILES\", \"FILES_SHARING\"],\"optional\":[\"USER_INFO\", \"USER_STATUS\", \"NOTIFICATIONS\", \"WEATHER_STATUS\", \"TALK\", \"TALK_BOT\", \"ACTIVITIES\", \"NOTES\"]},\"port\":$5,\"protocol\":\"http\",\"system_app\":1}" \
- -e --force-scopes
+ --force-scopes
diff --git a/scripts/dev_register.sh b/scripts/dev_register.sh
index b2f811fd..1fd027ac 100644
--- a/scripts/dev_register.sh
+++ b/scripts/dev_register.sh
@@ -14,7 +14,7 @@ echo $! > /tmp/_install.pid
python3 tests/_install_wait.py "http://localhost:9009/heartbeat" "\"status\":\"ok\"" 15 0.5
docker exec "$1" sudo -u www-data php occ app_api:app:register nc_py_api manual_install --json-info \
"{\"appid\":\"nc_py_api\",\"name\":\"nc_py_api\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"host\":\"host.docker.internal\",\"scopes\":{\"required\":[\"SYSTEM\", \"FILES\", \"FILES_SHARING\"],\"optional\":[\"USER_INFO\", \"USER_STATUS\", \"NOTIFICATIONS\", \"WEATHER_STATUS\", \"TALK\", \"TALK_BOT\", \"ACTIVITIES\", \"NOTES\"]},\"port\":9009,\"protocol\":\"http\",\"system_app\":1}" \
- -e --force-scopes
+ --force-scopes
cat /tmp/_install.pid
kill -15 "$(cat /tmp/_install.pid)"
echo "nc_py_api for $1 is ready to use"
diff --git a/tests/_install_init_handler_models.py b/tests/_install_init_handler_models.py
new file mode 100644
index 00000000..9d0f8ef0
--- /dev/null
+++ b/tests/_install_init_handler_models.py
@@ -0,0 +1,29 @@
+from fastapi import FastAPI
+from huggingface_hub import snapshot_download
+
+from nc_py_api import NextcloudApp, ex_app
+
+APP = FastAPI()
+MODEL_NAME = "MBZUAI/LaMini-T5-61M"
+
+
+def enabled_handler(_enabled: bool, _nc: NextcloudApp) -> str:
+ if _enabled:
+ try:
+ snapshot_download(MODEL_NAME, local_files_only=True)
+ except Exception: # noqa
+ return "model not found"
+ return ""
+
+
+def init_handler():
+ NextcloudApp().set_init_status(100)
+
+
+@APP.on_event("startup")
+def initialization():
+ ex_app.set_handlers(APP, enabled_handler, init_handler=init_handler, models_to_fetch=[MODEL_NAME])
+
+
+if __name__ == "__main__":
+ ex_app.run_app("_install_init_handler_models:APP", log_level="warning")
diff --git a/tests/_tests_at_the_end.py b/tests/_tests_at_the_end.py
index 04cec84d..0631678b 100644
--- a/tests/_tests_at_the_end.py
+++ b/tests/_tests_at_the_end.py
@@ -28,3 +28,26 @@ def test_ex_app_enable_disable(nc_client, nc_app):
assert nc_client.apps.ex_app_is_enabled("nc_py_api") is True
finally:
r.terminate()
+
+
+def test_install_init_handler_models(nc_client, nc_app):
+ child_environment = os.environ.copy()
+ child_environment["APP_PORT"] = os.environ.get("APP_PORT", "9009")
+ r = Popen(
+ [
+ sys.executable,
+ os.path.join(os.path.dirname(os.path.abspath(__file__)), "_install_init_handler_models.py"),
+ ],
+ env=child_environment,
+ cwd=os.getcwd(),
+ )
+ url = f"http://127.0.0.1:{child_environment['APP_PORT']}/heartbeat"
+ try:
+ if check_heartbeat(url, '"status":"ok"', 15, 0.3):
+ raise RuntimeError("`_install_init_handler_models` can not start.")
+ if nc_client.apps.ex_app_is_enabled("nc_py_api"):
+ nc_client.apps.ex_app_disable("nc_py_api")
+ nc_client.apps.ex_app_enable("nc_py_api")
+ assert nc_client.apps.ex_app_is_enabled("nc_py_api") is True
+ finally:
+ r.terminate()