diff --git a/ereuse_devicehub/resources/lot/views.py b/ereuse_devicehub/resources/lot/views.py index a06f9cca..13bbe80c 100644 --- a/ereuse_devicehub/resources/lot/views.py +++ b/ereuse_devicehub/resources/lot/views.py @@ -1,13 +1,14 @@ import uuid -from typing import Set +from collections import deque +from typing import List, Set import marshmallow as ma -from flask import request +from flask import jsonify, request from teal.resource import View from ereuse_devicehub.db import db from ereuse_devicehub.resources.device.models import Device -from ereuse_devicehub.resources.lot.models import Lot +from ereuse_devicehub.resources.lot.models import Lot, Path class LotView(View): @@ -25,6 +26,49 @@ class LotView(View): lot = Lot.query.filter_by(id=id).one() # type: Lot return self.schema.jsonify(lot) + def find(self, args: dict): + """Returns all lots as required for DevicehubClient:: + + [ + {title: 'lot1', + nodes: [{title: 'child1', nodes:[]}] + ] + """ + nodes = [] + for model in Path.query: # type: Path + path = deque(model.path.path.split('.')) + self._p(nodes, path) + return jsonify({ + 'items': nodes, + 'url': request.path + }) + + def _p(self, nodes: List[dict], path: deque): + """Recursively creates the nested lot structure. + + Every recursive step consumes path (a deque of lot_id), + trying to find it as the value of id in nodes, otherwise + it adds itself. Then moves to the node's children. + """ + lot_id = uuid.UUID(path.popleft().replace('_', '-')) + try: + # does lot_id exist already in node? + node = next(part for part in nodes if lot_id == part['id']) + except StopIteration: + lot = Lot.query.filter_by(id=lot_id).one() + node = { + 'id': lot_id, + 'title': lot.name, + 'url': lot.url.to_text(), + 'closed': lot.closed, + 'updated': lot.updated, + 'created': lot.created, + 'nodes': [] + } + nodes.append(node) + if path: + self._p(node['nodes'], path) + class LotBaseChildrenView(View): """Base class for adding / removing children devices and diff --git a/tests/test_lot.py b/tests/test_lot.py index 295e80cb..a9a11d85 100644 --- a/tests/test_lot.py +++ b/tests/test_lot.py @@ -122,7 +122,7 @@ def test_lot_multiple_parents(): @pytest.mark.usefixtures(conftest.auth_app_context.__name__) -def test_lot_unite_graphs(): +def test_lot_unite_graphs_and_find(): """Adds and removes children uniting already existing graphs. 1 3 @@ -220,7 +220,12 @@ def test_post_add_children_view(user: UserClient): assert parent['children'][0]['id'] == child['id'] child, _ = user.get(res=Lot, item=child['id']) assert child['parents'][0]['id'] == parent['id'] - return child['id'] + + lots = user.get(res=Lot)[0]['items'] + assert len(lots) == 1 + assert lots[0]['title'] == 'Parent' + assert len(lots[0]['nodes']) == 1 + assert lots[0]['nodes'][0]['title'] == 'Child' def test_lot_post_add_remove_device_view(app: Devicehub, user: UserClient):