Update pagination and return URL for Lot, Device, Event resources

This commit is contained in:
Xavier Bustamante Talavera 2018-10-05 17:13:23 +02:00
parent d1a23cbf9d
commit 4f0493c464
13 changed files with 49 additions and 9 deletions

View file

@ -5,6 +5,7 @@ from itertools import chain
from operator import attrgetter
from typing import Dict, List, Set
from boltons import urlutils
from citext import CIText
from ereuse_utils.naming import Naming
from sqlalchemy import BigInteger, Boolean, Column, Enum as DBEnum, Float, ForeignKey, Integer, \
@ -17,6 +18,7 @@ from stdnum import imei, meid
from teal.db import CASCADE, POLYMORPHIC_ID, POLYMORPHIC_ON, ResourceNotFound, URL, check_lower, \
check_range
from teal.marshmallow import ValidationError
from teal.resource import url_for_resource
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, DisplayTech, \
@ -56,9 +58,7 @@ class Device(Thing):
"""
depth = Column(Float(decimal_return_scale=3), check_range('depth', 0.1, 3))
color = Column(ColorType)
color.comment = """
"""
color.comment = """The predominant color of the device."""
@property
def events(self) -> list:
@ -93,6 +93,11 @@ class Device(Thing):
and not getattr(c, 'foreign_keys', None)
and c.key not in {'id', 'type', 'created', 'updated', 'parent_id', 'hid'}}
@property
def url(self) -> urlutils.URL:
"""The URL where to GET this device."""
return urlutils.URL(url_for_resource(Device, item_id=self.id))
@declared_attr
def __mapper_args__(cls):
"""

View file

@ -1,5 +1,6 @@
from typing import Dict, List, Set
from boltons import urlutils
from boltons.urlutils import URL
from colour import Color
from sqlalchemy import Column, Integer
@ -51,6 +52,9 @@ class Device(Thing):
self.tags = ... # type: Set[Tag]
self.lots = ... # type: Set[Lot]
@property
def url(self) -> urlutils.URL:
pass
class DisplayMixin:
technology = ... # type: Column

View file

@ -29,6 +29,7 @@ class Device(Thing):
height = Float(validate=Range(0.1, 3), unit=UnitCodes.m, description=m.Device.height.comment)
events = NestedOn('Event', many=True, dump_only=True, description=m.Device.events.__doc__)
events_one = NestedOn('Event', many=True, load_only=True, collection_class=OrderedSet)
url = URL(dump_only=True, description=m.Device.url.__doc__)
@pre_load
def from_events_to_events_one(self, data: dict):

View file

@ -114,7 +114,10 @@ class DeviceView(View):
'page': devices.page,
'perPage': devices.per_page,
'total': devices.total,
}
'previous': devices.prev_num,
'next': devices.next_num
},
'url': request.path
}
return jsonify(ret)

View file

