This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
devicehub-teal/ereuse_devicehub/resources/lot/views.py

144 lines
4.2 KiB
Python

import uuid
from collections import deque
from typing import List, Set
import marshmallow as ma
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, Path
class LotView(View):
def post(self):
l = request.get_json()
lot = Lot(**l)
db.session.add(lot)
db.session.commit()
ret = self.schema.jsonify(lot)
ret.status_code = 201
return ret
def one(self, id: uuid.UUID):
"""Gets one event."""
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
lots from a lot.
"""
def __init__(self, definition: 'Resource', **kw) -> None:
super().__init__(definition, **kw)
self.list_args = self.ListArgs()
def get_ids(self) -> Set[uuid.UUID]:
args = self.QUERY_PARSER.parse(self.list_args, request, locations=('querystring',))
return set(args['id'])
def get_lot(self, id: uuid.UUID) -> Lot:
return Lot.query.filter_by(id=id).one()
# noinspection PyMethodOverriding
def post(self, id: uuid.UUID):
lot = self.get_lot(id)
self._post(lot, self.get_ids())
db.session.commit()
ret = self.schema.jsonify(lot)
ret.status_code = 201
return ret
def delete(self, id: uuid.UUID):
lot = self.get_lot(id)
self._delete(lot, self.get_ids())
db.session.commit()
return self.schema.jsonify(lot)
def _post(self, lot: Lot, ids: Set[uuid.UUID]):
raise NotImplementedError
def _delete(self, lot: Lot, ids: Set[uuid.UUID]):
raise NotImplementedError
class LotChildrenView(LotBaseChildrenView):
"""View for adding and removing child lots from a lot.
Ex. ``lot/<id>/children/id=X&id=Y``.
"""
class ListArgs(ma.Schema):
id = ma.fields.List(ma.fields.UUID())
def _post(self, lot: Lot, ids: Set[uuid.UUID]):
for id in ids:
lot.add_child(id) # todo what to do if child exists already?
def _delete(self, lot: Lot, ids: Set[uuid.UUID]):
for id in ids:
lot.remove_child(id)
class LotDeviceView(LotBaseChildrenView):
"""View for adding and removing child devices from a lot.
Ex. ``lot/<id>/devices/id=X&id=Y``.
"""
class ListArgs(ma.Schema):
id = ma.fields.List(ma.fields.Integer())
def _post(self, lot: Lot, ids: Set[int]):
lot.devices.update(Device.query.filter(Device.id.in_(ids)))
def _delete(self, lot: Lot, ids: Set[int]):
lot.devices.difference_update(Device.query.filter(Device.id.in_(ids)))