Skip to content

Commit

Permalink
Merge branch 'main' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
denniswittich committed Feb 12, 2024
2 parents 37c7d5d + daa1e99 commit d9656dc
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 6 deletions.
4 changes: 4 additions & 0 deletions learning_loop_node/data_classes/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ def save(self):
del self_as_dict['model_root_path']
f.write(json.dumps(self_as_dict))

@staticmethod
def from_dict(data: Dict) -> 'ModelInformation':
return from_dict(ModelInformation, data=data)


@dataclass(**KWONLY_SLOTS)
class ErrorConfiguration():
Expand Down
2 changes: 0 additions & 2 deletions learning_loop_node/detector/detector_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ class DetectorLogic():
def __init__(self, model_format: str) -> None:
self.model_format: str = model_format
self._model_info: Optional[ModelInformation] = None
self.target_model: Optional[str] = None

async def soft_reload(self):
self._model_info = None
self.target_model = None

@property
def model_info(self) -> ModelInformation:
Expand Down
8 changes: 5 additions & 3 deletions learning_loop_node/detector/detector_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
from fastapi_socketio import SocketManager
from socketio import AsyncClient

from ..data_classes import (Category, Context, Detections, DetectionStatus,
ModelInformation, NodeState, Shape)
from ..data_classes import Category, Context, Detections, DetectionStatus, ModelInformation, NodeState, Shape
from ..data_classes.socket_response import SocketResponse
from ..data_exchanger import DataExchanger, DownloadError
from ..globals import GLOBALS
Expand All @@ -24,6 +23,7 @@
from .detector_logic import DetectorLogic
from .inbox_filter.relevance_filter import RelevanceFilter
from .outbox import Outbox
from .rest import about as rest_about
from .rest import backdoor_controls
from .rest import detect as rest_detect
from .rest import operation_mode as rest_mode
Expand All @@ -50,11 +50,13 @@ def __init__(self, name: str, detector: DetectorLogic, uuid: Optional[str] = Non
self.loop_communicator)

self.relevance_filter: RelevanceFilter = RelevanceFilter(self.outbox)
self.target_model = None
self.target_model: Optional[str] = None

self.include_router(rest_detect.router, tags=["detect"])
self.include_router(rest_upload.router, prefix="")
self.include_router(rest_mode.router, tags=["operation_mode"])
self.include_router(rest_about.router, tags=["about"])

if use_backdoor_controls:
self.include_router(backdoor_controls.router)

Expand Down
24 changes: 24 additions & 0 deletions learning_loop_node/detector/rest/about.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

from typing import TYPE_CHECKING

from fastapi import APIRouter, Request

if TYPE_CHECKING:
from ..detector_node import DetectorNode

router = APIRouter()


@router.get("/about")
async def get_about(request: Request):
'''
Example Usage
curl http://localhost/about
'''
app: 'DetectorNode' = request.app
return {
'operation_mode': app.operation_mode.value,
'state': app.status.state,
'model_info': app.detector_logic._model_info, # pylint: disable=protected-access
'target_model': app.target_model, # pylint: disable=protected-access
}
4 changes: 4 additions & 0 deletions learning_loop_node/detector/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ def should_have_segmentations(request) -> bool:

@pytest.fixture()
async def test_detector_node():
"""Initializes and runs a detector testnode. Note that the running instance and the one the function returns are not the same instances!"""

os.environ['ORGANIZATION'] = 'zauberzeug'
os.environ['PROJECT'] = 'demo'

Expand All @@ -46,6 +48,8 @@ async def test_detector_node():

multiprocessing.set_start_method('fork', force=True)
assert multiprocessing.get_start_method() == 'fork'
# print('\n\n',multiprocessing.get_start_method())

proc = Process(target=uvicorn.run,
args=(node,),
kwargs={
Expand Down
16 changes: 16 additions & 0 deletions learning_loop_node/detector/tests/test_client_communication.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import asyncio
import json

import pytest
import requests

from learning_loop_node import DetectorNode
from learning_loop_node.data_classes import Category, ModelInformation
from learning_loop_node.detector.tests.conftest import get_outbox_files
from learning_loop_node.globals import GLOBALS

Expand Down Expand Up @@ -84,3 +86,17 @@ async def test_sio_upload(test_detector_node: DetectorNode, sio_client):
result = await sio_client.call('upload', {'image': image_bytes})
assert result is None
assert len(get_outbox_files(test_detector_node.outbox)) == 2, 'There should be one image and one .json file.'


async def test_about_endpoint(test_detector_node: DetectorNode):
await asyncio.sleep(1)
response = requests.get(f'http://localhost:{GLOBALS.detector_port}/about', timeout=30)

assert response.status_code == 200
response_dict = json.loads(response.content)
model_information = ModelInformation.from_dict(response_dict['model_info'])

assert response_dict['operation_mode'] == 'idle'
assert response_dict['state'] == 'online'
assert response_dict['target_model'] == '1.1'
assert any([c.name == 'purple point' for c in model_information.categories])
2 changes: 1 addition & 1 deletion learning_loop_node/detector/tests/testing_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from learning_loop_node import DetectorLogic
from learning_loop_node.conftest import get_dummy_detections
from learning_loop_node.data_classes import Detections
from learning_loop_node.data_classes import Category, Detections, ModelInformation


class TestingDetectorLogic(DetectorLogic):
Expand Down

0 comments on commit d9656dc

Please sign in to comment.