Commit 1bd5357b authored by Sylvain Thénault's avatar Sylvain Thénault
Browse files

[uicfg] Fix autoform_section rtags wrt derivation

cw 3.25 introduced the 'derived rtags' feature, but missed that
`autoform_section` implementation was overriding several methods where this was
implemented in the base class. The following problems are tested and fixed:

* during init, we should not attempt to call `_initfunc_step2` if there is some

* but we should handle expansion of wildcard ('*' used as subject or object of a
  tag) since this is handled during init step for this class, unlike others
  which handle this in `get` method (i.e. at lookup time),

* fix overrided `get` method to consider parent rtag if any.

Closes #17107020

branch : 3.25
parent f2e6fb5ddf68
......@@ -19,7 +19,10 @@
import copy
import warnings
from cubicweb.devtools.testlib import CubicWebTC
from yams.buildobjs import RelationDefinition, EntityType
from cubicweb.devtools.testlib import CubicWebTC, BaseTestCase
from cubicweb.schema import build_schema_from_namespace
from cubicweb.web import uihelper, formwidgets as fwdgs
from cubicweb.web.views import uicfg
......@@ -144,6 +147,55 @@ class UicfgRegistryTC(CubicWebTC):
self.assertTrue(obj is custom_afs)
def _schema():
class Personne(EntityType):
class Societe(EntityType):
class Tag(EntityType):
class travaille(RelationDefinition):
subject = 'Personne'
object = 'Societe'
class tags(RelationDefinition):
subject = 'Tag'
object = ('Personne', 'Societe', 'Tag')
return build_schema_from_namespace(locals().items())
class AutoformSectionTC(BaseTestCase):
def test_derivation(self):
schema = _schema()
afs = uicfg.AutoformSectionRelationTags()
afs.tag_subject_of(('Personne', 'travaille', '*'), 'main', 'relations')
afs.tag_object_of(('*', 'travaille', 'Societe'), 'main', 'relations')
afs.tag_subject_of(('Tag', 'tags', '*'), 'main', 'relations')
afs2 = afs.derive(__name__, afs.__select__)
afs2.tag_subject_of(('Personne', 'travaille', '*'), 'main', 'attributes')
afs2.tag_object_of(('*', 'travaille', 'Societe'), 'main', 'attributes')
afs2.tag_subject_of(('Tag', 'tags', 'Societe'), 'main', 'attributes')
self.assertEqual(afs2.etype_get('Tag', 'tags', 'subject', 'Personne'),
set(('main_relations', 'muledit_hidden', 'inlined_relations')))
self.assertEqual(afs2.etype_get('Tag', 'tags', 'subject', 'Societe'),
set(('main_attributes', 'muledit_hidden', 'inlined_attributes')))
self.assertEqual(afs2.etype_get('Personne', 'travaille', 'subject', 'Societe'),
set(('main_attributes', 'muledit_hidden', 'inlined_attributes')))
self.assertEqual(afs2.etype_get('Societe', 'travaille', 'object', 'Personne'),
set(('main_attributes', 'muledit_hidden', 'inlined_attributes')))
if __name__ == '__main__':
import unittest
......@@ -54,12 +54,14 @@ Actions box configuration
uicfg.actionbox_appearsin_addmenu.tag_object_of(('*', 'entry_of', 'Blog'), True)
from itertools import repeat
from six import string_types
from cubicweb import neg_role
from cubicweb.rtags import (RelationTags, RelationTagsBool, RelationTagsSet,
RelationTagsDict, NoTargetRelationTagsDict,
rtags_chain, _ensure_str_key)
......@@ -203,7 +205,16 @@ def _card_and_comp(sschema, rschema, oschema, role):
class AutoformSectionRelationTags(RelationTagsSet):
"""autoform relations'section"""
"""autoform relations'section
Notice that unlike other rtags where wildcard handling is done when
retrieving some value, all values are expanded here during initialization
For derived rtags, values specified for the 'main' form type are propagated
to the 'inlined' form type if unspecified. Others are fetched back from the
__regid__ = 'autoform_section'
_allowed_form_types = ('main', 'inlined', 'muledit')
......@@ -215,7 +226,34 @@ class AutoformSectionRelationTags(RelationTagsSet):
def init(self, schema, check=True):
super(AutoformSectionRelationTags, self).init(schema, check)
self.apply(schema, self._initfunc_step2)
if self._parent is None:
self.apply(schema, self._initfunc_step2)
# 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))
concrete_rdefs = [(stype, otype)]
for sschema, oschema in concrete_rdefs:
self._init(sschema, rschema, oschema, role)
# also, we have to copy values from 'main' to 'inlined' and
# for other undefined sections from the parent's rtag
formsections = self.get(sschema, rschema, oschema, role)
sectdict = _formsections_as_dict(formsections)
parent_formsections = self._parent.get(sschema, rschema, oschema, role)
parent_sectdict = _formsections_as_dict(parent_formsections)
for formtype, section in parent_sectdict.items():
if formtype not in sectdict:
if formtype == 'inlined':
section = sectdict.get('main', section)
formsections.add('%s_%s' % (formtype, section))
def _init(self, sschema, rschema, oschema, role):
formsections = self.init_get(sschema, rschema, oschema, role)
......@@ -300,7 +338,12 @@ class AutoformSectionRelationTags(RelationTagsSet):
def get(self, *key):
# overriden to avoid recomputing done in parent classes
return self._tagdefs.get(key, ())
for rtag in rtags_chain(self):
return rtag._tagdefs[key]
except KeyError:
return ()
def relations_by_section(self, entity, formtype, section, permission,
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment