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/device/schemas.py

215 lines
7.4 KiB
Python
Raw Normal View History

from marshmallow import post_load, pre_load
from marshmallow.fields import Boolean, Float, Integer, List, Str, String
from marshmallow.validate import Length, OneOf, Range
from sqlalchemy.util import OrderedSet
from stdnum import imei, meid
2018-09-30 17:40:28 +00:00
from teal.marshmallow import EnumField, SanitizedStr, URL, ValidationError
from teal.resource import Schema
2018-06-20 21:18:15 +00:00
from ereuse_devicehub.marshmallow import NestedOn
from ereuse_devicehub.resources.device import models as m, states
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, \
DataStoragePrivacyCompliance, DisplayTech, RamFormat, RamInterface
2018-06-20 21:18:15 +00:00
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE
from ereuse_devicehub.resources.schemas import Thing, UnitCodes
2018-04-10 15:06:39 +00:00
class Device(Thing):
2018-06-26 13:35:13 +00:00
id = Integer(description=m.Device.id.comment, dump_only=True)
hid = SanitizedStr(lower=True, dump_only=True, description=m.Device.hid.comment)
tags = NestedOn('Tag',
many=True,
collection_class=OrderedSet,
description='The set of tags that identify the device.')
model = SanitizedStr(lower=True, validate=Length(max=STR_BIG_SIZE))
manufacturer = SanitizedStr(lower=True, validate=Length(max=STR_SIZE))
serial_number = SanitizedStr(lower=True, data_key='serialNumber')
weight = Float(validate=Range(0.1, 5), unit=UnitCodes.kgm, description=m.Device.weight.comment)
width = Float(validate=Range(0.1, 5), unit=UnitCodes.m, description=m.Device.width.comment)
height = Float(validate=Range(0.1, 5), unit=UnitCodes.m, description=m.Device.height.comment)
depth = Float(validate=Range(0.1, 5), unit=UnitCodes.m, description=m.Device.depth.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__)
lots = NestedOn('Lot',
many=True,
dump_only=True,
description='The lots where this device is directly under.')
rate = NestedOn('AggregateRate', dump_only=True, description=m.Device.rate.__doc__)
price = NestedOn('Price', dump_only=True, description=m.Device.price.__doc__)
trading = EnumField(states.Trading, dump_only=True, description=m.Device.trading.__doc__)
physical = EnumField(states.Physical, dump_only=True, description=m.Device.physical.__doc__)
physical_possessor = NestedOn('Agent', dump_only=True, data_key='physicalPossessor')
@pre_load
def from_events_to_events_one(self, data: dict):
"""
Not an elegant way of allowing submitting events to a device
(in the context of Snapshots) without creating an ``events``
field at the model (which is not possible).
:param data:
:return:
"""
# Note that it is secure to allow uploading events_one
# as the only time an user can send a device object is
# in snapshots.
data['events_one'] = data.pop('events', [])
return data
@post_load
def validate_snapshot_events(self, data):
"""Validates that only snapshot-related events can be uploaded."""
2018-06-19 16:38:42 +00:00
from ereuse_devicehub.resources.event.models import EraseBasic, Test, Rate, Install, \
Benchmark
for event in data['events_one']:
2018-06-19 16:38:42 +00:00
if not isinstance(event, (Install, EraseBasic, Rate, Test, Benchmark)):
raise ValidationError('You cannot upload {}'.format(event), field_names=['events'])
2018-04-10 15:06:39 +00:00
class Computer(Device):
components = NestedOn('Component', many=True, dump_only=True, collection_class=OrderedSet)
2018-06-26 13:35:13 +00:00
chassis = EnumField(ComputerChassis, required=True)
ram_size = Integer(dump_only=True, data_key='ramSize')
data_storage_size = Integer(dump_only=True, data_key='dataStorageSize')
processor_model = Str(dump_only=True, data_key='processorModel')
graphic_card_model = Str(dump_only=True, data_key='graphicCardModel')
network_speeds = List(Integer(dump_only=True), dump_only=True, data_key='networkSpeeds')
2018-04-10 15:06:39 +00:00
class Desktop(Computer):
pass
class Laptop(Computer):
pass
2018-06-26 13:35:13 +00:00
class Server(Computer):
2018-04-10 15:06:39 +00:00
pass
2018-06-26 13:35:13 +00:00
class DisplayMixin:
size = Float(description=m.DisplayMixin.size.comment, validate=Range(2, 150))
technology = EnumField(DisplayTech,
description=m.DisplayMixin.technology.comment)
resolution_width = Integer(data_key='resolutionWidth',
validate=Range(10, 20000),
description=m.DisplayMixin.resolution_width.comment)
resolution_height = Integer(data_key='resolutionHeight',
validate=Range(10, 20000),
description=m.DisplayMixin.resolution_height.comment)
class NetworkMixin:
speed = Integer(validate=Range(min=10, max=10000),
unit=UnitCodes.mbps,
description=m.NetworkAdapter.speed.comment)
wireless = Boolean(required=True)
2018-06-26 13:35:13 +00:00
class Monitor(DisplayMixin, Device):
2018-04-10 15:06:39 +00:00
pass
2018-06-26 13:35:13 +00:00
class ComputerMonitor(Monitor):
2018-04-10 15:06:39 +00:00
pass
2018-06-26 13:35:13 +00:00
class TelevisionSet(Monitor):
pass
class Mobile(Device):
imei = Integer(description=m.Mobile.imei.comment)
meid = Str(description=m.Mobile.meid.comment)
2018-06-26 13:35:13 +00:00
@pre_load
def convert_check_imei(self, data):
if data.get('imei', None):
data['imei'] = int(imei.validate(data['imei']))
return data
@pre_load
def convert_check_meid(self, data: dict):
if data.get('meid', None):
2018-06-26 13:35:13 +00:00
data['meid'] = meid.compact(data['meid'])
class Smartphone(Mobile):
pass
class Tablet(Mobile):
pass
class Cellphone(Mobile):
pass
2018-06-20 21:18:15 +00:00
2018-04-10 15:06:39 +00:00
class Component(Device):
parent = NestedOn(Device, dump_only=True)
2018-04-10 15:06:39 +00:00
class GraphicCard(Component):
2018-04-27 17:16:43 +00:00
memory = Integer(validate=Range(0, 10000),
unit=UnitCodes.mbyte,
2018-06-26 13:35:13 +00:00
description=m.GraphicCard.memory.comment)
2018-04-10 15:06:39 +00:00
2018-06-10 16:47:49 +00:00
class DataStorage(Component):
2018-04-27 17:16:43 +00:00
size = Integer(validate=Range(0, 10 ** 8),
unit=UnitCodes.mbyte,
2018-06-26 13:35:13 +00:00
description=m.DataStorage.size.comment)
2018-07-02 10:52:54 +00:00
interface = EnumField(DataStorageInterface)
privacy = EnumField(DataStoragePrivacyCompliance, dump_only=True)
2018-04-10 15:06:39 +00:00
2018-06-10 16:47:49 +00:00
class HardDrive(DataStorage):
pass
class SolidStateDrive(DataStorage):
pass
2018-04-10 15:06:39 +00:00
class Motherboard(Component):
2018-07-02 10:52:54 +00:00
slots = Integer(validate=Range(0, 20),
2018-06-26 13:35:13 +00:00
description=m.Motherboard.slots.comment)
2018-04-10 15:06:39 +00:00
usb = Integer(validate=Range(0, 20))
firewire = Integer(validate=Range(0, 20))
serial = Integer(validate=Range(0, 20))
pcmcia = Integer(validate=Range(0, 20))
2018-06-26 13:36:21 +00:00
class NetworkAdapter(NetworkMixin, Component):
pass
2018-04-27 17:16:43 +00:00
class Processor(Component):
speed = Float(validate=Range(min=0.1, max=15), unit=UnitCodes.ghz)
cores = Integer(validate=Range(min=1, max=10))
threads = Integer(validate=Range(min=1, max=20))
address = Integer(validate=OneOf({8, 16, 32, 64, 128, 256}))
2018-04-27 17:16:43 +00:00
class RamModule(Component):
size = Integer(validate=Range(min=128, max=17000), unit=UnitCodes.mbyte)
speed = Integer(validate=Range(min=100, max=10000), unit=UnitCodes.mhz)
2018-06-12 14:50:05 +00:00
interface = EnumField(RamInterface)
format = EnumField(RamFormat)
2018-06-26 13:36:21 +00:00
2018-07-02 10:52:54 +00:00
class SoundCard(Component):
pass
2018-06-26 13:36:21 +00:00
class Display(DisplayMixin, Component):
pass
2018-09-30 17:40:28 +00:00
class Manufacturer(Schema):
name = String(dump_only=True)
url = URL(dump_only=True)
logo = URL(dump_only=True)