diff --git a/hypha/VERSION b/hypha/VERSION
index 446f8ffb..652778b0 100644
--- a/hypha/VERSION
+++ b/hypha/VERSION
@@ -1,3 +1,3 @@
{
- "version": "0.15.46"
+ "version": "0.15.47"
}
diff --git a/hypha/built-in/echo-service.html b/hypha/built-in/echo-service.html
index 83a0ab55..c8a5b362 100644
--- a/hypha/built-in/echo-service.html
+++ b/hypha/built-in/echo-service.html
@@ -6,7 +6,7 @@
ImJoy Plugin Template
-
+
diff --git a/hypha/built-in/imjoy-plugin-parser.html b/hypha/built-in/imjoy-plugin-parser.html
index 3e1f9c09..9e5a0c85 100644
--- a/hypha/built-in/imjoy-plugin-parser.html
+++ b/hypha/built-in/imjoy-plugin-parser.html
@@ -6,7 +6,7 @@
ImJoy Plugin Template
-
+
diff --git a/hypha/built-in/playground.html b/hypha/built-in/playground.html
index 5490ba38..1f9c067f 100644
--- a/hypha/built-in/playground.html
+++ b/hypha/built-in/playground.html
@@ -7,7 +7,7 @@
-
+
+
diff --git a/hypha/core/__init__.py b/hypha/core/__init__.py
index 5a48ce90..edd8ed77 100644
--- a/hypha/core/__init__.py
+++ b/hypha/core/__init__.py
@@ -70,7 +70,7 @@ class ServiceInfo(BaseModel):
class Config:
"""Set the config for pydantic."""
- extra='allow'
+ extra = "allow"
def is_singleton(self):
"""Check if the service is singleton."""
@@ -137,7 +137,7 @@ class RDF(BaseModel):
class Config:
"""Set the config for pydantic."""
- extra='allow'
+ extra = "allow"
class ApplicationInfo(RDF):
diff --git a/hypha/core/store.py b/hypha/core/store.py
index adfc3780..203432c4 100644
--- a/hypha/core/store.py
+++ b/hypha/core/store.py
@@ -140,7 +140,9 @@ async def init(self, reset_redis, startup_functions=None):
await self.cleanup_disconnected_clients()
for service in self._public_services:
try:
- await self._public_workspace_interface.register_service(service.model_dump())
+ await self._public_workspace_interface.register_service(
+ service.model_dump()
+ )
except Exception: # pylint: disable=broad-except
logger.exception("Failed to register public service: %s", service)
raise
@@ -187,7 +189,9 @@ async def add_disconnected_client(self, client_info: ClientInfo):
await self._redis.hset(
"clients:disconnected",
f"{client_info.workspace}/{client_info.id}",
- json.dumps({"client": client_info.model_dump_json(), "timestamp": time.time()}),
+ json.dumps(
+ {"client": client_info.model_dump_json(), "timestamp": time.time()}
+ ),
)
async def remove_disconnected_client(
@@ -239,14 +243,17 @@ async def get_user_workspace(self, user_id: str):
workspace_info = await self._redis.hget("workspaces", user_id)
if workspace_info is None:
return None
- workspace_info = WorkspaceInfo.model_validate(json.loads(workspace_info.decode()))
+ workspace_info = WorkspaceInfo.model_validate(
+ json.loads(workspace_info.decode())
+ )
return workspace_info
async def get_all_users(self):
"""Get all users."""
users = await self._redis.hgetall("users")
return [
- UserInfo.model_validate(json.loads(user.decode())) for user in users.values()
+ UserInfo.model_validate(json.loads(user.decode()))
+ for user in users.values()
]
async def get_all_workspace(self):
@@ -278,14 +285,18 @@ async def register_workspace(self, workspace: dict, overwrite=False):
raise KeyError(
f"Client does not exist: {workspace.name}/{client_id}"
)
- client_info = ClientInfo.model_validate(json.loads(client_info.decode()))
+ client_info = ClientInfo.model_validate(
+ json.loads(client_info.decode())
+ )
await self._redis.srem(
f"user:{client_info.user_info.id}:clients", client_info.id
)
# assert ret >= 1, f"Client not found in user({client_info.user_info.id})'s clients list: {client_info.id}"
await self._redis.hdel(f"{workspace.name}:clients", client_id)
await self._redis.delete(f"{workspace}:clients")
- await self._redis.hset("workspaces", workspace.name, workspace.model_dump_json())
+ await self._redis.hset(
+ "workspaces", workspace.name, workspace.model_dump_json()
+ )
await self.get_workspace_manager(workspace.name, setup=True)
self._event_bus.emit("workspace_registered", workspace.model_dump())
diff --git a/hypha/core/workspace.py b/hypha/core/workspace.py
index dac19b10..5084de87 100644
--- a/hypha/core/workspace.py
+++ b/hypha/core/workspace.py
@@ -166,7 +166,9 @@ async def create_workspace(
if not overwrite and await self._redis.hexists("workspaces", workspace.name):
raise Exception(f"Workspace {workspace.name} already exists.")
- await self._redis.hset("workspaces", workspace.name, workspace.model_dump_json())
+ await self._redis.hset(
+ "workspaces", workspace.name, workspace.model_dump_json()
+ )
# Clear the workspace
await self.remove_clients(workspace.name)
workspace_info = await self.get_workspace_info(workspace.name)
@@ -630,7 +632,9 @@ async def get_workspace_info(self, workspace: str = None) -> WorkspaceInfo:
workspace_info = await self._redis.hget("workspaces", workspace)
if workspace_info is None:
raise KeyError(f"Workspace not found: {workspace}")
- workspace_info = WorkspaceInfo.model_validate(json.loads(workspace_info.decode()))
+ workspace_info = WorkspaceInfo.model_validate(
+ json.loads(workspace_info.decode())
+ )
return workspace_info
async def _get_workspace_info_dict(
@@ -819,7 +823,8 @@ async def _get_all_workspace(self):
"""Get all workspaces."""
workspaces = await self._redis.hgetall("workspaces")
return [
- WorkspaceInfo.model_validate(json.loads(v.decode())) for v in workspaces.values()
+ WorkspaceInfo.model_validate(json.loads(v.decode()))
+ for v in workspaces.values()
]
async def check_permission(
@@ -938,7 +943,9 @@ async def _update_workspace(self, config: dict, context=None):
if _id not in workspace.owners:
workspace.owners.append(_id)
workspace.owners = [o.strip() for o in workspace.owners if o.strip()]
- await self._redis.hset("workspaces", workspace.name, workspace.model_dump_json())
+ await self._redis.hset(
+ "workspaces", workspace.name, workspace.model_dump_json()
+ )
self._event_bus.emit("workspace_changed", workspace.model_dump())
async def delete_if_empty(self):
diff --git a/hypha/server.py b/hypha/server.py
index c1d3d290..9561cbc2 100644
--- a/hypha/server.py
+++ b/hypha/server.py
@@ -20,6 +20,7 @@
from hypha.triton import TritonProxy
from hypha.utils import GZipMiddleware, GzipRoute, PatchedCORSMiddleware
from hypha.websocket import WebsocketServer
+from contextlib import asynccontextmanager
try:
# For pyodide, we need to patch http
@@ -152,17 +153,6 @@ async def liveness(req: Request) -> JSONResponse:
return JSONResponse({"status": "DOWN"}, status_code=503)
- @app.on_event("startup")
- async def startup_event():
- # Here we can register all the startup functions
- args.startup_functions = args.startup_functions or []
- args.startup_functions.append("hypha.core.auth:register_login_service")
- await store.init(args.reset_redis, startup_functions=args.startup_functions)
-
- @app.on_event("shutdown")
- def shutdown_event():
- store.get_event_bus().emit("shutdown", target="local")
-
def mount_static_files(app, new_route, directory, name="static"):
# Get top level route paths
@@ -200,8 +190,19 @@ def create_application(args):
else:
args.allow_origins = env.get("ALLOW_ORIGINS", "*").split(",")
+ @asynccontextmanager
+ async def lifespan(app: FastAPI):
+ # Here we can register all the startup functions
+ args.startup_functions = args.startup_functions or []
+ args.startup_functions.append("hypha.core.auth:register_login_service")
+ await store.init(args.reset_redis, startup_functions=args.startup_functions)
+ yield
+ # Emit the shutdown event
+ store.get_event_bus().emit("shutdown", target="local")
+
application = FastAPI(
title="Hypha",
+ lifespan=lifespan,
docs_url="/api-docs",
redoc_url="/api-redoc",
description=(
diff --git a/hypha/templates/web-python-plugin.html b/hypha/templates/web-python-plugin.html
index af48d5aa..ee87422a 100644
--- a/hypha/templates/web-python-plugin.html
+++ b/hypha/templates/web-python-plugin.html
@@ -93,7 +93,7 @@
async def run():
try:
- await micropip.install(["imjoy-rpc==0.5.44", {% for req in requirements %}"{{req}}", {% endfor %}])
+ await micropip.install(["imjoy-rpc==0.5.48.post1", {% for req in requirements %}"{{req}}", {% endfor %}])
js.__resolve()
except Exception as e:
js.__reject(traceback.format_exc())
diff --git a/hypha/templates/web-worker-plugin.html b/hypha/templates/web-worker-plugin.html
index 03b91654..73df5a27 100644
--- a/hypha/templates/web-worker-plugin.html
+++ b/hypha/templates/web-worker-plugin.html
@@ -15,7 +15,7 @@
self.onmessage = function(e) {
const config = e.data
-importScripts("https://cdn.jsdelivr.net/npm/imjoy-rpc@0.5.44/dist/hypha-rpc-websocket.min.js")
+importScripts("https://cdn.jsdelivr.net/npm/imjoy-rpc@0.5.48/dist/hypha-rpc-websocket.min.js")
hyphaWebsocketClient.connectToServer(config).then(async (api)=>{
await hyphaWebsocketClient.loadRequirements([{% for req in requirements %}"{{req}}", {% endfor %}])
diff --git a/hypha/templates/window-plugin.html b/hypha/templates/window-plugin.html
index 030a9a8e..62a30447 100644
--- a/hypha/templates/window-plugin.html
+++ b/hypha/templates/window-plugin.html
@@ -6,7 +6,7 @@
ImJoy Plugin (window)
-
+
diff --git a/requirements.txt b/requirements.txt
index 0cd8f140..0ab01396 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,7 @@ aioboto3==11.2.0
aiofiles==23.2.1
base58==2.1.1
fastapi==0.104.1
-imjoy-rpc==0.5.44
+imjoy-rpc==0.5.48.post1
jinja2==3.1.2
lxml==4.9.3
msgpack==1.0.5
diff --git a/setup.py b/setup.py
index 12f06ccd..6569ae79 100644
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@
REQUIREMENTS = [
"aiofiles",
"fastapi>=0.70.0",
- "imjoy-rpc>=0.5.44",
+ "imjoy-rpc>=0.5.48.post1",
"msgpack>=1.0.2",
"numpy",
"pydantic[email]>=2.6.1",