[views] Use 3.25 'derived rtags' feature
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 06 Oct 2017 08:39:29 +0200
changeset 2715 757262c669ca
parent 2714 fadde7202d72
child 2726 935cf96e49f3
[views] Use 3.25 'derived rtags' feature This allows to keep only specific rules in derived rtags and to look for other in the "parent" rtag, so that rules which are set there after the derived rtag have been constructed are still considered (if not overriden). This will avoid some rules duplication in at least the saem_ref cube. There may be a few ones that may be removed from this cube but this is not done by this commit. Using this feature requires backporting fixes done in unreleased cubicweb 3.25.3. Related to #17106806
cubicweb_seda/views/__init__.py
cubicweb_seda/views/archivetransfer.py
cubicweb_seda/views/archiveunit.py
cubicweb_seda/views/patches.py
cubicweb_seda/views/simplified.py
--- a/cubicweb_seda/views/__init__.py	Wed Oct 11 08:06:59 2017 +0200
+++ b/cubicweb_seda/views/__init__.py	Fri Oct 06 08:39:29 2017 +0200
@@ -14,8 +14,6 @@
 # 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/>.
 
-from copy import deepcopy
-
 from yams import BASE_TYPES
 
 from cubicweb import tags, neg_role
@@ -63,17 +61,6 @@
     afs.tag_attribute((etype, 'user_annotation'), 'main', 'attributes')
 
 
