summaryrefslogtreecommitdiff
path: root/openerp/tools/view_validation.py
diff options
context:
space:
mode:
authorXavier Morel <xmo@odoo.com>2016-03-03 10:43:39 +0100
committerXavier Morel <xmo@odoo.com>2016-03-03 13:18:01 +0100
commita76b3caa6e3cb9bf20c37f1c5e4e862cef406b7c (patch)
tree65e32f9375bd1c95da0e7d3ea79aad504362b08c /openerp/tools/view_validation.py
parentcfbc1729c4a8d743cad8aa93fe076a644529a516 (diff)
[IMP] custom view validators system
Add possibility for modules to add validators, getting closer to defining views outside of base.
Diffstat (limited to 'openerp/tools/view_validation.py')
-rw-r--r--openerp/tools/view_validation.py84
1 files changed, 44 insertions, 40 deletions
diff --git a/openerp/tools/view_validation.py b/openerp/tools/view_validation.py
index dc0a8d51830..f3703712d24 100644
--- a/openerp/tools/view_validation.py
+++ b/openerp/tools/view_validation.py
@@ -1,80 +1,84 @@
""" View validation code (using assertions, not the RNG schema). """
+import collections
import logging
_logger = logging.getLogger(__name__)
+_validators = collections.defaultdict(list)
+def valid_view(arch):
+ for pred in _validators[arch.tag]:
+ if not pred(arch):
+ _logger.error("Invalid XML: %s", pred.__doc__)
+ return False
+ return True
+
+
+def validate(*view_types):
+ """ Registers a view-validation function for the specific view types
+ """
+ def decorator(fn):
+ for arch in view_types:
+ _validators[arch].append(fn)
+ return fn
+ return decorator
+
+
+@validate('form')
def valid_page_in_book(arch):
"""A `page` node must be below a `book` node."""
return not arch.xpath('//page[not(ancestor::notebook)]')
+@validate('graph')
def valid_field_in_graph(arch):
""" Children of ``graph`` can only be ``field`` """
- for child in arch.xpath('/graph/child::*'):
- if child.tag != 'field':
- return False
- return True
+ return all(
+ child.tag == 'field'
+ for child in arch.xpath('/graph/*')
+ )
+@validate('tree')
def valid_field_in_tree(arch):
""" Children of ``tree`` view must be ``field`` or ``button``."""
- for child in arch.xpath('/tree/child::*'):
- if child.tag not in ('field', 'button'):
- return False
- return True
+ return all(
+ child.tag in ('field', 'button')
+ for child in arch.xpath('/tree/*')
+ )
+@validate('form', 'graph', 'tree')
def valid_att_in_field(arch):
""" ``field`` nodes must all have a ``@name`` """
return not arch.xpath('//field[not(@name)]')
+@validate('form')
def valid_att_in_label(arch):
""" ``label`` nodes must have a ``@for`` or a ``@string`` """
return not arch.xpath('//label[not(@for or @string)]')
+@validate('form')
def valid_att_in_form(arch):
return True
+@validate('form')
def valid_type_in_colspan(arch):
"""A `colspan` attribute must be an `integer` type."""
- for attrib in arch.xpath('//*/@colspan'):
- try:
- int(attrib)
- except:
- return False
- return True
+ return all(
+ attrib.isdigit()
+ for attrib in arch.xpath('//@colspan')
+ )
+@validate('form')
def valid_type_in_col(arch):
"""A `col` attribute must be an `integer` type."""
- for attrib in arch.xpath('//*/@col'):
- try:
- int(attrib)
- except:
- return False
- return True
-
-
-def valid_view(arch):
- if arch.tag == 'form':
- for pred in [valid_page_in_book, valid_att_in_form, valid_type_in_colspan,
- valid_type_in_col, valid_att_in_field, valid_att_in_label]:
- if not pred(arch):
- _logger.error('Invalid XML: %s', pred.__doc__)
- return False
- elif arch.tag == 'graph':
- for pred in [valid_field_in_graph, valid_att_in_field]:
- if not pred(arch):
- _logger.error('Invalid XML: %s', pred.__doc__)
- return False
- elif arch.tag == 'tree':
- for pred in [valid_field_in_tree, valid_att_in_field]:
- if not pred(arch):
- _logger.error('Invalid XML: %s', pred.__doc__)
- return False
- return True
+ return all(
+ attrib.isdigit()
+ for attrib in arch.xpath('//@col')
+ )