[PATCH 2 of 3 seda v2] [views] Use 3.25 'derived rtags' feature

Sylvain Thenault sylvain.thenault at logilab.fr
Wed Oct 11 11:01:12 CEST 2017


# HG changeset patch
# User Sylvain Thénault <sylvain.thenault at logilab.fr>
# Date 1507271969 -7200
#      Fri Oct 06 08:39:29 2017 +0200
# Node ID 757262c669cadd9c36b7937f2be100bc0cd002f6
# Parent  fadde7202d728b86d1a4ad11dc002a59bf39afd3
# Available At https://hg.logilab.org/review/cubes/seda
#              hg pull https://hg.logilab.org/review/cubes/seda -r 757262c669ca
[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

diff --git a/cubicweb_seda/views/__init__.py b/cubicweb_seda/views/__init__.py
--- a/cubicweb_seda/views/__init__.py
+++ b/cubicweb_seda/views/__init__.py
@@ -12,12 +12,10 @@
 # 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/>.
 
-from copy import deepcopy
-
 from yams import BASE_TYPES
 
 from cubicweb import tags, neg_role
 from cubicweb.utils import UStringIO
 from cubicweb.web import formfields as ff
@@ -61,21 +59,10 @@ afs.tag_attribute(('*', 'user_annotation
 for etype in FIRST_LEVEL_ETYPES:
     aff.tag_attribute((etype, 'user_cardinality'), ff.StringField)
     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.
     """
     rtype_role_targets = ((rtype, role, path[-1][-2])
diff --git a/cubicweb_seda/views/archivetransfer.py b/cubicweb_seda/views/archivetransfer.py
--- a/cubicweb_seda/views/archivetransfer.py
+++ b/cubicweb_seda/views/archivetransfer.py
@@ -25,11 +25,11 @@ from cubicweb.web.views import tabs, uic
 
 from cubes.relationwidget import views as rwdg
 
 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
 
 at_ordered_fields = [
     ('seda_archival_agency', 'subject'),
@@ -91,12 +91,12 @@ def top_level_rule(cls, req, rset=None, 
     if parent.cw_etype == 'SEDAArchiveTransfer':
         return 1
     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:
     etype = 'SEDA{0}Rule'.format(rule_type.capitalize())
     rtype = 'seda_alt_{0}_rule_prevent_inheritance'.format(rule_type)
diff --git a/cubicweb_seda/views/archiveunit.py b/cubicweb_seda/views/archiveunit.py
--- a/cubicweb_seda/views/archiveunit.py
+++ b/cubicweb_seda/views/archiveunit.py
@@ -32,11 +32,11 @@ from cubes.relationwidget import views a
 from ..xsd import un_camel_case
 from ..entities import (is_full_seda2_profile, full_seda2_profile,
                         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
 
 
 def add_links_with_custom_arguments(seq, rtype, role, extraurlparams, sub_unit_types):
@@ -281,12 +281,12 @@ class ArchiveUnitTabbedPrimaryView(tabs.
         rwdg.bootstrap_dialog(self.w, self._cw._, clone._import_div_id(entity))
 
 
 # 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')
 rec.tag_subject_of(('SEDAArchiveUnit', 'seda_alt_archive_unit_archive_unit_ref_id', '*'),
                    {'rvid': 'seda.reledit.simplelink',
@@ -604,12 +604,12 @@ affk.set_fields_order('SEDAKeywordRefere
 
 # add rule in afs for 'complex keyword'
 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'),
     'main', 'hidden')
 # but one ordering is enough to rule them all
@@ -701,12 +701,12 @@ class ReferenceListItemContentView(viewl
             self.wdata(self._cw._('<no value specified>'))
         self.w(u'</div>')
         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',
               'SEDAAltIsVersionOfArchiveUnitRefId',
               'SEDAAltReferencesArchiveUnitRefId',
@@ -1068,13 +1068,13 @@ afs.tag_subject_of(
     ('SEDAAltArchiveUnitArchiveUnitRefId',
      'seda_seq_alt_archive_unit_archive_unit_ref_id_management', '*'),
     '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')
 au_ref_afs.tag_subject_of(
     ('SEDAAltArchiveUnitArchiveUnitRefId',
@@ -1136,7 +1136,7 @@ class DataObjectReferenceNoTitleEntityIn
     __select__ = (widgets.NoTitleEntityInlinedFormRenderer.__select__
                   & is_instance('SEDADataObjectReference')
                   & 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')
diff --git a/cubicweb_seda/views/patches.py b/cubicweb_seda/views/patches.py
--- a/cubicweb_seda/views/patches.py
+++ b/cubicweb_seda/views/patches.py
@@ -15,11 +15,11 @@
 # with this program. If not, see <http://www.gnu.org/licenses/>.
 """Dynamic patches to avoid hard dependancies on cubicweb releases"""
 
 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
 # in parent_and_container (see entities/__init__.py)
 
@@ -44,5 +44,56 @@ def __init__(self, *args, **kwargs):
 
 
 # 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
+
+
+ at 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))
+
+
+ at 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 ()
diff --git a/cubicweb_seda/views/simplified.py b/cubicweb_seda/views/simplified.py
--- a/cubicweb_seda/views/simplified.py
+++ b/cubicweb_seda/views/simplified.py
@@ -20,20 +20,20 @@ from logilab.common.registry import obje
 from cubicweb.predicates import is_instance
 from cubicweb.web.views import uicfg, autoform
 
 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:
 # 1. force one and only one eg AppraisalRuleRule,
 # 2. force start date, but hide it,


More information about the saem-devel mailing list