refactoring and fixing some problems of manual merge

This commit is contained in:
Cayo Puigdefabregas 2020-10-28 13:30:22 +01:00
parent 0106728e4f
commit fe3f038218

View file

@ -6,10 +6,13 @@ import marshmallow
from flask import g, current_app as app, render_template, request, Response
from flask.json import jsonify
from flask_sqlalchemy import Pagination
from sqlalchemy.util import OrderedSet
from marshmallow import fields, fields as f, validate as v, Schema as MarshmallowSchema
from teal import query
from teal.db import ResourceNotFound
from teal.cache import cache
from teal.resource import View
from teal.marshmallow import ValidationError
from ereuse_devicehub import auth
from ereuse_devicehub.db import db
@ -183,7 +186,7 @@ class DeviceMergeView(View):
return ret
@auth.Auth.requires_auth
def merge_devices(self, dev1_id, dev2_id):
def merge_devices(self, dev1_id: int, dev2_id: int) -> Device:
"""Merge the current device with `with_device` (dev2_id) by
adding all `with_device` actions under the current device, (dev1_id).
@ -191,45 +194,57 @@ class DeviceMergeView(View):
many models in session.
"""
# base_device = Device.query.filter_by(id=dev1_id, owner_id=g.user.id).one()
base_device = Device.query.filter_by(id=dev1_id).one()
with_device = Device.query.filter_by(id=dev2_id).one()
snapshots = sorted(
filterfalse(lambda x: not isinstance(x, actions.Snapshot), (base_device.actions + with_device.actions)))
workbench_snapshots = [s for s in snapshots if
s.software == (SnapshotSoftware.Workbench or SnapshotSoftware.WorkbenchAndroid)]
latest_snapshot_device = [d for d in (base_device, with_device) if d.id == snapshots[-1].device.id][0]
latest_snapshotworkbench_device = \
[d for d in (base_device, with_device) if d.id == workbench_snapshots[-1].device.id][0]
# Adding actions of with_device
with_actions_one = [a for a in with_device.actions if isinstance(a, actions.ActionWithOneDevice)]
with_actions_multiple = [a for a in with_device.actions if isinstance(a, actions.ActionWithMultipleDevices)]
self.base_device = Device.query.filter_by(id=dev1_id).one()
self.with_device = Device.query.filter_by(id=dev2_id).one()
if not self.base_device.type == self.with_device.type:
# Validation than we are speaking of the same kind of devices
raise ValidationError('The devices is not the same type.')
# Adding actions of self.with_device
with_actions_one = [a for a in self.with_device.actions
if isinstance(a, actions.ActionWithOneDevice)]
with_actions_multiple = [a for a in self.with_device.actions
if isinstance(a, actions.ActionWithMultipleDevices)]
# Moving the tags from `with_device` to `base_device`
# Union of tags the device had plus the (potentially) new ones
self.base_device.tags |= self.with_device.tags
self.with_device.tags.clear() # We don't want to add the transient dummy tags
# db.session.add(self.with_device)
# Moving the actions from `with_device` to `base_device`
for action in with_actions_one:
if action.parent:
action.parent = base_device
action.parent = self.base_device
else:
base_device.actions_one.add(action)
self.base_device.actions_one.add(action)
for action in with_actions_multiple:
if action.parent:
action.parent = base_device
action.parent = self.base_device
else:
base_device.actions_multiple.add(action)
self.base_device.actions_multiple.add(action)
# Keeping the components of latest SnapshotWorkbench
# base_device.components = latest_snapshotworkbench_device.components
base_device.components = with_device.components
# Keeping the components of with_device
components = OrderedSet(c for c in self.with_device.components)
self.base_device.components = components
# Properties from latest Snapshot
# Properties from with_device
self.merge()
base_device.type = with_device.type
base_device.hid = with_device.hid
base_device.manufacturer = with_device.manufacturer
base_device.model = with_device.model
base_device.chassis = with_device.chassis
db.session().add(base_device)
db.session().add(self.base_device)
db.session().final_flush()
return base_device
return self.base_device
def merge(self):
"""Copies the physical properties of the base_device to the with_device.
This method mutates base_device.
"""
for field_name, value in self.with_device.physical_properties.items():
if value is not None:
setattr(self.base_device, field_name, value)
self.base_device.hid = self.with_device.hid
class ManufacturerView(View):