From 7cfae43c7a8e1be329ef4ca3ddc5a8b966398317 Mon Sep 17 00:00:00 2001 From: Xavier Bustamante Talavera Date: Thu, 20 Sep 2018 18:25:47 +0200 Subject: [PATCH] Add / remove devices from lots with POST / DELETE --- ereuse_devicehub/dummy/dummy.py | 12 +++++--- ereuse_devicehub/resources/device/models.pyi | 4 +-- ereuse_devicehub/resources/lot/__init__.py | 12 +++++--- ereuse_devicehub/resources/lot/models.py | 2 +- ereuse_devicehub/resources/lot/views.py | 19 +++++++------ tests/test_lot.py | 30 +++++++++++++++++--- 6 files changed, 56 insertions(+), 23 deletions(-) diff --git a/ereuse_devicehub/dummy/dummy.py b/ereuse_devicehub/dummy/dummy.py index f4ffac78..8da2d93c 100644 --- a/ereuse_devicehub/dummy/dummy.py +++ b/ereuse_devicehub/dummy/dummy.py @@ -12,6 +12,7 @@ from ereuse_devicehub.db import db from ereuse_devicehub.resources.agent.models import Person from ereuse_devicehub.resources.event import models as m from ereuse_devicehub.resources.inventory import Inventory +from ereuse_devicehub.resources.lot.models import Lot from ereuse_devicehub.resources.tag.model import Tag from ereuse_devicehub.resources.user import User @@ -89,11 +90,14 @@ class Dummy: }, res=m.Event) - from tests.test_lot import test_post_add_children_view, test_post_add_device_view - test_post_add_children_view(user) + from tests.test_lot import test_post_add_children_view + child_id = test_post_add_children_view(user) - # todo this does not add devices to lots - test_post_add_device_view(user) + lot, _ = user.post({}, + res=Lot, + item='{}/devices'.format(child_id), + query=[('id', pc) for pc in itertools.islice(pcs, len(pcs) // 3)]) + assert len(lot['devices']) print('⭐ Done.') diff --git a/ereuse_devicehub/resources/device/models.pyi b/ereuse_devicehub/resources/device/models.pyi index 6d86d728..9b376fa0 100644 --- a/ereuse_devicehub/resources/device/models.pyi +++ b/ereuse_devicehub/resources/device/models.pyi @@ -26,7 +26,7 @@ class Device(Thing): height = ... # type: Column depth = ... # type: Column color = ... # type: Column - parents = ... # type: relationship + lots = ... # type: relationship def __init__(self, **kwargs) -> None: super().__init__(**kwargs) @@ -47,7 +47,7 @@ class Device(Thing): self.events_one = ... # type: Set[EventWithOneDevice] self.images = ... # type: ImageList self.tags = ... # type: Set[Tag] - self.parents = ... # type: Set[Lot] + self.lots = ... # type: Set[Lot] class DisplayMixin: diff --git a/ereuse_devicehub/resources/lot/__init__.py b/ereuse_devicehub/resources/lot/__init__.py index 46d17120..fe68df71 100644 --- a/ereuse_devicehub/resources/lot/__init__.py +++ b/ereuse_devicehub/resources/lot/__init__.py @@ -20,13 +20,17 @@ class LotDef(Resource): root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()): super().__init__(app, import_name, static_folder, static_url_path, template_folder, url_prefix, subdomain, url_defaults, root_path, cli_commands) - children = LotChildrenView.as_view('lot-children', definition=self, auth=app.auth) + lot_children = LotChildrenView.as_view('lot-children', definition=self, auth=app.auth) + if self.AUTH: + lot_children = app.auth.requires_auth(lot_children) self.add_url_rule('/<{}:{}>/children'.format(self.ID_CONVERTER.value, self.ID_NAME), - view_func=children, + view_func=lot_children, methods={'POST', 'DELETE'}) - children = LotDeviceView.as_view('lot-device', definition=self, auth=app.auth) + lot_device = LotDeviceView.as_view('lot-device', definition=self, auth=app.auth) + if self.AUTH: + lot_device = app.auth.requires_auth(lot_device) self.add_url_rule('/<{}:{}>/devices'.format(self.ID_CONVERTER.value, self.ID_NAME), - view_func=children, + view_func=lot_device, methods={'POST', 'DELETE'}) def init_db(self, db: 'db.SQLAlchemy'): diff --git a/ereuse_devicehub/resources/lot/models.py b/ereuse_devicehub/resources/lot/models.py index ecc9d066..930288db 100644 --- a/ereuse_devicehub/resources/lot/models.py +++ b/ereuse_devicehub/resources/lot/models.py @@ -23,7 +23,7 @@ class Lot(Thing): A closed lot cannot be modified anymore. """ devices = db.relationship(Device, - backref=db.backref('parents', lazy=True, collection_class=set), + backref=db.backref('lots', lazy=True, collection_class=set), secondary=lambda: LotDevice.__table__, collection_class=set) """ diff --git a/ereuse_devicehub/resources/lot/views.py b/ereuse_devicehub/resources/lot/views.py index 1320a48c..a06f9cca 100644 --- a/ereuse_devicehub/resources/lot/views.py +++ b/ereuse_devicehub/resources/lot/views.py @@ -6,6 +6,7 @@ from flask import 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 @@ -30,9 +31,6 @@ class LotBaseChildrenView(View): lots from a lot. """ - class ListArgs(ma.Schema): - id = ma.fields.List(ma.fields.UUID()) - def __init__(self, definition: 'Resource', **kw) -> None: super().__init__(definition, **kw) self.list_args = self.ListArgs() @@ -73,6 +71,9 @@ class LotChildrenView(LotBaseChildrenView): Ex. ``lot//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? @@ -88,9 +89,11 @@ class LotDeviceView(LotBaseChildrenView): Ex. ``lot//devices/id=X&id=Y``. """ - def _post(self, lot: Lot, ids: Set[uuid.UUID]): - # todo this works? - lot.devices |= ids + class ListArgs(ma.Schema): + id = ma.fields.List(ma.fields.Integer()) - def _delete(self, lot: Lot, ids: Set[uuid.UUID]): - lot.devices -= ids + 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))) diff --git a/tests/test_lot.py b/tests/test_lot.py index c3c91b2b..295e80cb 100644 --- a/tests/test_lot.py +++ b/tests/test_lot.py @@ -3,6 +3,7 @@ from flask import g from ereuse_devicehub.client import UserClient from ereuse_devicehub.db import db +from ereuse_devicehub.devicehub import Devicehub from ereuse_devicehub.resources.device.models import Desktop from ereuse_devicehub.resources.enums import ComputerChassis from ereuse_devicehub.resources.lot.models import Lot, LotDevice @@ -38,7 +39,7 @@ def test_lot_device_relationship(): assert lot_device.lot_id == lot.id assert lot_device.created assert lot_device.author_id == g.user.id - assert device.parents == {lot} + assert device.lots == {lot} @pytest.mark.usefixtures(conftest.auth_app_context.__name__) @@ -219,8 +220,29 @@ 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'] -@pytest.mark.xfail(reason='Just develop the test') -def test_post_add_device_view(user: UserClient): - pass +def test_lot_post_add_remove_device_view(app: Devicehub, user: UserClient): + """Tests adding a device to a lot using POST and + removing it with DELETE.""" + with app.app_context(): + device = Desktop(serial_number='foo', + model='bar', + manufacturer='foobar', + chassis=ComputerChassis.Lunchbox) + db.session.add(device) + db.session.commit() + device_id = device.id + parent, _ = user.post(({'name': 'lot'}), res=Lot) + lot, _ = user.post({}, + res=Lot, + item='{}/devices'.format(parent['id']), + query=[('id', device_id)]) + assert lot['devices'][0]['id'] == device_id + # Remove the device + lot, _ = user.delete(res=Lot, + item='{}/devices'.format(parent['id']), + query=[('id', device_id)], + status=200) + assert not len(lot['devices'])