diff -r cf8292f80384 -r ebb50479d2ab entity.py --- 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)