@ -3,6 +3,7 @@ from datetime import datetime, timedelta
from typing import Set, Union
from uuid import uuid4
from boltons import urlutils
from citext import CIText
from flask import current_app as app, g
from sqlalchemy import BigInteger, Boolean, CheckConstraint, Column, DateTime, Enum as DBEnum, \
@ -17,6 +18,7 @@ from teal.db import ArrayOfEnum, CASCADE, CASCADE_OWN, INHERIT_COND, IP, POLYMOR
POLYMORPHIC_ON, StrictVersionType, URL, check_lower, check_range
from teal.enums import Country, Currency, Subdivision
from teal.marshmallow import ValidationError
from teal.resource import url_for_resource
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.agent.models import Agent
@ -163,6 +165,11 @@ class Event(Thing):
would point to the computer that contained this data storage, if any.
"""
@property
def url(self) -> urlutils.URL:
"""The URL where to GET this event."""
return urlutils.URL(url_for_resource(Event, item_id=self.id))
# noinspection PyMethodParameters
@declared_attr
def __mapper_args__(cls):

View file

@ -5,6 +5,7 @@ from distutils.version import StrictVersion
from typing import Dict, List, Set, Union
from uuid import UUID
from boltons import urlutils
from boltons.urlutils import URL
from sqlalchemy import Column
from sqlalchemy.orm import relationship
@ -62,6 +63,9 @@ class Event(Thing):
self.agent = ... # type: Agent
self.author = ... # type: User
@property
def url(self) -> urlutils.URL:
pass
class EventWithOneDevice(Event):

View file

@ -3,11 +3,11 @@ import decimal
from flask import current_app as app
from marshmallow import Schema as MarshmallowSchema, ValidationError, validates_schema
from marshmallow.fields import Boolean, DateTime, Decimal, Float, Integer, List, Nested, String, \
TimeDelta, URL, UUID
TimeDelta, UUID
from marshmallow.validate import Length, Range
from sqlalchemy.util import OrderedSet
from teal.enums import Country, Currency, Subdivision
from teal.marshmallow import EnumField, IP, SanitizedStr, Version
from teal.marshmallow import EnumField, IP, SanitizedStr, Version, URL
from teal.resource import Schema
from ereuse_devicehub.marshmallow import NestedOn
@ -38,6 +38,7 @@ class Event(Thing):
author = NestedOn(User, dump_only=True, exclude=('token',))
components = NestedOn(Component, dump_only=True, many=True)
parent = NestedOn(Computer, dump_only=True, description=m.Event.parent_id.comment)
url = URL(dump_only=True, description=m.Event.url.__doc__)
class EventWithOneDevice(Event):

View file

@ -1,6 +1,7 @@
import uuid
from datetime import datetime
from boltons import urlutils
from citext import CIText
from flask import g
from sqlalchemy import TEXT
@ -9,6 +10,7 @@ from sqlalchemy.sql import expression as exp
from sqlalchemy_utils import LtreeType
from sqlalchemy_utils.types.ltree import LQUERY
from teal.db import UUIDLtree
from teal.resource import url_for_resource
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.device.models import Device
@ -61,6 +63,11 @@ class Lot(Thing):
assert isinstance(child, uuid.UUID)
Path.delete(self.id, child)
@property
def url(self) -> urlutils.URL:
"""The URL where to GET this event."""
return urlutils.URL(url_for_resource(Lot, item_id=self.id))
@property
def children(self):
"""The children lots."""

View file

@ -3,6 +3,7 @@ from datetime import datetime
from typing import Iterable, Set, Union
from uuid import UUID
from boltons import urlutils
from sqlalchemy import Column
from sqlalchemy.orm import Query, relationship
from sqlalchemy_utils import Ltree
@ -46,6 +47,9 @@ class Lot(Thing):
def parents(self) -> LotQuery:
pass
@property
def url(self) -> urlutils.URL:
pass
class Path:
id = ... # type: Column

View file

@ -1,5 +1,5 @@
from marshmallow import fields as f
from teal.marshmallow import SanitizedStr
from teal.marshmallow import SanitizedStr, URL
from ereuse_devicehub.marshmallow import NestedOn
from ereuse_devicehub.resources.device.schemas import Device
@ -15,3 +15,4 @@ class Lot(Thing):
devices = NestedOn(Device, many=True, dump_only=True)
children = NestedOn('Lot', many=True, dump_only=True)
parents = NestedOn('Lot', many=True, dump_only=True)
url = URL(dump_only=True, description=m.Lot.url.__doc__)

View file

@ -1,7 +1,8 @@
from enum import Enum
from marshmallow import post_load
from marshmallow.fields import DateTime, List, String, URL
from marshmallow.fields import DateTime, List, String
from teal.marshmallow import URL
from teal.resource import Schema
from ereuse_devicehub.resources import models as m
@ -20,7 +21,6 @@ class UnitCodes(Enum):
class Thing(Schema):
type = String(description='Only required when it is nested.')
url = URL(dump_only=True, description='The URL of the resource.')
same_as = List(URL(dump_only=True), dump_only=True, data_key='sameAs')
updated = DateTime('iso', dump_only=True, description=m.Thing.updated.comment.strip())
created = DateTime('iso', dump_only=True, description=m.Thing.created.comment.strip())

View file

@ -30,6 +30,7 @@ class TestConfig(DevicehubConfig):
TESTING = True
ORGANIZATION_NAME = 'FooOrg'
ORGANIZATION_TAX_ID = 'foo-org-id'
SERVER_NAME = 'localhost'
@pytest.fixture(scope='session')

View file

@ -102,6 +102,8 @@ def test_device_query(user: UserClient):
"""Checks result of inventory."""
user.post(conftest.file('basic.snapshot'), res=Snapshot)
i, _ = user.get(res=Device)
assert i['url'] == '/devices/'
assert i['items'][0]['url'] == '/devices/1'
pc = next(d for d in i['items'] if d['type'] == 'Desktop')
assert len(pc['events']) == 4
assert len(pc['components']) == 3