Skip to content
Snippets Groups Projects
Commit b46c3f860ccb authored by Denis Laxalde's avatar Denis Laxalde
Browse files

Add a hook to trigger cloning upon setting of <clone_rtype> relation

parent 3f7468af1f56
No related branches found
No related tags found
No related merge requests found
......@@ -173,6 +173,14 @@
else:
clones[child] = copy_entity(child, **kwargs)
@property
def clone(self):
"""The entity being cloned from this entity (the original) or None."""
rset = self.entity.related(self.rtype, role=self.role, limit=1)
if rset:
return rset.get_entity(0, 0)
return None
class IContained(EntityAdapter):
"""Abstract adapter for entities which are part of a container.
......
hooks.py 0 → 100644
# copyright 2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr -- mailto:contact@logilab.fr
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
"""cubicweb-compound specific hooks and operations"""
from cubicweb.predicates import objectify_predicate
from cubicweb.server import hook
@objectify_predicate
def match_clone_rtype(cls, req, *args, **kwargs):
"""Return 1 if `rtype` found in context matches with the `rtype` attribute
of a registered IClonable adapter bound to any of the entities
corresponding to `eidfrom` or `eidto` eids found in context.
"""
rtype = kwargs.get('rtype')
if rtype is None:
return 0
for eidrole in ('eidfrom', 'eidto'):
entity = req.entity_from_eid(kwargs[eidrole])
adapted = entity.cw_adapt_to('IClonable')
if adapted and adapted.rtype == rtype:
return 1
return 0
class CloneEntityHook(hook.Hook):
"""Trigger cloning of an entity upon addition of a <clone_of> relation.
"""
__regid__ = 'compound.clone_entity_hook'
__select__ = hook.Hook.__select__ & match_clone_rtype()
events = ('after_add_relation', )
def __call__(self):
for eid in (self.eidfrom, self.eidto):
original = self._cw.entity_from_eid(eid)
adapted = original.cw_adapt_to('IClonable')
if adapted:
clone = adapted.clone
if clone:
break
else:
raise AssertionError(
'{} unexpectedly selected'.format(self.__regid__))
adapted.clone_into(clone)
......@@ -185,6 +185,17 @@
self.assertEqual(alice2.name, u'alice')
self.assertEqual([x.eid for x in alice2.knows], [bob.eid])
def test_clone_property(self):
"""Test .clone property of IClonableAdapter."""
with self.admin_access.repo_cnx() as cnx:
bob = cnx.create_entity('Agent', name=u'bob')
cnx.commit()
self.assertIsNone(bob.cw_adapt_to('IClonable').clone)
bobby = cnx.create_entity('Agent', name=u'bobby', clone_of=bob)
cnx.commit()
self.assertEqual(bob.cw_adapt_to('IClonable').clone, bobby)
self.assertIsNone(bobby.cw_adapt_to('IClonable').clone)
def test_clone_simple(self):
with self.admin_access.repo_cnx() as cnx:
bob = cnx.create_entity('Agent', name=u'bob')
......@@ -238,6 +249,26 @@
rset=entity.as_rset())
self.assertIsInstance(action, CloneAction)
def test_clone_hook(self):
with self.admin_access.repo_cnx() as cnx:
agent = cnx.create_entity('Agent', name=u'bob')
account = cnx.create_entity('OnlineAccount', reverse_account=agent)
bio = cnx.create_entity('Biography', reverse_biography=agent)
event = cnx.create_entity('Event', reverse_event=bio)
anecdote1 = cnx.create_entity('Anecdote', reverse_event=bio)
anecdote2 = cnx.create_entity('Anecdote', reverse_event=bio, narrated_by=agent)
cnx.commit()
with self.new_access(u'georges').repo_cnx() as cnx:
bob = cnx.find('Agent', name=u'bob').one()
clone = cnx.create_entity('Agent', name=u'bobby', clone_of=bob)
cnx.commit()
clone.cw_clear_all_caches()
# Ensure all relation (to new entities) are present on the clone.
rset = cnx.execute(
'Any X WHERE X name "bobby", X account AC, X biography B,'
' B event E, E is Event, B event A, A narrated_by X')
self.assertTrue(rset)
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment