Fix tags not added to device search

This commit is contained in:
Xavier Bustamante Talavera 2018-10-18 10:09:10 +02:00
parent 4b763ed1e8
commit 03871b4462
9 changed files with 68 additions and 46 deletions

View file

@ -226,6 +226,10 @@ class Computer(Device):
id = Column(BigInteger, ForeignKey(Device.id), primary_key=True) id = Column(BigInteger, ForeignKey(Device.id), primary_key=True)
chassis = Column(DBEnum(ComputerChassis), nullable=False) chassis = Column(DBEnum(ComputerChassis), nullable=False)
def __init__(self, chassis, **kwargs) -> None:
chassis = ComputerChassis(chassis)
super().__init__(chassis=chassis, **kwargs)
@property @property
def events(self) -> list: def events(self) -> list:
return sorted(chain(super().events, self.events_parent), key=attrgetter('created')) return sorted(chain(super().events, self.events_parent), key=attrgetter('created'))

View file

@ -1,3 +1,5 @@
from itertools import chain
import inflection import inflection
from sqlalchemy.dialects import postgresql from sqlalchemy.dialects import postgresql
from sqlalchemy.dialects.postgresql import TSVECTOR from sqlalchemy.dialects.postgresql import TSVECTOR
@ -37,21 +39,24 @@ class DeviceSearch(db.Model):
@classmethod @classmethod
def update_modified_devices(cls, session: db.Session): def update_modified_devices(cls, session: db.Session):
"""Updates the documents of the devices that are part of a modified """Updates the documents of the devices that are part of a
event in the passed-in session. modified event, or tag in the passed-in session.
This method is registered as a SQLAlchemy This method is registered as a SQLAlchemy listener in the
listener in the Devicehub class. Devicehub class.
""" """
devices_to_update = set() devices_to_update = set()
for event in (e for e in session.new if isinstance(e, Event)): for model in chain(session.new, session.dirty):
if isinstance(event, EventWithMultipleDevices): if isinstance(model, Event):
devices_to_update |= event.devices if isinstance(model, EventWithMultipleDevices):
elif isinstance(event, EventWithOneDevice): devices_to_update |= model.devices
devices_to_update.add(event.device) elif isinstance(model, EventWithOneDevice):
if event.parent: devices_to_update.add(model.device)
devices_to_update.add(event.parent) if model.parent:
devices_to_update |= event.components devices_to_update.add(model.parent)
devices_to_update |= model.components
elif isinstance(model, Tag) and model.device:
devices_to_update.add(model.device)
# this flush is controversial: # this flush is controversial:
# see https://groups.google.com/forum/#!topic/sqlalchemy/hBzfypgPfYo # see https://groups.google.com/forum/#!topic/sqlalchemy/hBzfypgPfYo

View file

@ -229,7 +229,7 @@ class Sync:
if adding: if adding:
# For the components we are adding, let's remove them from their old parents # For the components we are adding, let's remove them from their old parents
def g_parent(component: Component) -> Device: def g_parent(component: Component) -> Device:
return component.parent or Computer(id=0) # Computer with id 0 is our Identity return component.parent or Device(id=0) # Computer with id 0 is our Identity
for parent, _components in groupby(sorted(adding, key=g_parent), key=g_parent): for parent, _components in groupby(sorted(adding, key=g_parent), key=g_parent):
if parent.id != 0: # Is not Computer Identity if parent.id != 0: # Is not Computer Identity

View file

@ -18,7 +18,6 @@ from ereuse_devicehub.resources.device.exceptions import NeedsId
from ereuse_devicehub.resources.device.models import Component, ComputerMonitor, DataStorage, \ from ereuse_devicehub.resources.device.models import Component, ComputerMonitor, DataStorage, \
Desktop, Device, GraphicCard, Laptop, Motherboard, NetworkAdapter Desktop, Device, GraphicCard, Laptop, Motherboard, NetworkAdapter
from ereuse_devicehub.resources.device.schemas import Device as DeviceS from ereuse_devicehub.resources.device.schemas import Device as DeviceS
from ereuse_devicehub.resources.device.search import DeviceSearch
from ereuse_devicehub.resources.device.sync import MismatchBetweenTags, MismatchBetweenTagsAndHid, \ from ereuse_devicehub.resources.device.sync import MismatchBetweenTags, MismatchBetweenTagsAndHid, \
Sync Sync
from ereuse_devicehub.resources.enums import ComputerChassis, DisplayTech from ereuse_devicehub.resources.enums import ComputerChassis, DisplayTech
@ -474,20 +473,6 @@ def test_computer_with_display():
pass pass
def test_device_search_all_devices_token_if_empty(app: Devicehub, user: UserClient):
"""Ensures DeviceSearch can regenerate itself when the table is empty."""
user.post(file('basic.snapshot'), res=m.Snapshot)
with app.app_context():
app.db.session.execute('TRUNCATE TABLE {}'.format(DeviceSearch.__table__.name))
app.db.session.commit()
i, _ = user.get(res=Device, query=[('search', 'Desktop')])
assert not len(i['items'])
with app.app_context():
DeviceSearch.set_all_devices_tokens_if_empty(app.db.session)
i, _ = user.get(res=Device, query=[('search', 'Desktop')])
assert not len(i['items'])
def test_manufacturer(user: UserClient): def test_manufacturer(user: UserClient):
m, r = user.get(res='Manufacturer', query=[('name', 'asus')]) m, r = user.get(res='Manufacturer', query=[('name', 'asus')])
assert m == {'items': [{'name': 'Asus', 'url': 'https://en.wikipedia.org/wiki/Asus'}]} assert m == {'items': [{'name': 'Asus', 'url': 'https://en.wikipedia.org/wiki/Asus'}]}
@ -528,10 +513,3 @@ def test_device_public(user: UserClient, client: Client):
html, _ = client.get(res=Device, item=s['device']['id'], accept=ANY) html, _ = client.get(res=Device, item=s['device']['id'], accept=ANY)
assert 'intel atom cpu n270 @ 1.60ghz' in html assert 'intel atom cpu n270 @ 1.60ghz' in html
assert 'S/N 00:24:8C:7F:CF:2D 100 Mbps' in html assert 'S/N 00:24:8C:7F:CF:2D 100 Mbps' in html
@pytest.mark.xfail(reason='Functionality not yet developed.')
def test_device_search_multiple_tags(user: UserClient):
"""Ensures that users can search multiple tags at once
and get their multiple devices."""
pass

View file

@ -6,6 +6,7 @@ from ereuse_devicehub.db import db
from ereuse_devicehub.devicehub import Devicehub from ereuse_devicehub.devicehub import Devicehub
from ereuse_devicehub.resources.device.models import Desktop, Device, Laptop, Processor, \ from ereuse_devicehub.resources.device.models import Desktop, Device, Laptop, Processor, \
SolidStateDrive SolidStateDrive
from ereuse_devicehub.resources.device.search import DeviceSearch
from ereuse_devicehub.resources.device.views import Filters, Sorting from ereuse_devicehub.resources.device.views import Filters, Sorting
from ereuse_devicehub.resources.enums import ComputerChassis from ereuse_devicehub.resources.enums import ComputerChassis
from ereuse_devicehub.resources.event.models import Snapshot from ereuse_devicehub.resources.event.models import Snapshot
@ -174,6 +175,21 @@ def test_device_lots_query(user: UserClient):
pass pass
def test_device_search_all_devices_token_if_empty(app: Devicehub, user: UserClient):
"""Ensures DeviceSearch can regenerate itself when the table is empty."""
user.post(file('basic.snapshot'), res=Snapshot)
with app.app_context():
app.db.session.execute('TRUNCATE TABLE {}'.format(DeviceSearch.__table__.name))
app.db.session.commit()
i, _ = user.get(res=Device, query=[('search', 'Desktop')])
assert not len(i['items'])
with app.app_context():
DeviceSearch.set_all_devices_tokens_if_empty(app.db.session)
app.db.session.commit()
i, _ = user.get(res=Device, query=[('search', 'Desktop')])
assert i['items']
def test_device_query_search(user: UserClient): def test_device_query_search(user: UserClient):
# todo improve # todo improve
user.post(file('basic.snapshot'), res=Snapshot) user.post(file('basic.snapshot'), res=Snapshot)

View file

@ -112,7 +112,10 @@ def test_install():
@pytest.mark.usefixtures(conftest.auth_app_context.__name__) @pytest.mark.usefixtures(conftest.auth_app_context.__name__)
def test_update_components_event_one(): def test_update_components_event_one():
computer = Desktop(serial_number='sn1', model='ml1', manufacturer='mr1') computer = Desktop(serial_number='sn1',
model='ml1',
manufacturer='mr1',
chassis=ComputerChassis.Tower)
hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar') hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar')
computer.components.add(hdd) computer.components.add(hdd)
@ -137,7 +140,10 @@ def test_update_components_event_one():
@pytest.mark.usefixtures(conftest.auth_app_context.__name__) @pytest.mark.usefixtures(conftest.auth_app_context.__name__)
def test_update_components_event_multiple(): def test_update_components_event_multiple():
computer = Desktop(serial_number='sn1', model='ml1', manufacturer='mr1') computer = Desktop(serial_number='sn1',
model='ml1',
manufacturer='mr1',
chassis=ComputerChassis.Tower)
hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar') hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar')
computer.components.add(hdd) computer.components.add(hdd)
@ -163,7 +169,10 @@ def test_update_components_event_multiple():
@pytest.mark.usefixtures(conftest.auth_app_context.__name__) @pytest.mark.usefixtures(conftest.auth_app_context.__name__)
def test_update_parent(): def test_update_parent():
computer = Desktop(serial_number='sn1', model='ml1', manufacturer='mr1') computer = Desktop(serial_number='sn1',
model='ml1',
manufacturer='mr1',
chassis=ComputerChassis.Tower)
hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar') hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar')
computer.components.add(hdd) computer.components.add(hdd)

View file

@ -51,7 +51,7 @@ def test_rate():
appearance_range=AppearanceRange.A, appearance_range=AppearanceRange.A,
functionality_range=FunctionalityRange.A functionality_range=FunctionalityRange.A
) )
pc = Desktop() pc = Desktop(chassis=ComputerChassis.Tower)
hdd = HardDrive(size=476940) hdd = HardDrive(size=476940)
hdd.events_one.add(BenchmarkDataStorage(read_speed=126, write_speed=29.8)) hdd.events_one.add(BenchmarkDataStorage(read_speed=126, write_speed=29.8))
cpu = Processor(cores=2, speed=3.4) cpu = Processor(cores=2, speed=3.4)

View file