-def copy_rtag(rtag, module, select):
-    """Return a copy of the given relation tag, associated to given module and selector.
-
-    >>> class_afs = copy_rtag(uicfg.autoform_section, __name__, is_instance('Class'))
-    """
-    copied = deepcopy(rtag)
-    copied.__module__ = module
-    copied.__select__ = select
-    return copied
-
-
 def rtags_from_xsd_element(etype, element_name):
     """Return primary view section and display control rtags, generated from information in the XSD
     for the given element name.
--- a/cubicweb_seda/views/archivetransfer.py	Wed Oct 11 08:06:59 2017 +0200
+++ b/cubicweb_seda/views/archivetransfer.py	Fri Oct 06 08:39:29 2017 +0200
@@ -27,7 +27,7 @@
 
 from ..xsd2yams import RULE_TYPES
 from ..entities import full_seda2_profile, simplified_profile, parent_and_container
-from . import rtags_from_xsd_element, rtags_from_rtype_role_targets, copy_rtag
+from . import rtags_from_xsd_element, rtags_from_rtype_role_targets
 from . import clone, viewlib
 from . import uicfg as sedauicfg  # noqa - ensure those rules are defined first
 
@@ -93,8 +93,8 @@
     return 0
 
 
-top_level_rule_afs = copy_rtag(
-    afs, __name__,
+top_level_rule_afs = afs.derive(
+    __name__,
     is_instance(*['SEDA{0}Rule'.format(rule_type.capitalize())
                   for rule_type in RULE_TYPES]) & top_level_rule())
 for rule_type in RULE_TYPES:
--- a/cubicweb_seda/views/archiveunit.py	Wed Oct 11 08:06:59 2017 +0200
+++ b/cubicweb_seda/views/archiveunit.py	Fri Oct 06 08:39:29 2017 +0200
@@ -34,7 +34,7 @@
                         simplified_profile, parent_and_container)
 from ..entities.itree import parent_archive_unit
 from . import (CONTENT_ETYPE, add_subobject_link,
-               rtags_from_xsd_element, rtags_from_rtype_role_targets, copy_rtag, has_rel_perm)
+               rtags_from_xsd_element, rtags_from_rtype_role_targets, has_rel_perm)
 from . import clone, viewlib, widgets
 from . import uicfg as sedauicfg  # noqa - ensure those rules are defined first
 
@@ -283,8 +283,8 @@
 
 # main tab for archive unit reference ##########################################
 
-au_ref_pvs = copy_rtag(pvs, __name__,
-                       is_instance('SEDAArchiveUnit') & is_archive_unit_ref())
+au_ref_pvs = pvs.derive(__name__,
+                        is_instance('SEDAArchiveUnit') & is_archive_unit_ref())
 au_ref_pvs.tag_subject_of(
     ('SEDAArchiveUnit', 'seda_alt_archive_unit_archive_unit_ref_id', '*'),
     'attributes')
@@ -606,8 +606,8 @@
 afs.tag_attribute(('SEDAKeyword', 'keyword_content'), 'main', 'hidden')
 afs.tag_attribute(('SEDAKeywordReference', 'user_cardinality'), 'main', 'hidden')
 # custom afs to handle 'simple keyword'
-kw_simple_afs = copy_rtag(afs, __name__,
-                          is_instance('SEDAKeyword') & is_simple_keyword())
+kw_simple_afs = afs.derive(__name__,
+                           is_instance('SEDAKeyword') & is_simple_keyword())
 kw_simple_afs.tag_attribute(('SEDAKeyword', 'keyword_content'), 'main', 'attributes')
 kw_simple_afs.tag_object_of(
     ('*', 'seda_keyword_reference_from', 'SEDAKeyword'),
@@ -703,8 +703,8 @@
         self.w(u'<div class="clearfix"/>')
 
 
-do_ref_afs = copy_rtag(afs, __name__,
-                       is_instance('SEDADataObjectReference') & typed_reference())
+do_ref_afs = afs.derive(__name__,
+                        is_instance('SEDADataObjectReference') & typed_reference())
 do_ref_afs.tag_attribute(('SEDADataObjectReference', 'user_cardinality'), 'main', 'hidden')
 
 for etype in ('SEDAAltIsPartOfArchiveUnitRefId',
@@ -1070,9 +1070,9 @@
     'inlined', 'inlined')
 
 # and create a custom one for reference archive unit
-au_ref_afs = copy_rtag(afs, __name__,
-                       is_instance('SEDAAltArchiveUnitArchiveUnitRefId')
-                       & is_archive_unit_ref())
+au_ref_afs = afs.derive(__name__,
+                        is_instance('SEDAAltArchiveUnitArchiveUnitRefId')
+                        & is_archive_unit_ref())
 au_ref_afs.tag_object_of(
     ('*', 'seda_archive_unit_ref_id_from', 'SEDAAltArchiveUnitArchiveUnitRefId'),
     'inlined', 'inlined')
@@ -1138,5 +1138,5 @@
                   & simplified_profile())
 
 
-copy_afs = copy_rtag(afs, __name__, afs.__select__ & match_form_params(vid='copy'))
+copy_afs = afs.derive(__name__, afs.__select__ & match_form_params(vid='copy'))
 copy_afs.tag_subject_of(('*', 'seda_alt_archive_unit_archive_unit_ref_id', '*'), 'main', 'hidden')
--- a/cubicweb_seda/views/patches.py	Wed Oct 11 08:06:59 2017 +0200
+++ b/cubicweb_seda/views/patches.py	Fri Oct 06 08:39:29 2017 +0200
@@ -17,7 +17,7 @@
 
 from logilab.common.decorators import monkeypatch
 
-from cubicweb.web.views import autoform  # noqa
+from cubicweb.web.views import autoform
 
 
 # monkey patch autoform to add an hidden field container the parent container eid that may be used
@@ -46,3 +46,54 @@
 # this js file contains a custom implementation of addInlineCreationForm that propage
 # sedaContainerEID
 autoform.AutomaticEntityForm.needs_js += ('cubes.seda.form.js',)
+
+
+# Broken derivation for autoform_section (https://www.cubicweb.org/ticket/17107020)
+
+from itertools import repeat  # noqa
+from cubicweb.rtags import rtags_chain  # noqa
+from cubicweb.web.views import uicfg  # noqa
+
+
+@monkeypatch(uicfg.AutoformSectionRelationTags)
+def init(self, schema, check=True):
+    super(uicfg.AutoformSectionRelationTags, self).init(schema, check)
+    if self._parent is None:
+        self.apply(schema, self._initfunc_step2)
+    else:
+        # we still need to expand wildcard in defined keys
+        for key in list(self._tagdefs):
+            stype, rtype, otype, role = key
+            rschema = schema.rschema(rtype)
+            if stype == '*' and stype == '*':
+                concrete_rdefs = rschema.rdefs.keys()
+            elif stype == '*':
+                concrete_rdefs = zip(rschema.subjects(otype), repeat(otype))
+            elif otype == '*':
+                concrete_rdefs = zip(repeat(stype), rschema.objects(stype))
+            else:
+                concrete_rdefs = [(stype, otype)]
+            for sschema, oschema in concrete_rdefs:
+                self._init(sschema, rschema, oschema, role)
+                # also, we have to copy values for undefined section from
+                # the parent's rtag
+                formsections = self.get(sschema, rschema, oschema, role)
+                sectdict = uicfg._formsections_as_dict(formsections)
+                if 'main' in sectdict:
+                    sectdict.setdefault('inlined', sectdict['main'])
+                parent_formsections = self._parent.get(sschema, rschema, oschema, role)
+                parent_sectdict = uicfg._formsections_as_dict(parent_formsections)
+                for formtype, section in parent_sectdict.items():
+                    if formtype not in sectdict:
+                        formsections.add('%s_%s' % (formtype, section))
+
+
+@monkeypatch(uicfg.AutoformSectionRelationTags)
+def get(self, *key):
+    # overriden to avoid recomputing done in parent classes
+    for rtag in rtags_chain(self):
+        try:
+            return rtag._tagdefs[key]
+        except KeyError:
+            continue
+    return ()
--- a/cubicweb_seda/views/simplified.py	Wed Oct 11 08:06:59 2017 +0200
+++ b/cubicweb_seda/views/simplified.py	Fri Oct 06 08:39:29 2017 +0200
@@ -22,16 +22,16 @@
 
 from ..xsd2yams import RULE_TYPES
 from ..entities import simplified_profile
-from . import CONTENT_ETYPE, copy_rtag
+from . import CONTENT_ETYPE
 # ensure those are registered first
 from . import mgmt_rules, archivetransfer, dataobject, archiveunit  # noqa
 
 
 # Add arbitrary score using `yes` to overtake e.g. afs for DataObjectReference defined in content
 afs = uicfg.autoform_section
-simplified_afs = copy_rtag(afs, __name__, simplified_profile())
+simplified_afs = afs.derive(__name__, simplified_profile())
 pvs = uicfg.primaryview_section
-simplified_pvs = copy_rtag(pvs, __name__, simplified_profile())
+simplified_pvs = pvs.derive(__name__, simplified_profile())
 
 # appraisal/access rules have a single top level cardinality in simplified profile, as well as
 # always a start date. This implies: