fix *relations_by_categories + rtags api/key mess tls-sprint
authorsylvain.thenault@logilab.fr
Fri, 27 Mar 2009 12:30:19 +0100
branchtls-sprint
changeset 1179 70825477c6ce
parent 1178 8d9b705168d3
child 1180 5536d4ee2bc3
fix *relations_by_categories + rtags api/key mess
entities/__init__.py
rtags.py
web/views/editforms.py
--- a/entities/__init__.py	Fri Mar 27 12:25:24 2009 +0100
+++ b/entities/__init__.py	Fri Mar 27 12:30:19 2009 +0100
@@ -8,7 +8,7 @@
 
 from warnings import warn
 
-from logilab.common.deprecation import deprecated_function
+from logilab.common.deprecation import deprecated_function, obsolete
 from logilab.common.decorators import cached
 
 from cubicweb import Unauthorized, typed_eid
@@ -249,19 +249,25 @@
             wdg = widget(cls.vreg, tschema, rschema, cls, 'object')
         return wdg
 
-    @obsolete('use AutomaticEntityForm.relations_by_category')
+    @obsolete('use EntityFieldsForm.subject_relation_vocabulary')
+    def subject_relation_vocabulary(self, rtype, limit):
+        from cubicweb.web.form import EntityFieldsForm
+        return EntityFieldsForm(entity=self).subject_relation_vocabulary(rtype, limit)
+
+    @obsolete('use EntityFieldsForm.object_relation_vocabulary')
+    def object_relation_vocabulary(self, rtype, limit):
+        from cubicweb.web.form import EntityFieldsForm
+        return EntityFieldsForm(entity=self).object_relation_vocabulary(rtype, limit)
+    
+    @obsolete('use AutomaticEntityForm.[e]relations_by_category')
     def relations_by_category(self, categories=None, permission=None):
-        from cubicweb.web.views.editform import AutomaticEntityForm
-        return AutomaticEntityForm.relations_by_category(entity, categories, permission)
+        from cubicweb.web.views.editforms import AutomaticEntityForm
+        return AutomaticEntityForm.erelations_by_category(self, categories, permission)
 
+    @obsolete('use AutomaticEntityForm.[e]srelations_by_category')
     def srelations_by_category(self, categories=None, permission=None):
-        result = []
-        for rschema, ttypes, target in self.relations_by_category(categories,
-                                                                  permission):
-            if rschema.is_final():
-                continue
-            result.append( (rschema.display_name(self.req, target), rschema, target) )
-        return sorted(result)
+        from cubicweb.web.views.editforms import AutomaticEntityForm
+        return AutomaticEntityForm.esrelations_by_category(self, categories, permission)
     
     def _default_format(self):
         return self.req.property_value('ui.default-text-format')
--- a/rtags.py	Fri Mar 27 12:25:24 2009 +0100
+++ b/rtags.py	Fri Mar 27 12:30:19 2009 +0100
@@ -22,58 +22,58 @@
         self.use_set = use_set
         self._tagdefs = {}
         
-    def set_rtag(self, tag, role, rtype, stype='*', otype='*'):
+    def set_rtag(self, tag, rtype, role, stype='*', otype='*'):
         assert not self.use_set
         assert role in ('subject', 'object'), role
-        self._tagdefs[(stype, rtype, otype, role)] = tag
+        self._tagdefs[(rtype, role, stype, otype)] = tag
         
-    def rtag(self, role, rtype, stype='*', otype='*'):
+    def rtag(self, rtype, role, stype='*', otype='*'):
         assert not self.use_set
-        for key in reversed(self._get_keys(role, rtype, stype, otype)):
+        for key in reversed(self._get_keys(rtype, role, stype, otype)):
             try:
                 return self._tagdefs[key]
             except KeyError:
                 continue
         return None
         
-    def etype_rtag(self, etype, role, rtype, ttype='*'):
+    def etype_rtag(self, etype, rtype, role, ttype='*'):
         if role == 'subject':
-            return self.rtag(role, rtype, etype, ttype)
-        return self.rtag(role, rtype, ttype, etype)
+            return self.rtag(rtype, role, etype, ttype)
+        return self.rtag(rtype, role, ttype, etype)
         
-    def add_rtag(self, tag, role, rtype, stype='*', otype='*'):
+    def add_rtag(self, tag, rtype, role, stype='*', otype='*'):
         assert self.use_set
         assert role in ('subject', 'object'), role
-        rtags = self._tagdefs.setdefault((stype, rtype, otype, role), set())
+        rtags = self._tagdefs.setdefault((rtype, role, stype, otype), set())
         rtags.add(tag)
         
-    def rtags(self, role, rtype, stype='*', otype='*'):
+    def rtags(self, rtype, role, stype='*', otype='*'):
         assert self.use_set
         rtags = set()
-        for key in self._get_keys(role, rtype, stype, otype):
+        for key in self._get_keys(rtype, role, stype, otype):
             try:
                 rtags.update(self._tagdefs[key])
             except KeyError:
                 continue
         return rtags
         
-    def etype_rtags(self, etype, role, rtype, ttype='*'):
+    def etype_rtags(self, etype, rtype, role, ttype='*'):
         if role == 'subject':
-            return self.rtags(role, rtype, etype, ttype)
-        return self.rtags(role, rtype, ttype, etype)
+            return self.rtags(rtype, role, etype, ttype)
+        return self.rtags(rtype, role, ttype, etype)
 
-    def _get_keys(self, role, rtype, stype, otype): 
+    def _get_keys(self, rtype, role, stype, otype): 
         assert role in ('subject', 'object'), role
-        keys = [('*', rtype, '*', role),
-                ('*', rtype, otype, role),
-                (stype, rtype, '*', role),
-                (stype, rtype, otype, role)]
+        keys = [(rtype, role, '*', '*'),
+                (rtype, role, '*', otype),
+                (rtype, role, stype, '*'),
+                (rtype, role, stype, otype)]
         if stype == '*' or otype == '*':
-            keys.remove(('*', rtype, '*', role))
+            keys.remove((rtype, role, '*', '*'))
             if stype == '*':
-                keys.remove(('*', rtype, otype, role))
+                keys.remove((rtype, role, '*', otype))
             if otype == '*':
-                keys.remove((stype, rtype, '*', role))            
+                keys.remove((rtype, role, stype, '*'))            
         return keys
     
     # dict compat
--- a/web/views/editforms.py	Fri Mar 27 12:25:24 2009 +0100
+++ b/web/views/editforms.py	Fri Mar 27 12:30:19 2009 +0100
@@ -151,10 +151,10 @@
     # relations'category (eg primary/secondary/generic/metadata/generated)
     rcategories = RelationTags()
     # use primary and not generated for eid since it has to be an hidden
-    rcategories.set_rtag('primary', 'subject', 'eid')
-    rcategories.set_rtag('metadata', 'subject', 'creation_date')
-    rcategories.set_rtag('metadata', 'subject', 'modification_date')
-    rcategories.set_rtag('generated', 'subject', 'has_text')
+    rcategories.set_rtag('primary', 'eid', 'subject')
+    rcategories.set_rtag('metadata', 'creation_date', 'subject')
+    rcategories.set_rtag('metadata', 'modification_date', 'subject')
+    rcategories.set_rtag('generated', 'has_text', 'subject')
     rcategories.set_rtag('metadata', 'owned_by', 'subject')
     rcategories.set_rtag('metadata', 'created_by', 'subject')
     rcategories.set_rtag('generated', 'is', 'subject')
@@ -171,7 +171,9 @@
 
     # relations'widget (eg one of available class name in cubicweb.web.formwidgets)
     rwidgets = RelationTags()
-    # inlined view flag for non final relations
+    # inlined view flag for non final relations: when True for an entry, the
+    # entity(ies) at the other end of the relation will be editable from the
+    # form of the edited entity
     rinlined = RelationTags()
     # set of tags of the form <action>_on_new on relations. <action> is a
     # schema action (add/update/delete/read), and when such a tag is found
@@ -201,7 +203,7 @@
                         X, Y = tschema, eschema
                         card = rschema.rproperty(X, Y, 'cardinality')[1]
                         composed = rschema.rproperty(X, Y, 'composite') == 'subject'
-                    if not cls.rcategories.rtag(role, rschema, X, Y):
+                    if not cls.rcategories.rtag(rschema, role, X, Y):
                         if card in '1+':
                             if not rschema.is_final() and composed:
                                 category = 'generated'
@@ -211,49 +213,10 @@
                             category = 'secondary'
                         else: 
                             category = 'generic'
-                        cls.rcategories.set_rtag(category, role, rschema, X, Y)
-                        
-    
-    def __init__(self, *args, **kwargs):
-        super(AutomaticEntityForm, self).__init__(*args, **kwargs)
-        if self.edited_entity.has_eid():
-            self.edited_entity.complete()
-        for rschema, role in self.editable_attributes():
-            wdgname = self.rwidgets.etype_rtag(self.edited_entity.id, role, rschema)
-            if wdgname:
-                field = guess_field(self.edited_entity.__class__, rschema, role,
-                                    eidparam=True, widget=getattr(formwidgets, wdgname))
-            else:
-                field = guess_field(self.edited_entity.__class__, rschema, role,
-                                    eidparam=True)
-            self.fields.append(field)
-        
-    def action(self):
-        """return the form's action attribute"""
-        try:
-            return self._action
-        except AttributeError:
-            return self.build_url('validateform')
-        
-    def set_action(self, value):
-        self._action = value
-        
-    action = property(action, set_action)
-    
-    def form_buttons(self):
-        """return the form's buttons (as string)"""
-        return [self.button_ok(tabindex=self.req.next_tabindex()),
-                self.button_apply(tabindex=self.req.next_tabindex()),
-                self.button_cancel(tabindex=self.req.next_tabindex())]
-
-    def editable_attributes(self):
-        """return a list of (relation schema, role) to edit for the entity
-        """
-        return [(rschema, x) for rschema, _, x in self.relations_by_category(
-            self.entity, self.attrcategories, 'add') if rschema != 'eid']
+                        cls.rcategories.set_rtag(category, rschema, role, X, Y)
 
     @classmethod
-    def relations_by_category(cls, entity, categories=None, permission=None):
+    def erelations_by_category(cls, entity, categories=None, permission=None):
         """return a list of (relation schema, target schemas, role) matching
         categories and permission
         """
@@ -276,14 +239,14 @@
             # permission which may imply rql queries
             if categories is not None:
                 targetschemas = [tschema for tschema in targetschemas
-                                 if rtags.etype_rtag(eschema, role, rschema, tschema) in categories]
+                                 if rtags.etype_rtag(eschema, rschema, role, tschema) in categories]
                 if not targetschemas:
                     continue
             if permission is not None:
                 # tag allowing to hijack the permission machinery when
                 # permission is not verifiable until the entity is actually
                 # created...
-                if eid is None and '%s_on_new' % permission in permsoverrides.etype_rtags(eschema, role, rschema):
+                if eid is None and '%s_on_new' % permission in permsoverrides.etype_rtags(eschema, rschema, role):
                     yield (rschema, targetschemas, role)
                     continue
                 if rschema.is_final():
@@ -315,19 +278,80 @@
                         continue
             yield (rschema, targetschemas, role)
     
+    @classmethod
+    def esrelations_by_category(cls, entity, categories=None, permission=None):
+        """filter out result of relations_by_category(categories, permission) by
+        removing final relations
+
+        return a sorted list of (relation's label, relation'schema, role) 
+        """
+        result = []
+        for rschema, ttypes, role in cls.erelations_by_category(
+            entity, categories, permission):
+            if rschema.is_final():
+                continue
+            result.append((rschema.display_name(entity.req, role), rschema, role))
+        return sorted(result)
+                        
+    
+    def __init__(self, *args, **kwargs):
+        super(AutomaticEntityForm, self).__init__(*args, **kwargs)
+        if self.edited_entity.has_eid():
+            self.edited_entity.complete()
+        for rschema, role in self.editable_attributes():
+            wdgname = self.rwidgets.etype_rtag(self.edited_entity.id, rschema,
+                                               role)
+            if wdgname:
+                widget = getattr(formwidgets, wdgname)
+                field = guess_field(self.edited_entity.__class__, rschema, role,
+                                    eidparam=True, widget=widget)
+            else:
+                field = guess_field(self.edited_entity.__class__, rschema, role,
+                                    eidparam=True)
+            if field is not None:
+                self.fields.append(field)
+    
+    def relations_by_category(self, categories=None, permission=None):
+        """return a list of (relation schema, target schemas, role) matching
+        given category(ies) and permission
+        """
+        return self.erelations_by_category(self.edited_entity, categories,
+                                           permission)
+    
     def srelations_by_category(self, categories=None, permission=None):
         """filter out result of relations_by_category(categories, permission) by
         removing final relations
 
-        return a list of (relation's label, relation'schema, role)
+        return a sorted list of (relation's label, relation'schema, role) 
+        """
+        return self.esrelations_by_category(self.edited_entity, categories,
+                                           permission)
+        
+    def action(self):
+        """return the form's action attribute. Default to validateform if not
+        explicitly overriden.
         """
-        result = []
-        for rschema, ttypes, role in self.relations_by_category(
-            self.entity, categories, permission):
-            if rschema.is_final():
-                continue
-            result.append( (rschema.display_name(self.req, role), rschema, role) )
-        return sorted(result)
+        try:
+            return self._action
+        except AttributeError:
+            return self.build_url('validateform')
+        
+    def set_action(self, value):
+        """override default action"""
+        self._action = value
+        
+    action = property(action, set_action)
+    
+    def form_buttons(self):
+        """return the form's buttons (as string)"""
+        return [self.button_ok(tabindex=self.req.next_tabindex()),
+                self.button_apply(tabindex=self.req.next_tabindex()),
+                self.button_cancel(tabindex=self.req.next_tabindex())]
+
+    def editable_attributes(self):
+        """return a list of (relation schema, role) to edit for the entity"""
+        return [(rschema, x) for rschema, _, x in self.relations_by_category(
+            self.attrcategories, 'add') if rschema != 'eid']
         
     def relations_table(self):
         """yiels 3-tuples (rtype, target, related_list)
@@ -339,7 +363,7 @@
         """
         entity = self.edited_entity
         pending_deletes = self.req.get_pending_deletes(entity.eid)
-        for label, rschema, role in self.srelations_by_category('generic'), 'add'):
+        for label, rschema, role in self.srelations_by_category('generic', 'add'):
             relatedrset = entity.related(rschema, role, limit=self.limit)
             if rschema.has_perm(self.req, 'delete'):
                 toggable_rel_link_func = toggable_relation_link
@@ -390,7 +414,7 @@
         """return true if the given relation with entity has role and a
         targettype target should be inlined
         """
-        return self.rinlined.etype_rtag(self.edited_entity.id, role, rschema, targettype)
+        return self.rinlined.etype_rtag(self.edited_entity.id, rschema, role, targettype)
 
     def should_display_inline_creation_form(self, rschema, existant, card):
         """return true if a creation form should be inlined