adds API versioning

This commit is contained in:
Mose Müller 2024-07-25 13:24:34 +02:00
parent e659ca9d1c
commit 0e73239d08
5 changed files with 72 additions and 38 deletions

View File

@ -0,0 +1,24 @@
import logging
import aiohttp.web
import aiohttp_middlewares.error
import pydase.server.web_server.api.v1.application
from pydase.data_service.state_manager import StateManager
logger = logging.getLogger(__name__)
def create_api_application(state_manager: StateManager) -> aiohttp.web.Application:
api_application = aiohttp.web.Application(
middlewares=(aiohttp_middlewares.error.error_middleware(),)
)
api_application.add_subapp(
"/v1/",
pydase.server.web_server.api.v1.application.create_api_application(
state_manager
),
)
return api_application

View File

@ -1,45 +1,25 @@
import logging import logging
from typing import Any from typing import TYPE_CHECKING
import aiohttp.web import aiohttp.web
import aiohttp_middlewares.error import aiohttp_middlewares.error
from pydase.data_service.state_manager import StateManager from pydase.data_service.state_manager import StateManager
from pydase.server.web_server.sio_setup import TriggerMethodDict, UpdateDict from pydase.server.web_server.api.v1.endpoints import (
from pydase.utils.helpers import get_object_attr_from_path get_value,
from pydase.utils.serialization.deserializer import loads trigger_method,
update_value,
)
from pydase.utils.serialization.serializer import dump from pydase.utils.serialization.serializer import dump
from pydase.utils.serialization.types import SerializedObject
if TYPE_CHECKING:
from pydase.server.web_server.sio_setup import TriggerMethodDict, UpdateDict
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
API_VERSION = "v1" API_VERSION = "v1"
def update_value(state_manager: StateManager, data: UpdateDict) -> None:
path = data["access_path"]
state_manager.set_service_attribute_value_by_path(
path=path, serialized_value=data["value"]
)
def get_value(state_manager: StateManager, access_path: str) -> SerializedObject:
return state_manager._data_service_cache.get_value_dict_from_cache(access_path)
def trigger_method(state_manager: StateManager, data: TriggerMethodDict) -> Any:
method = get_object_attr_from_path(state_manager.service, data["access_path"])
serialized_args = data.get("args", None)
args = loads(serialized_args) if serialized_args else []
serialized_kwargs = data.get("kwargs", None)
kwargs: dict[str, Any] = loads(serialized_kwargs) if serialized_kwargs else {}
return dump(method(*args, **kwargs))
def create_api_application(state_manager: StateManager) -> aiohttp.web.Application: def create_api_application(state_manager: StateManager) -> aiohttp.web.Application:
api_application = aiohttp.web.Application( api_application = aiohttp.web.Application(
middlewares=(aiohttp_middlewares.error.error_middleware(),) middlewares=(aiohttp_middlewares.error.error_middleware(),)
@ -47,8 +27,6 @@ def create_api_application(state_manager: StateManager) -> aiohttp.web.Applicati
async def _get_value(request: aiohttp.web.Request) -> aiohttp.web.Response: async def _get_value(request: aiohttp.web.Request) -> aiohttp.web.Response:
logger.info("Handle api request: %s", request) logger.info("Handle api request: %s", request)
api_version = request.match_info["version"]
logger.info("Version number: %s", api_version)
access_path = request.rel_url.query["access_path"] access_path = request.rel_url.query["access_path"]
@ -81,8 +59,8 @@ def create_api_application(state_manager: StateManager) -> aiohttp.web.Applicati
logger.exception(e) logger.exception(e)
return aiohttp.web.json_response(dump(e)) return aiohttp.web.json_response(dump(e))
api_application.router.add_get("/{version}/get_value", _get_value) api_application.router.add_get("/get_value", _get_value)
api_application.router.add_post("/{version}/update_value", _update_value) api_application.router.add_post("/update_value", _update_value)
api_application.router.add_post("/{version}/trigger_method", _trigger_method) api_application.router.add_post("/trigger_method", _trigger_method)
return api_application return api_application

View File

@ -0,0 +1,32 @@
from typing import Any
from pydase.data_service.state_manager import StateManager
from pydase.server.web_server.sio_setup import TriggerMethodDict, UpdateDict
from pydase.utils.helpers import get_object_attr_from_path
from pydase.utils.serialization.deserializer import loads
from pydase.utils.serialization.serializer import dump
from pydase.utils.serialization.types import SerializedObject
def update_value(state_manager: StateManager, data: UpdateDict) -> None:
path = data["access_path"]
state_manager.set_service_attribute_value_by_path(
path=path, serialized_value=data["value"]
)
def get_value(state_manager: StateManager, access_path: str) -> SerializedObject:
return state_manager._data_service_cache.get_value_dict_from_cache(access_path)
def trigger_method(state_manager: StateManager, data: TriggerMethodDict) -> Any:
method = get_object_attr_from_path(state_manager.service, data["access_path"])
serialized_args = data.get("args", None)
args = loads(serialized_args) if serialized_args else []
serialized_kwargs = data.get("kwargs", None)
kwargs: dict[str, Any] = loads(serialized_kwargs) if serialized_kwargs else {}
return dump(method(*args, **kwargs))

View File

@ -11,7 +11,7 @@ else:
import click import click
import socketio # type: ignore[import-untyped] import socketio # type: ignore[import-untyped]
import pydase.server.web_server.api import pydase.server.web_server.api.v1.endpoints
import pydase.utils.serialization.deserializer import pydase.utils.serialization.deserializer
import pydase.utils.serialization.serializer import pydase.utils.serialization.serializer
from pydase.data_service.data_service_observer import DataServiceObserver from pydase.data_service.data_service_observer import DataServiceObserver
@ -145,7 +145,7 @@ def setup_sio_events(sio: socketio.AsyncServer, state_manager: StateManager) ->
@sio.event @sio.event
async def update_value(sid: str, data: UpdateDict) -> SerializedObject | None: async def update_value(sid: str, data: UpdateDict) -> SerializedObject | None:
try: try:
pydase.server.web_server.api.update_value( pydase.server.web_server.api.v1.endpoints.update_value(
state_manager=state_manager, data=data state_manager=state_manager, data=data
) )
except Exception as e: except Exception as e:
@ -156,7 +156,7 @@ def setup_sio_events(sio: socketio.AsyncServer, state_manager: StateManager) ->
@sio.event @sio.event
async def get_value(sid: str, access_path: str) -> SerializedObject: async def get_value(sid: str, access_path: str) -> SerializedObject:
try: try:
return pydase.server.web_server.api.get_value( return pydase.server.web_server.api.v1.endpoints.get_value(
state_manager=state_manager, access_path=access_path state_manager=state_manager, access_path=access_path
) )
except Exception as e: except Exception as e:
@ -166,7 +166,7 @@ def setup_sio_events(sio: socketio.AsyncServer, state_manager: StateManager) ->
@sio.event @sio.event
async def trigger_method(sid: str, data: TriggerMethodDict) -> Any: async def trigger_method(sid: str, data: TriggerMethodDict) -> Any:
try: try:
return pydase.server.web_server.api.trigger_method( return pydase.server.web_server.api.v1.endpoints.trigger_method(
state_manager=state_manager, data=data state_manager=state_manager, data=data
) )
except Exception as e: except Exception as e: