[MERGE] forward port of branch saas-1 up to revid 4908 dle@openerp.com-20130918160049-fo88fl7uyhfoofkv

bzr revid: chs@openerp.com-20130918171816-cxxt3c9ktcq4a8oz
This commit is contained in:
Christophe Simonis 2013-09-18 19:18:16 +02:00
commit fd9a9577df
9 changed files with 156 additions and 11 deletions

View File

@ -110,7 +110,7 @@ class report_xml(osv.osv):
kwargs = {}
new_report = report_sxw('report.'+r['report_name'], r['model'],
opj('addons',r['report_rml'] or '/'), header=r['header'], register=False, **kwargs)
elif r['report_xsl']:
elif r['report_xsl'] and r['report_xml']:
new_report = report_rml('report.'+r['report_name'], r['model'],
opj('addons',r['report_xml']),
r['report_xsl'] and opj('addons',r['report_xsl']), register=False)

View File

@ -404,8 +404,10 @@ class ir_mail_server(osv.osv):
# The email's "Envelope From" (Return-Path), and all recipient addresses must only contain ASCII characters.
from_rfc2822 = extract_rfc2822_addresses(smtp_from)
assert len(from_rfc2822) == 1, "Malformed 'Return-Path' or 'From' address - it may only contain plain ASCII characters"
smtp_from = from_rfc2822[0]
assert from_rfc2822, ("Malformed 'Return-Path' or 'From' address: %r - "
"It should contain one valid plain ASCII email") % smtp_from
# use last extracted email, to support rarities like 'Support@MyComp <support@mycompany.com>'
smtp_from = from_rfc2822[-1]
email_to = message['To']
email_cc = message['Cc']
email_bcc = message['Bcc']

View File

@ -21,6 +21,7 @@
import logging
from lxml import etree
from operator import itemgetter
import os
from openerp import tools
@ -127,10 +128,14 @@ class view(osv.osv):
try:
fvg = self.pool[view.model].fields_view_get(cr, uid, view_id=view.id, view_type=view.type, context=context)
return fvg['arch']
except:
except Exception:
return False
def _check_xml(self, cr, uid, ids, context=None):
if context is None:
context = {}
context['check_view_ids'] = ids
for view in self.browse(cr, uid, ids, context):
# Sanity check: the view should not break anything upon rendering!
view_arch_utf8 = self._check_render_view(cr, uid, view, context=context)
@ -183,13 +188,15 @@ class view(osv.osv):
:rtype: list of tuples
:return: [(view_arch,view_id), ...]
"""
user_groups = frozenset(self.pool.get('res.users').browse(cr, 1, uid, context).groups_id)
if self.pool._init:
# Module init currently in progress, only consider views from modules whose code was already loaded
check_view_ids = context and context.get('check_view_ids') or (0,)
query = """SELECT v.id FROM ir_ui_view v LEFT JOIN ir_model_data md ON (md.model = 'ir.ui.view' AND md.res_id = v.id)
WHERE v.inherit_id=%s AND v.model=%s AND (md.module IS NULL or md.module in %s)
WHERE v.inherit_id=%s AND v.model=%s AND (md.module in %s OR v.id in %s)
ORDER BY priority"""
query_params = (view_id, model, tuple(self.pool._init_modules))
query_params = (view_id, model, tuple(self.pool._init_modules), tuple(check_view_ids))
else:
# Modules fully loaded, consider all views
query = """SELECT v.id FROM ir_ui_view v
@ -282,6 +289,22 @@ class view(osv.osv):
'blank_nodes': blank_nodes,
'node_parent_field': _Model_Field,}
def _validate_custom_views(self, cr, uid, model):
"""Validate architecture of custom views (= without xml id) for a given model.
This method is called at the end of registry update.
"""
cr.execute("""SELECT max(v.id)
FROM ir_ui_view v
LEFT JOIN ir_model_data md ON (md.model = 'ir.ui.view' AND md.res_id = v.id)
WHERE md.module IS NULL
AND v.model = %s
GROUP BY coalesce(v.inherit_id, v.id)
""", (model,))
ids = map(itemgetter(0), cr.fetchall())
return self._check_xml(cr, uid, ids)
class view_sc(osv.osv):
_name = 'ir.ui.view_sc'
_columns = {

View File

@ -7,6 +7,7 @@ import test_menu
import test_res_config
import test_res_lang
import test_search
import test_views
checks = [
test_base,
@ -18,4 +19,5 @@ checks = [
test_res_config,
test_res_lang,
test_search,
test_views,
]

View File

@ -0,0 +1,105 @@
from functools import partial
import unittest2
import openerp.tests.common as common
from openerp.osv.orm import except_orm
from openerp.tools import mute_logger
class test_views(common.TransactionCase):
@mute_logger('openerp.osv.orm', 'openerp.addons.base.ir.ir_ui_view')
def test_00_init_check_views(self):
Views = self.registry('ir.ui.view')
self.assertTrue(Views.pool._init)
error_msg = "Invalid XML for View Architecture"
# test arch check is call for views without xmlid during registry initialization
with self.assertRaisesRegexp(except_orm, error_msg):
Views.create(self.cr, self.uid, {
'name': 'Test View #1',
'model': 'ir.ui.view',
'arch': """<?xml version="1.0"?>
<tree>
<field name="test_1"/>
</tree>
""",
})
# same for inherited views
with self.assertRaisesRegexp(except_orm, error_msg):
# Views.pudb = True
Views.create(self.cr, self.uid, {
'name': 'Test View #2',
'model': 'ir.ui.view',
'inherit_id': self.browse_ref('base.view_view_tree').id,
'arch': """<?xml version="1.0"?>
<xpath expr="//field[@name='name']" position="after">
<field name="test_2"/>
</xpath>
""",
})
def _insert_view(self, **kw):
"""Insert view into database via a query to passtrough validation"""
kw.pop('id', None)
keys = sorted(kw.keys())
fields = ','.join('"%s"' % (k.replace('"', r'\"'),) for k in keys)
params = ','.join('%%(%s)s' % (k,) for k in keys)
query = 'INSERT INTO ir_ui_view(%s) VALUES(%s) RETURNING id' % (fields, params)
self.cr.execute(query, kw)
return self.cr.fetchone()[0]
def test_10_validate_custom_views(self):
Views = self.registry('ir.ui.view')
model = 'ir.actions.act_url'
validate = partial(Views._validate_custom_views, self.cr, self.uid, model)
# validation of a single view
vid = self._insert_view(**{
'name': 'base view',
'model': model,
'priority': 1,
'arch': """<?xml version="1.0"?>
<tree string="view">
<field name="url"/>
</tree>
""",
})
self.assertTrue(validate()) # single view
# validation of a inherited view
self._insert_view(**{
'name': 'inherited view',
'model': model,
'priority': 1,
'inherit_id': vid,
'arch': """<?xml version="1.0"?>
<xpath expr="//field[@name='url']" position="before">
<field name="name"/>
</xpath>
""",
})
self.assertTrue(validate()) # inherited view
# validation of a bad inherited view
self._insert_view(**{
'name': 'bad inherited view',
'model': model,
'priority': 2,
'inherit_id': vid,
'arch': """<?xml version="1.0"?>
<xpath expr="//field[@name='url']" position="after">
<field name="bad"/>
</xpath>
""",
})
with mute_logger('openerp.osv.orm', 'openerp.addons.base.ir.ir_ui_view'):
self.assertFalse(validate()) # bad inherited view
if __name__ == '__main__':
unittest2.main()

View File

@ -400,12 +400,22 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
_logger.info('Reloading registry once more after uninstalling modules')
return openerp.modules.registry.RegistryManager.new(cr.dbname, force_demo, status, update_module)
# STEP 7: verify custom views on every model
if update_module:
Views = registry['ir.ui.view']
custom_view_test = True
for model in registry.models.keys():
if not Views._validate_custom_views(cr, SUPERUSER_ID, model):
custom_view_test = False
_logger.error('invalid custom view(s) for model %s', model)
report.record_result(custom_view_test)
if report.failures:
_logger.error('At least one test failed when loading the modules.')
else:
_logger.info('Modules loaded.')
# STEP 7: call _register_hook on every model
# STEP 8: call _register_hook on every model
for model in registry.models.values():
model._register_hook(cr)

View File

@ -89,7 +89,7 @@ class MigrationManager(object):
'post': '[%s>]',
}
if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade'):
if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade') or pkg.installed_version is None:
return
def convert_version(version):

View File

@ -2191,7 +2191,7 @@ class BaseModel(object):
are applied
"""
sql_inherit = self.pool.get('ir.ui.view').get_inheriting_views_arch(cr, user, inherit_id, self._name)
sql_inherit = self.pool.get('ir.ui.view').get_inheriting_views_arch(cr, user, inherit_id, self._name, context=context)
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)

View File

@ -832,8 +832,11 @@ def trans_generate(lang, modules, cr):
if module:
src_file = open(fabsolutepath, 'r')
try:
for lineno, message, comments in extract.extract(extract_method, src_file,
keywords=extract_keywords):
for extracted in extract.extract(extract_method, src_file,
keywords=extract_keywords):
# Babel 0.9.6 yields lineno, message, comments
# Babel 1.3 yields lineno, message, comments, context
lineno, message, comments = extracted[:3]
push_translation(module, trans_type, display_path, lineno,
encode(message), comments + extra_comments)
except Exception: