entity.py
branchstable
changeset 5199 ebb50479d2ab
parent 5144 5a09bea07302
child 5201 2b4267157f85
child 5320 848e92bb81cc
--- a/entity.py	Fri Apr 09 15:04:56 2010 +0200
+++ b/entity.py	Fri Apr 09 15:07:01 2010 +0200
@@ -202,6 +202,59 @@
             needcheck = False
         return mainattr, needcheck
 
+    @classmethod
+    def cw_instantiate(cls, execute, **kwargs):
+        """add a new entity of this given type
+
+        Example (in a shell session):
+
+        >>> companycls = vreg['etypes'].etype_class(('Company')
+        >>> personcls = vreg['etypes'].etype_class(('Person')
+        >>> c = companycls.cw_instantiate(req.execute, name=u'Logilab')
+        >>> personcls.cw_instantiate(req.execute, firstname=u'John', lastname=u'Doe',
+        ...                          works_for=c)
+
+        """
+        rql = 'INSERT %s X' % cls.__regid__
+        relations = []
+        restrictions = set()
+        pending_relations = []
+        for attr, value in kwargs.items():
+            if isinstance(value, (tuple, list, set, frozenset)):
+                if len(value) == 1:
+                    value = iter(value).next()
+                else:
+                    del kwargs[attr]
+                    pending_relations.append( (attr, value) )
+                    continue
+            if hasattr(value, 'eid'): # non final relation
+                rvar = attr.upper()
+                # XXX safer detection of object relation
+                if attr.startswith('reverse_'):
+                    relations.append('%s %s X' % (rvar, attr[len('reverse_'):]))
+                else:
+                    relations.append('X %s %s' % (attr, rvar))
+                restriction = '%s eid %%(%s)s' % (rvar, attr)
+                if not restriction in restrictions:
+                    restrictions.add(restriction)
+                kwargs[attr] = value.eid
+            else: # attribute
+                relations.append('X %s %%(%s)s' % (attr, attr))
+        if relations:
+            rql = '%s: %s' % (rql, ', '.join(relations))
+        if restrictions:
+            rql = '%s WHERE %s' % (rql, ', '.join(restrictions))
+        created = execute(rql, kwargs).get_entity(0, 0)
+        for attr, values in pending_relations:
+            if attr.startswith('reverse_'):
+                restr = 'Y %s X' % attr[len('reverse_'):]
+            else:
+                restr = 'X %s Y' % attr
+            execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % (
+                restr, ','.join(str(r.eid) for r in values)),
+                    {'x': created.eid}, build_descr=False)
+        return created
+
     def __init__(self, req, rset=None, row=None, col=0):
         AppObject.__init__(self, req, rset=rset, row=row, col=col)
         dict.__init__(self)