Add Lot.parents

This commit is contained in:
Xavier Bustamante Talavera 2018-09-12 14:53:14 +02:00
parent aa52367f03
commit f7112d7fe1
5 changed files with 38 additions and 19 deletions

View File

@ -2,9 +2,9 @@ import uuid
from datetime import datetime from datetime import datetime
from flask import g from flask import g
from sqlalchemy import TEXT
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import aliased from sqlalchemy.sql import expression as exp
from sqlalchemy.sql import expression
from sqlalchemy_utils import LtreeType from sqlalchemy_utils import LtreeType
from sqlalchemy_utils.types.ltree import LQUERY from sqlalchemy_utils.types.ltree import LQUERY
from teal.db import UUIDLtree from teal.db import UUIDLtree
@ -53,22 +53,32 @@ class Lot(Thing):
Path.add(self.id, child) Path.add(self.id, child)
db.session.refresh(self) # todo is this useful? db.session.refresh(self) # todo is this useful?
def remove_child(self, child: 'Lot'): def remove_child(self, child):
if isinstance(child, Lot):
Path.delete(self.id, child.id) Path.delete(self.id, child.id)
else:
assert isinstance(child, uuid.UUID)
Path.delete(self.id, child)
@property @property
def children(self): def children(self):
"""The children lots.""" """The children lots."""
# From https://stackoverflow.com/a/41158890 # From https://stackoverflow.com/a/41158890
# todo test id = UUIDLtree.convert(self.id)
cls = self.__class__
exp = '*.{}.*{{1}}'.format(UUIDLtree.convert(self.id))
child_lots = aliased(Lot)
return self.query \ return self.query \
.join(cls.paths) \ .join(self.__class__.paths) \
.filter(Path.path.lquery(expression.cast(exp, LQUERY))) \ .filter(Path.path.lquery(exp.cast('*.{}.*{{1}}'.format(id), LQUERY)))
.join(child_lots, Path.lot)
@property
def parents(self):
"""The parent lots."""
id = UUIDLtree.convert(self.id)
i = db.func.index(Path.path, id)
parent_id = db.func.replace(exp.cast(db.func.subpath(Path.path, i - 1, i), TEXT), '_', '-')
join_clause = parent_id == exp.cast(Lot.id, TEXT)
return self.query.join(Path, join_clause).filter(
Path.path.lquery(exp.cast('*{{1}}.{}.*'.format(id), LQUERY))
)
def __contains__(self, child: 'Lot'): def __contains__(self, child: 'Lot'):
return Path.has_lot(self.id, child.id) return Path.has_lot(self.id, child.id)

View File

@ -31,7 +31,7 @@ class Lot(Thing):
def add_child(self, child: Union[Lot, uuid.UUID]): def add_child(self, child: Union[Lot, uuid.UUID]):
pass pass
def remove_child(self, child: Lot): def remove_child(self, child: Union[Lot, uuid.UUID]):
pass pass
@classmethod @classmethod
@ -42,6 +42,10 @@ class Lot(Thing):
def children(self) -> LotQuery: def children(self) -> LotQuery:
pass pass
@property
def parents(self) -> LotQuery:
pass
class Path: class Path:
id = ... # type: Column id = ... # type: Column

View File

@ -12,6 +12,5 @@ class Lot(Thing):
name = f.String(validate=f.validate.Length(max=STR_SIZE), required=True) name = f.String(validate=f.validate.Length(max=STR_SIZE), required=True)
closed = f.Boolean(missing=False, description=m.Lot.closed.comment) closed = f.Boolean(missing=False, description=m.Lot.closed.comment)
devices = NestedOn(Device, many=True, dump_only=True) devices = NestedOn(Device, many=True, dump_only=True)
children = NestedOn('Lot', children = NestedOn('Lot', many=True, dump_only=True)
many=True, parents = NestedOn('Lot', many=True, dump_only=True)
dump_only=True)

View File

@ -49,6 +49,7 @@ class LotBaseChildrenView(View):
lot = self.get_lot(id) lot = self.get_lot(id)
self._post(lot, self.get_ids()) self._post(lot, self.get_ids())
db.session.commit() db.session.commit()
ret = self.schema.jsonify(lot) ret = self.schema.jsonify(lot)
ret.status_code = 201 ret.status_code = 201
return ret return ret

View File

@ -210,10 +210,15 @@ def test_post_get_lot(user: UserClient):
def test_post_add_children_view(user: UserClient): def test_post_add_children_view(user: UserClient):
"""Tests adding children lots to a lot through the view.""" """Tests adding children lots to a lot through the view."""
l, _ = user.post(({'name': 'Parent'}), res=Lot) parent, _ = user.post(({'name': 'Parent'}), res=Lot)
child, _ = user.post(({'name': 'Child'}), res=Lot) child, _ = user.post(({'name': 'Child'}), res=Lot)
l, _ = user.post({}, res=Lot, item='{}/children'.format(l['id']), query=[('id', child['id'])]) parent, _ = user.post({},
assert l['children'][0]['id'] == child['id'] res=Lot,
item='{}/children'.format(parent['id']),
query=[('id', child['id'])])
assert parent['children'][0]['id'] == child['id']
child, _ = user.get(res=Lot, item=child['id'])
assert child['parents'][0]['id'] == parent['id']
@pytest.mark.xfail(reason='Just develop the test') @pytest.mark.xfail(reason='Just develop the test')