[ADD] depth-first iterator on views, refactor apply_view_inheritance to use it
bzr revid: xmo@openerp.com-20130422125000-pg60ovrxejegenka
This commit is contained in:
parent
bad87b4245
commit
edf1f23a6e
|
@ -230,6 +230,31 @@ class view(osv.osv):
|
|||
for view in self.browse(cr, 1, view_ids, context)
|
||||
if not (view.groups_id and user_groups.isdisjoint(view.groups_id))]
|
||||
|
||||
def iter(self, cr, uid, view_id, model, exclude_base=False, context=None):
|
||||
""" iterates on all of `view_id`'s descendants tree depth-first.
|
||||
|
||||
If `exclude_base` is `False`, also yields `view_id` itself. It is
|
||||
`False` by default to match the behavior of etree's Element.iter.
|
||||
|
||||
:param int view_id: database id of the root view
|
||||
:param str model: name of the view's related model (for filtering)
|
||||
:param boolean exclude_base: whether `view_id` should be excluded from the iteration
|
||||
:param context:
|
||||
:return: iterator of (database_id, arch_field) pairs for all
|
||||
descendants of `view_id` (including `view_id` itself if
|
||||
`exclude_base` is `False`, the default)
|
||||
"""
|
||||
if not exclude_base:
|
||||
[base] = self.browse(cr, uid, [view_id], context=context)
|
||||
yield base.id, base.arch
|
||||
|
||||
for arch, id in self.get_inheriting_views_arch(
|
||||
cr, uid, view_id, model, context=context):
|
||||
yield id, arch
|
||||
for info in self.iter(
|
||||
cr, uid, id, model, exclude_base=True, context=None):
|
||||
yield info
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if not isinstance(ids, (list, tuple)):
|
||||
ids = [ids]
|
||||
|
|
|
@ -2068,16 +2068,16 @@ class BaseModel(object):
|
|||
raise AttributeError("View definition error for inherited view '%s' on model '%s': %s"
|
||||
% (child_view.xml_id, self._name, error_msg))
|
||||
|
||||
def apply_inheritance_specs(source, specs_arch, inherit_id=None):
|
||||
""" Apply an inheriting view.
|
||||
def apply_inheritance_specs(source, descendant_id, specs_arch):
|
||||
""" Apply an inheriting view (a descendant of the base view)
|
||||
|
||||
Apply to a source architecture all the spec nodes (i.e. nodes
|
||||
describing where and what changes to apply to some parent
|
||||
architecture) given by an inheriting view.
|
||||
|
||||
:param source: a parent architecture to modify
|
||||
:param descendant_id: the database id of the descendant
|
||||
:param specs_arch: a modifying architecture in an inheriting view
|
||||
:param inherit_id: the database id of the inheriting view
|
||||
:return: a modified source where the specs are applied
|
||||
|
||||
"""
|
||||
|
@ -2124,7 +2124,7 @@ class BaseModel(object):
|
|||
elif pos == 'before':
|
||||
node.addprevious(child)
|
||||
else:
|
||||
raise_view_error("Invalid position value: '%s'" % pos, inherit_id)
|
||||
raise_view_error("Invalid position value: '%s'" % pos, descendant_id)
|
||||
else:
|
||||
attrs = ''.join([
|
||||
' %s="%s"' % (attr, spec.get(attr))
|
||||
|
@ -2134,8 +2134,8 @@ class BaseModel(object):
|
|||
tag = "<%s%s>" % (spec.tag, attrs)
|
||||
if spec.get('version') and spec.get('version') != source.get('version'):
|
||||
raise_view_error("Mismatching view API version for element '%s': %r vs %r in parent view '%%(parent_xml_id)s'" % \
|
||||
(tag, spec.get('version'), source.get('version')), inherit_id)
|
||||
raise_view_error("Element '%s' not found in parent view '%%(parent_xml_id)s'" % tag, inherit_id)
|
||||
(tag, spec.get('version'), source.get('version')), descendant_id)
|
||||
raise_view_error("Element '%s' not found in parent view '%%(parent_xml_id)s'" % tag, descendant_id)
|
||||
|
||||
return source
|
||||
|
||||
|
@ -2149,11 +2149,10 @@ class BaseModel(object):
|
|||
are applied
|
||||
|
||||
"""
|
||||
sql_inherit = self.pool.get('ir.ui.view').get_inheriting_views_arch(cr, user, inherit_id, self._name)
|
||||
for (view_arch, view_id) in sql_inherit:
|
||||
source = apply_inheritance_specs(source, view_arch, view_id)
|
||||
source = apply_view_inheritance(cr, user, source, view_id)
|
||||
return source
|
||||
return reduce(
|
||||
lambda s, descendant: apply_inheritance_specs(s, *descendant),
|
||||
self.pool['ir.ui.view'].iter(cr, user, inherit_id, self._name),
|
||||
source)
|
||||
|
||||
result = {'type': view_type, 'model': self._name}
|
||||
|
||||
|
|
|
@ -139,3 +139,16 @@ class TestViewInheritance(common.TransactionCase):
|
|||
self.assertEqual(self.View.get_inheriting_views_arch(
|
||||
self.cr, self.uid, self.ids['A11'], self.model),
|
||||
[(self.view_for('A111'), self.ids['A111'])])
|
||||
|
||||
def test_iterate_descendents(self):
|
||||
descendents = list(self.View.iter(self.cr, self.uid, self.ids['A1'], self.model))
|
||||
self.assertEqual(descendents, [
|
||||
(self.ids[name], self.view_for(name))
|
||||
for name in ['A1', 'A11', 'A111', 'A12']
|
||||
])
|
||||
descendents = list(self.View.iter(
|
||||
self.cr, self.uid, self.ids['A2'], self.model, exclude_base=True))
|
||||
self.assertEqual(descendents, [
|
||||
(self.ids[name], self.view_for(name))
|
||||
for name in ['A21', 'A22', 'A221']
|
||||
])
|
||||
|
|
Loading…
Reference in New Issue