Add ComputerAccessory, Networking, Printer, Sound, Video devices
This commit is contained in:
parent
46f765a683
commit
10c73a4e75
14
ereuse_devicehub/dummy/files/keyboard.snapshot.yaml
Normal file
14
ereuse_devicehub/dummy/files/keyboard.snapshot.yaml
Normal file
|
@ -0,0 +1,14 @@
|
|||
type: Snapshot
|
||||
version: '1.0'
|
||||
software: Web
|
||||
device:
|
||||
type: Keyboard
|
||||
model: FOO
|
||||
serialNumber: BAR
|
||||
manufacturer: BAZ
|
||||
layout: ES
|
||||
events:
|
||||
- type: ManualRate
|
||||
appearanceRange: A
|
||||
functionalityRange: A
|
||||
labelling: False
|
|
@ -161,6 +161,121 @@ class DisplayDef(ComponentDef):
|
|||
SCHEMA = schemas.Display
|
||||
|
||||
|
||||
class ComputerAccessoryDef(DeviceDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.ComputerAccessory
|
||||
|
||||
def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
|
||||
template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
|
||||
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)
|
||||
|
||||
|
||||
class MouseDef(ComputerAccessoryDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Mouse
|
||||
|
||||
|
||||
class KeyboardDef(ComputerAccessoryDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Keyboard
|
||||
|
||||
|
||||
class SAIDef(ComputerAccessoryDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.SAI
|
||||
|
||||
|
||||
class MemoryCardReaderDef(ComputerAccessoryDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.MemoryCardReader
|
||||
|
||||
|
||||
class NetworkingDef(DeviceDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Networking
|
||||
|
||||
def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
|
||||
template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
|
||||
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)
|
||||
|
||||
|
||||
class RouterDef(NetworkingDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Router
|
||||
|
||||
|
||||
class SwitchDef(NetworkingDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Switch
|
||||
|
||||
|
||||
class HubDef(NetworkingDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Hub
|
||||
|
||||
|
||||
class WirelessAccessPointDef(NetworkingDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.WirelessAccessPoint
|
||||
|
||||
|
||||
class PrinterDef(DeviceDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Printer
|
||||
|
||||
def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
|
||||
template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
|
||||
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)
|
||||
|
||||
|
||||
class LabelPrinterDef(PrinterDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.LabelPrinter
|
||||
|
||||
|
||||
class SoundDef(DeviceDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Sound
|
||||
|
||||
def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
|
||||
template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
|
||||
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)
|
||||
|
||||
|
||||
class MicrophoneDef(SoundDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Microphone
|
||||
|
||||
|
||||
class VideoDef(DeviceDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Video
|
||||
|
||||
def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
|
||||
template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
|
||||
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)
|
||||
|
||||
|
||||
class VideoScalerDef(VideoDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.VideoScaler
|
||||
|
||||
|
||||
class VideoconferenceDef(VideoDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Videoconference
|
||||
|
||||
|
||||
class ManufacturerDef(Resource):
|
||||
VIEW = ManufacturerView
|
||||
SCHEMA = schemas.Manufacturer
|
||||
|
|
|
@ -17,12 +17,13 @@ from sqlalchemy_utils import ColorType
|
|||
from stdnum import imei, meid
|
||||
from teal.db import CASCADE, POLYMORPHIC_ID, POLYMORPHIC_ON, ResourceNotFound, URL, check_lower, \
|
||||
check_range
|
||||
from teal.enums import Layouts
|
||||
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, \
|
||||
DataStoragePrivacyCompliance, DisplayTech, RamFormat, RamInterface
|
||||
DataStoragePrivacyCompliance, DisplayTech, PrinterTechnology, RamFormat, RamInterface
|
||||
from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing
|
||||
|
||||
|
||||
|
@ -62,6 +63,19 @@ class Device(Thing):
|
|||
"""
|
||||
color = Column(ColorType)
|
||||
color.comment = """The predominant color of the device."""
|
||||
production_date = Column(db.TIMESTAMP(timezone=True))
|
||||
production_date.comment = """The date of production of the item."""
|
||||
|
||||
_NON_PHYSICAL_PROPS = {
|
||||
'id',
|
||||
'type',
|
||||
'created',
|
||||
'updated',
|
||||
'parent_id',
|
||||
'hid',
|
||||
'production_date',
|
||||
'color'
|
||||
}
|
||||
|
||||
@property
|
||||
def events(self) -> list:
|
||||
|
@ -94,7 +108,7 @@ class Device(Thing):
|
|||
for c in inspect(self.__class__).attrs
|
||||
if isinstance(c, ColumnProperty)
|
||||
and not getattr(c, 'foreign_keys', None)
|
||||
and c.key not in {'id', 'type', 'created', 'updated', 'parent_id', 'hid'}}
|
||||
and c.key not in self._NON_PHYSICAL_PROPS}
|
||||
|
||||
@property
|
||||
def url(self) -> urlutils.URL:
|
||||
|
@ -194,6 +208,11 @@ class Device(Thing):
|
|||
|
||||
|
||||
class DisplayMixin:
|
||||
"""
|
||||
Aspect ratio can be computed as in
|
||||
https://github.com/mirukan/whratio/blob/master/whratio/ratio.py and
|
||||
could be a future property.
|
||||
"""
|
||||
size = Column(Float(decimal_return_scale=2), check_range('size', 2, 150))
|
||||
size.comment = """
|
||||
The size of the monitor in inches.
|
||||
|
@ -212,6 +231,10 @@ class DisplayMixin:
|
|||
The maximum vertical resolution the monitor can natively support
|
||||
in pixels.
|
||||
"""
|
||||
refresh_rate = Column(SmallInteger, check_range('refresh_rate', 10, 1000))
|
||||
contrast_ratio = Column(SmallInteger, check_range('contrast_ratio', 100, 100000))
|
||||
touchable = Column(Boolean, nullable=False, default=False)
|
||||
touchable.comment = """Whether it is a touchscreen."""
|
||||
|
||||
def __format__(self, format_spec: str) -> str:
|
||||
v = ''
|
||||
|
@ -289,7 +312,9 @@ class Desktop(Computer):
|
|||
|
||||
|
||||
class Laptop(Computer):
|
||||
pass
|
||||
layout = Column(DBEnum(Layouts))
|
||||
layout.comment = """Layout of a built-in keyboard of the computer,
|
||||
if any."""
|
||||
|
||||
|
||||
class Server(Computer):
|
||||
|
@ -308,6 +333,10 @@ class TelevisionSet(Monitor):
|
|||
pass
|
||||
|
||||
|
||||
class Projector(Monitor):
|
||||
pass
|
||||
|
||||
|
||||
class Mobile(Device):
|
||||
id = Column(BigInteger, ForeignKey(Device.id), primary_key=True)
|
||||
imei = Column(BigInteger)
|
||||
|
@ -483,6 +512,83 @@ class Display(JoinedComponentTableMixin, DisplayMixin, Component):
|
|||
pass
|
||||
|
||||
|
||||
class ComputerAccessory(Device):
|
||||
id = Column(BigInteger, ForeignKey(Device.id), primary_key=True)
|
||||
pass
|
||||
|
||||
|
||||
class SAI(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class Keyboard(ComputerAccessory):
|
||||
layout = Column(DBEnum(Layouts)) # If we want to do it not null
|
||||
|
||||
|
||||
class Mouse(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class MemoryCardReader(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class Networking(NetworkMixin, Device):
|
||||
id = Column(BigInteger, ForeignKey(Device.id), primary_key=True)
|
||||
|
||||
|
||||
class Router(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Switch(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Hub(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class WirelessAccessPoint(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Printer(Device):
|
||||
id = Column(BigInteger, ForeignKey(Device.id), primary_key=True)
|
||||
wireless = Column(Boolean, nullable=False, default=False)
|
||||
wireless.comment = """Whether it is a wireless printer."""
|
||||
scanning = Column(Boolean, nullable=False, default=False)
|
||||
scanning.comment = """Whether the printer has scanning capabilities."""
|
||||
technology = Column(DBEnum(PrinterTechnology))
|
||||
technology.comment = """Technology used to print."""
|
||||
monochrome = Column(Boolean, nullable=False, default=True)
|
||||
monochrome.comment = """Whether the printer is only monochrome."""
|
||||
|
||||
|
||||
class LabelPrinter(Printer):
|
||||
pass
|
||||
|
||||
|
||||
class Sound(Device):
|
||||
pass
|
||||
|
||||
|
||||
class Microphone(Sound):
|
||||
pass
|
||||
|
||||
|
||||
class Video(Device):
|
||||
pass
|
||||
|
||||
|
||||
class VideoScaler(Video):
|
||||
pass
|
||||
|
||||
|
||||
class Videoconference(Video):
|
||||
pass
|
||||
|
||||
|
||||
class Manufacturer(db.Model):
|
||||
__table_args__ = {'schema': 'common'}
|
||||
CSV_DELIMITER = csv.get_dialect('excel').delimiter
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from datetime import datetime
|
||||
from typing import Dict, List, Set, Type, Union
|
||||
|
||||
from boltons import urlutils
|
||||
|
@ -6,11 +7,12 @@ from colour import Color
|
|||
from sqlalchemy import Column, Integer
|
||||
from sqlalchemy.orm import relationship
|
||||
from teal.db import Model
|
||||
from teal.enums import Layouts
|
||||
|
||||
from ereuse_devicehub.resources.agent.models import Agent
|
||||
from ereuse_devicehub.resources.device import states
|
||||
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, \
|
||||
DataStoragePrivacyCompliance, DisplayTech, RamFormat, RamInterface
|
||||
DataStoragePrivacyCompliance, DisplayTech, PrinterTechnology, RamFormat, RamInterface
|
||||
from ereuse_devicehub.resources.event import models as e
|
||||
from ereuse_devicehub.resources.image.models import ImageList
|
||||
from ereuse_devicehub.resources.lot.models import Lot
|
||||
|
@ -31,6 +33,7 @@ class Device(Thing):
|
|||
depth = ... # type: Column
|
||||
color = ... # type: Column
|
||||
lots = ... # type: relationship
|
||||
production_date = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
|
@ -52,6 +55,7 @@ class Device(Thing):
|
|||
self.images = ... # type: ImageList
|
||||
self.tags = ... # type: Set[Tag]
|
||||
self.lots = ... # type: Set[Lot]
|
||||
self.production_date = ... # type: datetime
|
||||
|
||||
@property
|
||||
def url(self) -> urlutils.URL:
|
||||
|
@ -86,6 +90,9 @@ class DisplayMixin:
|
|||
size = ... # type: Column
|
||||
resolution_width = ... # type: Column
|
||||
resolution_height = ... # type: Column
|
||||
refresh_rate = ... # type: Column
|
||||
contrast_ratio = ... # type: Column
|
||||
touchable = ... # type: Column
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
@ -93,6 +100,9 @@ class DisplayMixin:
|
|||
self.size = ... # type: Integer
|
||||
self.resolution_width = ... # type: int
|
||||
self.resolution_height = ... # type: int
|
||||
self.refresh_rate = ... # type: int
|
||||
self.contrast_ratio = ... # type: int
|
||||
self.touchable = ... # type: bool
|
||||
|
||||
|
||||
class Computer(DisplayMixin, Device):
|
||||
|
@ -135,7 +145,11 @@ class Desktop(Computer):
|
|||
|
||||
|
||||
class Laptop(Computer):
|
||||
pass
|
||||
layout = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.layout = ... # type: Layouts
|
||||
|
||||
|
||||
class Server(Computer):
|
||||
|
@ -233,12 +247,18 @@ class Motherboard(Component):
|
|||
self.pcmcia = ... # type: int
|
||||
|
||||
|
||||
class NetworkAdapter(Component):
|
||||
class NetworkMixin:
|
||||
speed = ... # type: Column
|
||||
wireless = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.speed = ... # type: int
|
||||
self.wireless = ... # type: bool
|
||||
|
||||
|
||||
class NetworkAdapter(NetworkMixin, Component):
|
||||
pass
|
||||
|
||||
|
||||
class Processor(Component):
|
||||
|
@ -271,6 +291,88 @@ class Display(DisplayMixin, Component):
|
|||
pass
|
||||
|
||||
|
||||
class ComputerAccessory(Device):
|
||||
pass
|
||||
|
||||
|
||||
class SAI(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class Keyboard(ComputerAccessory):
|
||||
layout = ... # type: Column
|
||||
|
||||
def __init__(self, layout: Layouts, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.layout = ... # type: Layouts
|
||||
|
||||
|
||||
class Mouse(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class MemoryCardReader(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class Networking(NetworkMixin, Device):
|
||||
pass
|
||||
|
||||
|
||||
class Router(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Switch(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Hub(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class WirelessAccessPoint(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Printer(Device):
|
||||
wireless = ... # type: Column
|
||||
scanning = ... # type: Column
|
||||
technology = ... # type: Column
|
||||
monochrome = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.wireless = ... # type: bool
|
||||
self.scanning = ... # type: bool
|
||||
self.technology = ... # type: PrinterTechnology
|
||||
self.monochrome = ... # type: bool
|
||||
|
||||
|
||||
class LabelPrinter(Printer):
|
||||
pass
|
||||
|
||||
|
||||
class Sound(Device):
|
||||
pass
|
||||
|
||||
|
||||
class Microphone(Sound):
|
||||
pass
|
||||
|
||||
|
||||
class Video(Device):
|
||||
pass
|
||||
|
||||
|
||||
class VideoScaler(Video):
|
||||
pass
|
||||
|
||||
|
||||
class Videoconference(Video):
|
||||
pass
|
||||
|
||||
|
||||
class Manufacturer(Model):
|
||||
CUSTOM_MANUFACTURERS = ... # type: set
|
||||
name = ... # type: Column
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
from marshmallow import post_load, pre_load
|
||||
from marshmallow.fields import Boolean, Float, Integer, List, Str, String
|
||||
from marshmallow.fields import Boolean, DateTime, Float, Integer, List, Str, String
|
||||
from marshmallow.validate import Length, OneOf, Range
|
||||
from sqlalchemy.util import OrderedSet
|
||||
from stdnum import imei, meid
|
||||
from teal.enums import Layouts
|
||||
from teal.marshmallow import EnumField, SanitizedStr, URL, ValidationError
|
||||
from teal.resource import Schema
|
||||
|
||||
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
|
||||
DataStoragePrivacyCompliance, DisplayTech, PrinterTechnology, RamFormat, RamInterface
|
||||
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE
|
||||
from ereuse_devicehub.resources.schemas import Thing, UnitCodes
|
||||
|
||||
|
@ -40,6 +41,9 @@ class Device(Thing):
|
|||
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')
|
||||
production_date = DateTime('iso',
|
||||
description=m.Device.updated.comment,
|
||||
data_key='productionDate')
|
||||
|
||||
@pre_load
|
||||
def from_events_to_events_one(self, data: dict):
|
||||
|
@ -98,6 +102,9 @@ class DisplayMixin:
|
|||
resolution_height = Integer(data_key='resolutionHeight',
|
||||
validate=Range(10, 20000),
|
||||
description=m.DisplayMixin.resolution_height.comment)
|
||||
refresh_rate = Integer(data_key='refreshRate', validate=Range(10, 1000))
|
||||
contrast_ratio = Integer(data_key='contrastRatio', validate=Range(100, 100000))
|
||||
touchable = Boolean(missing=False, description=m.DisplayMixin.touchable.comment)
|
||||
|
||||
|
||||
class NetworkMixin:
|
||||
|
@ -212,3 +219,74 @@ class Manufacturer(Schema):
|
|||
name = String(dump_only=True)
|
||||
url = URL(dump_only=True)
|
||||
logo = URL(dump_only=True)
|
||||
|
||||
|
||||
class ComputerAccessory(Device):
|
||||
pass
|
||||
|
||||
|
||||
class Mouse(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class MemoryCardReader(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class SAI(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class Keyboard(ComputerAccessory):
|
||||
layout = EnumField(Layouts)
|
||||
|
||||
|
||||
class Networking(NetworkMixin, Device):
|
||||
pass
|
||||
|
||||
|
||||
class Router(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Switch(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Hub(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class WirelessAccessPoint(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Printer(Device):
|
||||
wireless = Boolean(required=True, missing=False)
|
||||
scanning = Boolean(required=True, missing=False)
|
||||
technology = EnumField(PrinterTechnology, required=True)
|
||||
monochrome = Boolean(required=True, missing=True)
|
||||
|
||||
|
||||
class LabelPrinter(Printer):
|
||||
pass
|
||||
|
||||
|
||||
class Sound(Device):
|
||||
pass
|
||||
|
||||
|
||||
class Microphone(Sound):
|
||||
pass
|
||||
|
||||
|
||||
class Video(Device):
|
||||
pass
|
||||
|
||||
|
||||
class VideoScaler(Video):
|
||||
pass
|
||||
|
||||
|
||||
class Videoconference(Video):
|
||||
pass
|
||||
|
|
|
@ -276,3 +276,12 @@ class DataStoragePrivacyCompliance(Enum):
|
|||
return cls.EraseSectors if not erasure.error else cls.EraseSectorsError
|
||||
else:
|
||||
return cls.EraseBasic if not erasure.error else cls.EraseBasicError
|
||||
|
||||
|
||||
class PrinterTechnology(Enum):
|
||||
"""Technology of the printer."""
|
||||
Toner = 'Toner / Laser'
|
||||
Inkjet = 'Liquid inkjet'
|
||||
SolidInk = 'Solid ink'
|
||||
Dye = 'Dye-sublimation'
|
||||
Thermal = 'Thermal'
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from sqlalchemy import Column
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Column
|
||||
from teal.db import Model
|
||||
|
||||
STR_SIZE = 64
|
||||
|
@ -13,3 +14,8 @@ class Thing(Model):
|
|||
type = ... # type: str
|
||||
updated = ... # type: Column
|
||||
created = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.updated = ... # type: datetime
|
||||
self.created = ... # type: datetime
|
||||
|
|
|
@ -22,8 +22,8 @@ class UnitCodes(Enum):
|
|||
class Thing(Schema):
|
||||
type = String(description='Only required when it is nested.')
|
||||
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())
|
||||
updated = DateTime('iso', dump_only=True, description=m.Thing.updated.comment)
|
||||
created = DateTime('iso', dump_only=True, description=m.Thing.created.comment)
|
||||
|
||||
@post_load
|
||||
def remove_type(self, data: dict):
|
||||
|
|
|
@ -40,4 +40,4 @@ def test_api_docs(client: Client):
|
|||
'scheme': 'basic',
|
||||
'name': 'Authorization'
|
||||
}
|
||||
assert 75 == len(docs['definitions'])
|
||||
assert 92 == len(docs['definitions'])
|
||||
|
|
|
@ -9,14 +9,14 @@ from ereuse_utils.test import ANY
|
|||
from pytest import raises
|
||||
from sqlalchemy.util import OrderedSet
|
||||
from teal.db import ResourceNotFound
|
||||
from teal.enums import Layouts
|
||||
|
||||
from ereuse_devicehub.client import Client, UserClient
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.devicehub import Devicehub
|
||||
from ereuse_devicehub.resources.agent.models import Person
|
||||
from ereuse_devicehub.resources.device import models as d
|
||||
from ereuse_devicehub.resources.device.exceptions import NeedsId
|
||||
from ereuse_devicehub.resources.device.models import Component, ComputerMonitor, DataStorage, \
|
||||
Desktop, Device, GraphicCard, Laptop, Motherboard, NetworkAdapter
|
||||
from ereuse_devicehub.resources.device.schemas import Device as DeviceS
|
||||
from ereuse_devicehub.resources.device.sync import MismatchBetweenTags, MismatchBetweenTagsAndHid, \
|
||||
Sync
|
||||
|
@ -34,43 +34,43 @@ def test_device_model():
|
|||
"""
|
||||
Tests that the correctness of the device model and its relationships.
|
||||
"""
|
||||
pc = Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
net = NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s')
|
||||
graphic = GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
pc = d.Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
net = d.NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s')
|
||||
graphic = d.GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
pc.components.add(net)
|
||||
pc.components.add(graphic)
|
||||
db.session.add(pc)
|
||||
db.session.commit()
|
||||
pc = Desktop.query.one()
|
||||
pc = d.Desktop.query.one()
|
||||
assert pc.serial_number == 'p1s'
|
||||
assert pc.components == OrderedSet([net, graphic])
|
||||
network_adapter = NetworkAdapter.query.one()
|
||||
network_adapter = d.NetworkAdapter.query.one()
|
||||
assert network_adapter.parent == pc
|
||||
|
||||
# Removing a component from pc doesn't delete the component
|
||||
pc.components.remove(net)
|
||||
db.session.commit()
|
||||
pc = Device.query.first() # this is the same as querying for Desktop directly
|
||||
pc = d.Device.query.first() # this is the same as querying for d.Desktop directly
|
||||
assert pc.components == {graphic}
|
||||
network_adapter = NetworkAdapter.query.one()
|
||||
network_adapter = d.NetworkAdapter.query.one()
|
||||
assert network_adapter not in pc.components
|
||||
assert network_adapter.parent is None
|
||||
|
||||
# Deleting the pc deletes everything
|
||||
gcard = GraphicCard.query.one()
|
||||
gcard = d.GraphicCard.query.one()
|
||||
db.session.delete(pc)
|
||||
db.session.flush()
|
||||
assert pc.id == 1
|
||||
assert Desktop.query.first() is None
|
||||
assert d.Desktop.query.first() is None
|
||||
db.session.commit()
|
||||
assert Desktop.query.first() is None
|
||||
assert d.Desktop.query.first() is None
|
||||
assert network_adapter.id == 2
|
||||
assert NetworkAdapter.query.first() is not None, 'We removed the network adaptor'
|
||||
assert d.NetworkAdapter.query.first() is not None, 'We removed the network adaptor'
|
||||
assert gcard.id == 3, 'We should still hold a reference to a zombie graphic card'
|
||||
assert GraphicCard.query.first() is None, 'We should have deleted it –it was inside the pc'
|
||||
assert d.GraphicCard.query.first() is None, 'We should have deleted it –it was inside the pc'
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
|
@ -78,26 +78,26 @@ def test_device_schema():
|
|||
"""Ensures the user does not upload non-writable or extra fields."""
|
||||
device_s = DeviceS()
|
||||
device_s.load({'serialNumber': 'foo1', 'model': 'foo', 'manufacturer': 'bar2'})
|
||||
device_s.dump(Device(id=1))
|
||||
device_s.dump(d.Device(id=1))
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_physical_properties():
|
||||
c = Motherboard(slots=2,
|
||||
usb=3,
|
||||
serial_number='sn',
|
||||
model='ml',
|
||||
manufacturer='mr',
|
||||
width=2.0,
|
||||
color=Color())
|
||||
pc = Desktop(chassis=ComputerChassis.Tower,
|
||||
model='foo',
|
||||
manufacturer='bar',
|
||||
serial_number='foo-bar',
|
||||
weight=2.8,
|
||||
width=1.4,
|
||||
height=2.1,
|
||||
color=Color('LightSeaGreen'))
|
||||
c = d.Motherboard(slots=2,
|
||||
usb=3,
|
||||
serial_number='sn',
|
||||
model='ml',
|
||||
manufacturer='mr',
|
||||
width=2.0,
|
||||
color=Color())
|
||||
pc = d.Desktop(chassis=ComputerChassis.Tower,
|
||||
model='foo',
|
||||
manufacturer='bar',
|
||||
serial_number='foo-bar',
|
||||
weight=2.8,
|
||||
width=1.4,
|
||||
height=2.1,
|
||||
color=Color('LightSeaGreen'))
|
||||
pc.components.add(c)
|
||||
db.session.add(pc)
|
||||
db.session.commit()
|
||||
|
@ -113,7 +113,6 @@ def test_physical_properties():
|
|||
'weight': None,
|
||||
'height': None,
|
||||
'width': 2.0,
|
||||
'color': Color(),
|
||||
'depth': None
|
||||
}
|
||||
assert pc.physical_properties == {
|
||||
|
@ -124,7 +123,6 @@ def test_physical_properties():
|
|||
'width': 1.4,
|
||||
'height': 2.1,
|
||||
'depth': None,
|
||||
'color': Color('LightSeaGreen'),
|
||||
'chassis': ComputerChassis.Tower
|
||||
}
|
||||
|
||||
|
@ -132,18 +130,18 @@ def test_physical_properties():
|
|||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_component_similar_one():
|
||||
snapshot = conftest.file('pc-components.db')
|
||||
d = snapshot['device']
|
||||
pc = snapshot['device']
|
||||
snapshot['components'][0]['serial_number'] = snapshot['components'][1]['serial_number'] = None
|
||||
pc = Desktop(**d, components=OrderedSet(Component(**c) for c in snapshot['components']))
|
||||
component1, component2 = pc.components # type: Component
|
||||
pc = d.Desktop(**pc, components=OrderedSet(d.Component(**c) for c in snapshot['components']))
|
||||
component1, component2 = pc.components # type: d.Component
|
||||
db.session.add(pc)
|
||||
db.session.flush()
|
||||
# Let's create a new component named 'A' similar to 1
|
||||
componentA = Component(model=component1.model, manufacturer=component1.manufacturer)
|
||||
componentA = d.Component(model=component1.model, manufacturer=component1.manufacturer)
|
||||
similar_to_a = componentA.similar_one(pc, set())
|
||||
assert similar_to_a == component1
|
||||
# Component B does not have the same model
|
||||
componentB = Component(model='nope', manufacturer=component1.manufacturer)
|
||||
# d.Component B does not have the same model
|
||||
componentB = d.Component(model='nope', manufacturer=component1.manufacturer)
|
||||
with pytest.raises(ResourceNotFound):
|
||||
assert componentB.similar_one(pc, set())
|
||||
# If we blacklist component A we won't get anything
|
||||
|
@ -159,14 +157,14 @@ def test_add_remove():
|
|||
# c4 is not with any pc
|
||||
values = conftest.file('pc-components.db')
|
||||
pc = values['device']
|
||||
c1, c2 = (Component(**c) for c in values['components'])
|
||||
pc = Desktop(**pc, components=OrderedSet([c1, c2]))
|
||||
c1, c2 = (d.Component(**c) for c in values['components'])
|
||||
pc = d.Desktop(**pc, components=OrderedSet([c1, c2]))
|
||||
db.session.add(pc)
|
||||
c3 = Component(serial_number='nc1')
|
||||
pc2 = Desktop(serial_number='s2',
|
||||
components=OrderedSet([c3]),
|
||||
chassis=ComputerChassis.Microtower)
|
||||
c4 = Component(serial_number='c4s')
|
||||
c3 = d.Component(serial_number='nc1')
|
||||
pc2 = d.Desktop(serial_number='s2',
|
||||
components=OrderedSet([c3]),
|
||||
chassis=ComputerChassis.Microtower)
|
||||
c4 = d.Component(serial_number='c4s')
|
||||
db.session.add(pc2)
|
||||
db.session.add(c4)
|
||||
db.session.commit()
|
||||
|
@ -189,12 +187,12 @@ def test_sync_run_components_empty():
|
|||
remove all the components from the device.
|
||||
"""
|
||||
s = conftest.file('pc-components.db')
|
||||
pc = Desktop(**s['device'], components=OrderedSet(Component(**c) for c in s['components']))
|
||||
pc = d.Desktop(**s['device'], components=OrderedSet(d.Component(**c) for c in s['components']))
|
||||
db.session.add(pc)
|
||||
db.session.commit()
|
||||
|
||||
# Create a new transient non-db synced object
|
||||
pc = Desktop(**s['device'])
|
||||
pc = d.Desktop(**s['device'])
|
||||
db_pc, _ = Sync().run(pc, components=OrderedSet())
|
||||
assert not db_pc.components
|
||||
assert not pc.components
|
||||
|
@ -207,25 +205,25 @@ def test_sync_run_components_none():
|
|||
keep all the components from the device.
|
||||
"""
|
||||
s = conftest.file('pc-components.db')
|
||||
pc = Desktop(**s['device'], components=OrderedSet(Component(**c) for c in s['components']))
|
||||
pc = d.Desktop(**s['device'], components=OrderedSet(d.Component(**c) for c in s['components']))
|
||||
db.session.add(pc)
|
||||
db.session.commit()
|
||||
|
||||
# Create a new transient non-db synced object
|
||||
transient_pc = Desktop(**s['device'])
|
||||
transient_pc = d.Desktop(**s['device'])
|
||||
db_pc, _ = Sync().run(transient_pc, components=None)
|
||||
assert db_pc.components
|
||||
assert db_pc.components == pc.components
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_sync_execute_register_desktop_new_Desktop_no_tag():
|
||||
def test_sync_execute_register_desktop_new_desktop_no_tag():
|
||||
"""
|
||||
Syncs a new Desktop with HID and without a tag, creating it.
|
||||
Syncs a new d.Desktop with HID and without a tag, creating it.
|
||||
:return:
|
||||
"""
|
||||
# Case 1: device does not exist on DB
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
db_pc = Sync().execute_register(pc)
|
||||
assert pc.physical_properties == db_pc.physical_properties
|
||||
|
||||
|
@ -233,13 +231,13 @@ def test_sync_execute_register_desktop_new_Desktop_no_tag():
|
|||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_sync_execute_register_desktop_existing_no_tag():
|
||||
"""
|
||||
Syncs an existing Desktop with HID and without a tag.
|
||||
Syncs an existing d.Desktop with HID and without a tag.
|
||||
"""
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
db.session.add(pc)
|
||||
db.session.commit()
|
||||
|
||||
pc = Desktop(
|
||||
pc = d.Desktop(
|
||||
**conftest.file('pc-components.db')['device']) # Create a new transient non-db object
|
||||
# 1: device exists on DB
|
||||
db_pc = Sync().execute_register(pc)
|
||||
|
@ -249,11 +247,11 @@ def test_sync_execute_register_desktop_existing_no_tag():
|
|||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_sync_execute_register_desktop_no_hid_no_tag():
|
||||
"""
|
||||
Syncs a Desktop without HID and no tag.
|
||||
Syncs a d.Desktop without HID and no tag.
|
||||
|
||||
This should fail as we don't have a way to identify it.
|
||||
"""
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
# 1: device has no HID
|
||||
pc.hid = pc.model = None
|
||||
with pytest.raises(NeedsId):
|
||||
|
@ -263,7 +261,7 @@ def test_sync_execute_register_desktop_no_hid_no_tag():
|
|||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_sync_execute_register_desktop_tag_not_linked():
|
||||
"""
|
||||
Syncs a new Desktop with HID and a non-linked tag.
|
||||
Syncs a new d.Desktop with HID and a non-linked tag.
|
||||
|
||||
It is OK if the tag was not linked, it will be linked in this process.
|
||||
"""
|
||||
|
@ -272,24 +270,24 @@ def test_sync_execute_register_desktop_tag_not_linked():
|
|||
db.session.commit()
|
||||
|
||||
# Create a new transient non-db object
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([Tag(id='foo')]))
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([Tag(id='foo')]))
|
||||
returned_pc = Sync().execute_register(pc)
|
||||
assert returned_pc == pc
|
||||
assert tag.device == pc, 'Tag has to be linked'
|
||||
assert Desktop.query.one() == pc, 'Desktop had to be set to db'
|
||||
assert d.Desktop.query.one() == pc, 'd.Desktop had to be set to db'
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_sync_execute_register_no_hid_tag_not_linked(tag_id: str):
|
||||
"""
|
||||
Validates registering a Desktop without HID and a non-linked tag.
|
||||
Validates registering a d.Desktop without HID and a non-linked tag.
|
||||
|
||||
In this case it is ok still, as the non-linked tag proves that
|
||||
the Desktop was not existing before (otherwise the tag would
|
||||
be linked), and thus it creates a new Desktop.
|
||||
the d.Desktop was not existing before (otherwise the tag would
|
||||
be linked), and thus it creates a new d.Desktop.
|
||||
"""
|
||||
tag = Tag(id=tag_id)
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([tag]))
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([tag]))
|
||||
returned_pc = Sync().execute_register(pc)
|
||||
db.session.commit()
|
||||
assert returned_pc == pc
|
||||
|
@ -299,7 +297,7 @@ def test_sync_execute_register_no_hid_tag_not_linked(tag_id: str):
|
|||
# they have the same pk though
|
||||
assert tag != db_tag, 'They are not the same tags though'
|
||||
assert db_tag.id == tag.id
|
||||
assert Desktop.query.one() == pc, 'Desktop had to be set to db'
|
||||
assert d.Desktop.query.one() == pc, 'd.Desktop had to be set to db'
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
|
@ -310,7 +308,7 @@ def test_sync_execute_register_tag_does_not_exist():
|
|||
|
||||
Tags have to be created before trying to link them through a Snapshot.
|
||||
"""
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([Tag('foo')]))
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([Tag('foo')]))
|
||||
with raises(ResourceNotFound):
|
||||
Sync().execute_register(pc)
|
||||
|
||||
|
@ -323,11 +321,11 @@ def test_sync_execute_register_tag_linked_same_device():
|
|||
(If it has HID it validates both HID and tag point at the same
|
||||
device, this his checked in ).
|
||||
"""
|
||||
orig_pc = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
orig_pc = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
db.session.add(Tag(id='foo', device=orig_pc))
|
||||
db.session.commit()
|
||||
|
||||
pc = Desktop(
|
||||
pc = d.Desktop(
|
||||
**conftest.file('pc-components.db')['device']) # Create a new transient non-db object
|
||||
pc.tags.add(Tag(id='foo'))
|
||||
db_pc = Sync().execute_register(pc)
|
||||
|
@ -342,15 +340,15 @@ def test_sync_execute_register_tag_linked_other_device_mismatch_between_tags():
|
|||
Checks that sync raises an error if finds that at least two passed-in
|
||||
tags are not linked to the same device.
|
||||
"""
|
||||
pc1 = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc1 = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
db.session.add(Tag(id='foo-1', device=pc1))
|
||||
pc2 = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc2 = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc2.serial_number = 'pc2-serial'
|
||||
pc2.hid = Naming.hid(pc2.manufacturer, pc2.serial_number, pc2.model)
|
||||
db.session.add(Tag(id='foo-2', device=pc2))
|
||||
db.session.commit()
|
||||
|
||||
pc1 = Desktop(
|
||||
pc1 = d.Desktop(
|
||||
**conftest.file('pc-components.db')['device']) # Create a new transient non-db object
|
||||
pc1.tags.add(Tag(id='foo-1'))
|
||||
pc1.tags.add(Tag(id='foo-2'))
|
||||
|
@ -366,15 +364,15 @@ def test_sync_execute_register_mismatch_between_tags_and_hid():
|
|||
|
||||
In this case we set HID -> pc1 but tag -> pc2
|
||||
"""
|
||||
pc1 = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc1 = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
db.session.add(Tag(id='foo-1', device=pc1))
|
||||
pc2 = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc2 = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc2.serial_number = 'pc2-serial'
|
||||
pc2.hid = Naming.hid(pc2.manufacturer, pc2.serial_number, pc2.model)
|
||||
db.session.add(Tag(id='foo-2', device=pc2))
|
||||
db.session.commit()
|
||||
|
||||
pc1 = Desktop(
|
||||
pc1 = d.Desktop(
|
||||
**conftest.file('pc-components.db')['device']) # Create a new transient non-db object
|
||||
pc1.tags.add(Tag(id='foo-2'))
|
||||
with raises(MismatchBetweenTagsAndHid):
|
||||
|
@ -382,15 +380,15 @@ def test_sync_execute_register_mismatch_between_tags_and_hid():
|
|||
|
||||
|
||||
def test_get_device(app: Devicehub, user: UserClient):
|
||||
"""Checks GETting a Desktop with its components."""
|
||||
"""Checks GETting a d.Desktop with its components."""
|
||||
with app.app_context():
|
||||
pc = Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc = d.Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc.components = OrderedSet([
|
||||
NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s'),
|
||||
GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
d.NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s'),
|
||||
d.GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
])
|
||||
db.session.add(pc)
|
||||
db.session.add(Test(device=pc,
|
||||
|
@ -399,7 +397,7 @@ def test_get_device(app: Devicehub, user: UserClient):
|
|||
agent=Person(name='Timmy'),
|
||||
author=User(email='bar@bar.com')))
|
||||
db.session.commit()
|
||||
pc, _ = user.get(res=Device, item=1)
|
||||
pc, _ = user.get(res=d.Device, item=1)
|
||||
assert len(pc['events']) == 1
|
||||
assert pc['events'][0]['type'] == 'Test'
|
||||
assert pc['events'][0]['device'] == 1
|
||||
|
@ -414,46 +412,46 @@ def test_get_device(app: Devicehub, user: UserClient):
|
|||
assert pc['model'] == 'p1mo'
|
||||
assert pc['manufacturer'] == 'p1ma'
|
||||
assert pc['serialNumber'] == 'p1s'
|
||||
assert pc['type'] == 'Desktop'
|
||||
assert pc['type'] == d.Desktop.t
|
||||
|
||||
|
||||
def test_get_devices(app: Devicehub, user: UserClient):
|
||||
"""Checks GETting multiple devices."""
|
||||
with app.app_context():
|
||||
pc = Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc = d.Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc.components = OrderedSet([
|
||||
NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s'),
|
||||
GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
d.NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s'),
|
||||
d.GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
])
|
||||
pc1 = Desktop(model='p2mo',
|
||||
manufacturer='p2ma',
|
||||
serial_number='p2s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc2 = Laptop(model='p3mo',
|
||||
manufacturer='p3ma',
|
||||
serial_number='p3s',
|
||||
chassis=ComputerChassis.Netbook)
|
||||
pc1 = d.Desktop(model='p2mo',
|
||||
manufacturer='p2ma',
|
||||
serial_number='p2s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc2 = d.Laptop(model='p3mo',
|
||||
manufacturer='p3ma',
|
||||
serial_number='p3s',
|
||||
chassis=ComputerChassis.Netbook)
|
||||
db.session.add_all((pc, pc1, pc2))
|
||||
db.session.commit()
|
||||
devices, _ = user.get(res=Device)
|
||||
assert tuple(d['id'] for d in devices['items']) == (1, 2, 3, 4, 5)
|
||||
assert tuple(d['type'] for d in devices['items']) == (
|
||||
'Desktop', 'Desktop', 'Laptop', 'NetworkAdapter', 'GraphicCard'
|
||||
devices, _ = user.get(res=d.Device)
|
||||
assert tuple(dev['id'] for dev in devices['items']) == (1, 2, 3, 4, 5)
|
||||
assert tuple(dev['type'] for dev in devices['items']) == (
|
||||
d.Desktop.t, d.Desktop.t, d.Laptop.t, d.NetworkAdapter.t, d.GraphicCard.t
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_computer_monitor():
|
||||
m = ComputerMonitor(technology=DisplayTech.LCD,
|
||||
manufacturer='foo',
|
||||
model='bar',
|
||||
serial_number='foo-bar',
|
||||
resolution_width=1920,
|
||||
resolution_height=1080,
|
||||
size=14.5)
|
||||
m = d.ComputerMonitor(technology=DisplayTech.LCD,
|
||||
manufacturer='foo',
|
||||
model='bar',
|
||||
serial_number='foo-bar',
|
||||
resolution_width=1920,
|
||||
resolution_height=1080,
|
||||
size=14.5)
|
||||
db.session.add(m)
|
||||
db.session.commit()
|
||||
|
||||
|
@ -489,7 +487,7 @@ def test_manufacturer_enforced():
|
|||
def test_device_properties_format(app: Devicehub, user: UserClient):
|
||||
user.post(file('asus-eee-1000h.snapshot.11'), res=m.Snapshot)
|
||||
with app.app_context():
|
||||
pc = Laptop.query.one() # type: Laptop
|
||||
pc = d.Laptop.query.one() # type: d.Laptop
|
||||
assert format(pc) == 'Laptop 1: model 1000h, S/N 94oaaq021116'
|
||||
assert format(pc, 't') == 'Netbook 1000h'
|
||||
assert format(pc, 's') == '(asustek computer inc.) S/N 94OAAQ021116'
|
||||
|
@ -497,12 +495,12 @@ def test_device_properties_format(app: Devicehub, user: UserClient):
|
|||
assert pc.data_storage_size == 152627
|
||||
assert pc.graphic_card_model == 'mobile 945gse express integrated graphics controller'
|
||||
assert pc.processor_model == 'intel atom cpu n270 @ 1.60ghz'
|
||||
net = next(c for c in pc.components if isinstance(c, NetworkAdapter))
|
||||
net = next(c for c in pc.components if isinstance(c, d.NetworkAdapter))
|
||||
assert format(net) == 'NetworkAdapter 2: model ar8121/ar8113/ar8114 ' \
|
||||
'gigabit or fast ethernet, S/N 00:24:8c:7f:cf:2d'
|
||||
assert format(net, 't') == 'NetworkAdapter ar8121/ar8113/ar8114 gigabit or fast ethernet'
|
||||
assert format(net, 's') == '(qualcomm atheros) S/N 00:24:8C:7F:CF:2D – 100 Mbps'
|
||||
hdd = next(c for c in pc.components if isinstance(c, DataStorage))
|
||||
hdd = next(c for c in pc.components if isinstance(c, d.DataStorage))
|
||||
assert format(hdd) == 'HardDrive 7: model st9160310as, S/N 5sv4tqa6'
|
||||
assert format(hdd, 't') == 'HardDrive st9160310as'
|
||||
assert format(hdd, 's') == '(seagate) S/N 5SV4TQA6 – 152 GB'
|
||||
|
@ -510,6 +508,26 @@ def test_device_properties_format(app: Devicehub, user: UserClient):
|
|||
|
||||
def test_device_public(user: UserClient, client: Client):
|
||||
s, _ = user.post(file('asus-eee-1000h.snapshot.11'), res=m.Snapshot)
|
||||
html, _ = client.get(res=Device, item=s['device']['id'], accept=ANY)
|
||||
html, _ = client.get(res=d.Device, item=s['device']['id'], accept=ANY)
|
||||
assert 'intel atom cpu n270 @ 1.60ghz' in html
|
||||
assert 'S/N 00:24:8C:7F:CF:2D – 100 Mbps' in html
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_computer_accessory_model():
|
||||
sai = d.SAI()
|
||||
db.session.add(sai)
|
||||
keyboard = d.Keyboard(layout=Layouts.ES)
|
||||
db.session.add(keyboard)
|
||||
mouse = d.Mouse()
|
||||
db.session.add(mouse)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_networking_model():
|
||||
router = d.Router(speed=1000, wireless=True)
|
||||
db.session.add(router)
|
||||
switch = d.Switch(speed=1000, wireless=False)
|
||||
db.session.add(switch)
|
||||
db.session.commit()
|
||||
|
|
|
@ -411,3 +411,10 @@ def snapshot_and_check(user: UserClient,
|
|||
return snapshot_and_check(user, input_snapshot, event_types, perform_second_snapshot=False)
|
||||
else:
|
||||
return snapshot
|
||||
|
||||
|
||||
def test_snapshot_keyboard(user: UserClient):
|
||||
s = file('keyboard.snapshot')
|
||||
snapshot = snapshot_and_check(user, s, event_types=('ManualRate',))
|
||||
keyboard = snapshot['device']
|
||||
assert keyboard['layout'] == 'ES'
|
||||
|
|
Reference in a new issue