@ -15,7 +15,7 @@ Excluded cases in tests
import pytest import pytest
from ereuse_devicehub.resources.device.models import Desktop, HardDrive, Processor, RamModule from ereuse_devicehub.resources.device.models import Desktop, HardDrive, Processor, RamModule
from ereuse_devicehub.resources.enums import AppearanceRange, FunctionalityRange from ereuse_devicehub.resources.enums import AppearanceRange, ComputerChassis, FunctionalityRange
from ereuse_devicehub.resources.event.models import BenchmarkDataStorage, BenchmarkProcessor, \ from ereuse_devicehub.resources.event.models import BenchmarkDataStorage, BenchmarkProcessor, \
WorkbenchRate WorkbenchRate
from ereuse_devicehub.resources.event.rate.workbench.v1_0 import DataStorageRate, ProcessorRate, \ from ereuse_devicehub.resources.event.rate.workbench.v1_0 import DataStorageRate, ProcessorRate, \
@ -307,7 +307,7 @@ def test_rate_computer_rate():
""" """
# Create a new Computer with components characteristics of pc with id = 1193 # Create a new Computer with components characteristics of pc with id = 1193
pc_test = Desktop() pc_test = Desktop(chassis=ComputerChassis.Tower)
data_storage = HardDrive(size=476940) data_storage = HardDrive(size=476940)
data_storage.events_one.add(BenchmarkDataStorage(read_speed=126, write_speed=29.8)) data_storage.events_one.add(BenchmarkDataStorage(read_speed=126, write_speed=29.8))
cpu = Processor(cores=2, speed=3.4) cpu = Processor(cores=2, speed=3.4)
@ -333,7 +333,7 @@ def test_rate_computer_rate():
assert round(rate_pc.rating, 2) == 4.61 assert round(rate_pc.rating, 2) == 4.61
# Create a new Computer with components characteristics of pc with id = 1201 # Create a new Computer with components characteristics of pc with id = 1201
pc_test = Desktop() pc_test = Desktop(chassis=ComputerChassis.Tower)
data_storage = HardDrive(size=476940) data_storage = HardDrive(size=476940)
data_storage.events_one.add(BenchmarkDataStorage(read_speed=158, write_speed=34.7)) data_storage.events_one.add(BenchmarkDataStorage(read_speed=158, write_speed=34.7))
cpu = Processor(cores=2, speed=3.3) cpu = Processor(cores=2, speed=3.3)
@ -358,7 +358,7 @@ def test_rate_computer_rate():
assert round(rate_pc.rating, 2) == 3.48 assert round(rate_pc.rating, 2) == 3.48
# Create a new Computer with components characteristics of pc with id = 79 # Create a new Computer with components characteristics of pc with id = 79
pc_test = Desktop() pc_test = Desktop(chassis=ComputerChassis.Tower)
data_storage = HardDrive(size=76319) data_storage = HardDrive(size=76319)
data_storage.events_one.add(BenchmarkDataStorage(read_speed=72.2, write_speed=24.3)) data_storage.events_one.add(BenchmarkDataStorage(read_speed=72.2, write_speed=24.3))
cpu = Processor(cores=1, speed=1.6) cpu = Processor(cores=1, speed=1.6)
@ -386,7 +386,7 @@ def test_rate_computer_rate():
assert round(rate_pc.rating, 2) == 1.58 assert round(rate_pc.rating, 2) == 1.58
# Create a new Computer with components characteristics of pc with id = 798 # Create a new Computer with components characteristics of pc with id = 798
pc_test = Desktop() pc_test = Desktop(chassis=ComputerChassis.Tower)
data_storage = HardDrive(size=152587) data_storage = HardDrive(size=152587)
data_storage.events_one.add(BenchmarkDataStorage(read_speed=78.1, write_speed=24.4)) data_storage.events_one.add(BenchmarkDataStorage(read_speed=78.1, write_speed=24.4))
cpu = Processor(cores=2, speed=2.5) cpu = Processor(cores=2, speed=2.5)

View file

@ -155,8 +155,11 @@ def test_tag_create_etags_cli(app: Devicehub, user: UserClient):
assert tag.provider == URL('https://t.ereuse.org') assert tag.provider == URL('https://t.ereuse.org')
def test_tag_manual_link(app: Devicehub, user: UserClient): def test_tag_manual_link_search(app: Devicehub, user: UserClient):
"""Tests linking manually a tag through PUT /tags/<id>/device/<id>""" """Tests linking manually a tag through PUT /tags/<id>/device/<id>
Checks search has the term.
"""
with app.app_context(): with app.app_context():
db.session.add(Tag('foo-bar', secondary='foo-sec')) db.session.add(Tag('foo-bar', secondary='foo-sec'))
desktop = Desktop(serial_number='foo', chassis=ComputerChassis.AllInOne) desktop = Desktop(serial_number='foo', chassis=ComputerChassis.AllInOne)
@ -179,6 +182,13 @@ def test_tag_manual_link(app: Devicehub, user: UserClient):
# cannot link to another device when already linked # cannot link to another device when already linked
user.put({}, res=Tag, item='foo-bar/device/99', status=LinkedToAnotherDevice) user.put({}, res=Tag, item='foo-bar/device/99', status=LinkedToAnotherDevice)
i, _ = user.get(res=Device, query=[('search', 'foo-bar')])
assert i['items']
i, _ = user.get(res=Device, query=[('search', 'foo-sec')])
assert i['items']
i, _ = user.get(res=Device, query=[('search', 'foo')])
assert i['items']
@pytest.mark.usefixtures(conftest.app_context.__name__) @pytest.mark.usefixtures(conftest.app_context.__name__)
def test_tag_secondary_workbench_link_find(user: UserClient): def test_tag_secondary_workbench_link_find(user: UserClient):