diff --git a/openerp-server b/openerp-server index 12b6962e4e6..be0710cbce9 100755 --- a/openerp-server +++ b/openerp-server @@ -105,7 +105,7 @@ def run_test_file(dbname, test_file): db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False) cr = db.cursor() _logger.info('loading test file %s', test_file) - openerp.tools.convert_yaml_import(cr, 'base', file(test_file), {}, 'test', True) + openerp.tools.convert_yaml_import(cr, 'base', file(test_file), 'test', {}, 'test', True) cr.rollback() cr.close() except Exception: diff --git a/openerp/addons/base/res/res_partner_view.xml b/openerp/addons/base/res/res_partner_view.xml index 67fb3b5d6e4..d98c486a00d 100644 --- a/openerp/addons/base/res/res_partner_view.xml +++ b/openerp/addons/base/res/res_partner_view.xml @@ -201,7 +201,7 @@
- +
diff --git a/openerp/addons/base/test/base_test.yml b/openerp/addons/base/test/base_test.yml index fe22e3a4935..1aea2363f84 100644 --- a/openerp/addons/base/test/base_test.yml +++ b/openerp/addons/base/test/base_test.yml @@ -42,15 +42,13 @@ - !python {model: ir.model}: | from tools.safe_eval import safe_eval + from tools.misc import mute_logger try: - safe_eval('open("/etc/passwd","r")') - assert False, "safe_eval should not allow calling open() builtin" + with mute_logger('openerp.tools.safe_eval'): + safe_eval('open("/etc/passwd","r")') + assert False, "safe_eval should not allow calling open() builtin" except NameError: - pass - except: - # NameError should be raised because open() builtin is not found, - # but other exceptions probably indicate that open() was executed! - assert False, "safe_eval should not allow calling open() builtin" + pass - "ORM test: verify that parent_store computation are going right" diff --git a/openerp/modules/loading.py b/openerp/modules/loading.py index 874a6ce7063..8a2c43e6ed2 100644 --- a/openerp/modules/loading.py +++ b/openerp/modules/loading.py @@ -3,7 +3,7 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). -# Copyright (C) 2010-2011 OpenERP s.a. (). +# Copyright (C) 2010-2012 OpenERP s.a. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -84,7 +84,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules= _load_data(cr, module_name, idref, mode, 'test') return True except Exception: - _logger.error( + _logger.exception( 'module %s: an exception occurred in a test', module_name) return False finally: @@ -119,7 +119,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules= elif ext == '.sql': process_sql_file(cr, fp) elif ext == '.yml': - tools.convert_yaml_import(cr, module_name, fp, idref, mode, noupdate, report) + tools.convert_yaml_import(cr, module_name, fp, kind, idref, mode, noupdate, report) else: tools.convert_xml_import(cr, module_name, fp, idref, mode, noupdate, report) finally: diff --git a/openerp/netsvc.py b/openerp/netsvc.py index 506c1e4bcba..170108a13ad 100644 --- a/openerp/netsvc.py +++ b/openerp/netsvc.py @@ -3,7 +3,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2004-2011 OpenERP SA () +# Copyright (C) 2004-2012 OpenERP SA () # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -376,11 +376,11 @@ def dispatch_rpc(service_name, method, params): except openerp.exceptions.Warning: raise except openerp.exceptions.DeferredException, e: - _logger.error(tools.exception_to_unicode(e)) + _logger.exception(tools.exception_to_unicode(e)) post_mortem(e.traceback) raise except Exception, e: - _logger.error(tools.exception_to_unicode(e)) + _logger.exception(tools.exception_to_unicode(e)) post_mortem(sys.exc_info()) raise diff --git a/openerp/tests/addons/test_impex/tests/test_import.py b/openerp/tests/addons/test_impex/tests/test_import.py index ab12f0375b5..4712d53feff 100644 --- a/openerp/tests/addons/test_impex/tests/test_import.py +++ b/openerp/tests/addons/test_impex/tests/test_import.py @@ -3,6 +3,7 @@ import openerp.modules.registry import openerp from openerp.tests import common +from openerp.tools.misc import mute_logger def ok(n): """ Successful import of ``n`` records @@ -221,6 +222,7 @@ class test_integer_field(ImporterCase): -1, -42, -(2**31 - 1), -(2**31), -12345678 ], values(self.read())) + @mute_logger('openerp.sql_db') def test_out_of_range(self): self.assertEqual( self.import_(['value'], [[str(2**31)]]), diff --git a/openerp/tests/test_ir_sequence.py b/openerp/tests/test_ir_sequence.py index fcc5888e47e..b1076e830ee 100644 --- a/openerp/tests/test_ir_sequence.py +++ b/openerp/tests/test_ir_sequence.py @@ -22,6 +22,16 @@ def registry(model): def cursor(): return openerp.modules.registry.RegistryManager.get(DB).db.cursor() + +def drop_sequence(code): + cr = cursor() + for model in ['ir.sequence', 'ir.sequence.type']: + s = registry(model) + ids = s.search(cr, ADMIN_USER_ID, [('code', '=', code)]) + s.unlink(cr, ADMIN_USER_ID, ids) + cr.commit() + cr.close() + class test_ir_sequence_standard(unittest2.TestCase): """ A few tests for a 'Standard' (i.e. PostgreSQL) sequence. """ @@ -48,7 +58,7 @@ class test_ir_sequence_standard(unittest2.TestCase): def test_ir_sequence_draw(self): """ Try to draw a number. """ cr = cursor() - n = registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type', {}) + n = registry('ir.sequence').next_by_code(cr, ADMIN_USER_ID, 'test_sequence_type', {}) assert n cr.commit() cr.close() @@ -57,15 +67,19 @@ class test_ir_sequence_standard(unittest2.TestCase): """ Try to draw a number from two transactions. """ cr0 = cursor() cr1 = cursor() - n0 = registry('ir.sequence').get(cr0, ADMIN_USER_ID, 'test_sequence_type', {}) + n0 = registry('ir.sequence').next_by_code(cr0, ADMIN_USER_ID, 'test_sequence_type', {}) assert n0 - n1 = registry('ir.sequence').get(cr1, ADMIN_USER_ID, 'test_sequence_type', {}) + n1 = registry('ir.sequence').next_by_code(cr1, ADMIN_USER_ID, 'test_sequence_type', {}) assert n1 cr0.commit() cr1.commit() cr0.close() cr1.close() + @classmethod + def tearDownClass(cls): + drop_sequence('test_sequence_type') + class test_ir_sequence_no_gap(unittest2.TestCase): """ Copy of the previous tests for a 'No gap' sequence. """ @@ -85,7 +99,7 @@ class test_ir_sequence_no_gap(unittest2.TestCase): def test_ir_sequence_draw_no_gap(self): """ Try to draw a number. """ cr = cursor() - n = registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type_2', {}) + n = registry('ir.sequence').next_by_code(cr, ADMIN_USER_ID, 'test_sequence_type_2', {}) assert n cr.commit() cr.close() @@ -99,12 +113,16 @@ class test_ir_sequence_no_gap(unittest2.TestCase): cr1._default_log_exceptions = False # Prevent logging a traceback msg_re = '^could not obtain lock on row in relation "ir_sequence"$' with self.assertRaisesRegexp(psycopg2.OperationalError, msg_re): - n0 = registry('ir.sequence').get(cr0, ADMIN_USER_ID, 'test_sequence_type_2', {}) + n0 = registry('ir.sequence').next_by_code(cr0, ADMIN_USER_ID, 'test_sequence_type_2', {}) assert n0 - n1 = registry('ir.sequence').get(cr1, ADMIN_USER_ID, 'test_sequence_type_2', {}) + n1 = registry('ir.sequence').next_by_code(cr1, ADMIN_USER_ID, 'test_sequence_type_2', {}) cr0.close() cr1.close() + @classmethod + def tearDownClass(cls): + drop_sequence('test_sequence_type_2') + class test_ir_sequence_change_implementation(unittest2.TestCase): """ Create sequence objects and change their ``implementation`` field. """ @@ -146,6 +164,11 @@ class test_ir_sequence_change_implementation(unittest2.TestCase): cr.commit() cr.close() + @classmethod + def tearDownClass(cls): + drop_sequence('test_sequence_type_3') + drop_sequence('test_sequence_type_4') + class test_ir_sequence_generate(unittest2.TestCase): """ Create sequence objects and generate some values. """ @@ -162,7 +185,7 @@ class test_ir_sequence_generate(unittest2.TestCase): cr.close() cr = cursor() - f = lambda *a: registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type_5', {}) + f = lambda *a: registry('ir.sequence').next_by_code(cr, ADMIN_USER_ID, 'test_sequence_type_5', {}) assert all(str(x) == f() for x in xrange(1,1000)) cr.commit() cr.close() @@ -180,11 +203,15 @@ class test_ir_sequence_generate(unittest2.TestCase): cr.close() cr = cursor() - f = lambda *a: registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type_6', {}) + f = lambda *a: registry('ir.sequence').next_by_code(cr, ADMIN_USER_ID, 'test_sequence_type_6', {}) assert all(str(x) == f() for x in xrange(1,1000)) cr.commit() cr.close() - + + @classmethod + def tearDownClass(cls): + drop_sequence('test_sequence_type_5') + drop_sequence('test_sequence_type_6') if __name__ == '__main__': diff --git a/openerp/tools/misc.py b/openerp/tools/misc.py index 8ca90e32f07..024d75fcae0 100644 --- a/openerp/tools/misc.py +++ b/openerp/tools/misc.py @@ -1146,4 +1146,37 @@ class UnquoteEvalContext(defaultdict): def __missing__(self, key): return unquote(key) + +class mute_logger(object): + """Temporary suppress the logging. + Can be used as context manager or decorator. + + @mute_logger('openerp.plic.ploc') + def do_stuff(): + blahblah() + + with mute_logger('openerp.foo.bar'): + do_suff() + + """ + def __init__(self, *loggers): + self.loggers = loggers + + def filter(self, record): + return 0 + + def __enter__(self): + for logger in self.loggers: + logging.getLogger(logger).addFilter(self) + + def __exit__(self, exc_type=None, exc_val=None, exc_tb=None): + for logger in self.loggers: + logging.getLogger(logger).removeFilter(self) + + def __call__(self, func): + @wraps(func) + def deco(*args, **kwargs): + with self: + return func(*args, **kwargs) + return deco # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/tools/yaml_import.py b/openerp/tools/yaml_import.py index 136d1bcee7b..57af9e45e89 100644 --- a/openerp/tools/yaml_import.py +++ b/openerp/tools/yaml_import.py @@ -100,7 +100,7 @@ class RecordDictWrapper(dict): return dict.__getitem__(self, key) class YamlInterpreter(object): - def __init__(self, cr, module, id_map, mode, filename, report=None, noupdate=False): + def __init__(self, cr, module, id_map, mode, filename, report=None, noupdate=False, loglevel=logging.DEBUG): self.cr = cr self.module = module self.id_map = id_map @@ -110,6 +110,7 @@ class YamlInterpreter(object): report = assertion_report.assertion_report() self.assertion_report = report self.noupdate = noupdate + self.loglevel = loglevel self.pool = pooler.get_pool(cr.dbname) self.uid = 1 self.context = {} # opererp context @@ -119,6 +120,9 @@ class YamlInterpreter(object): 'datetime': datetime, 'timedelta': timedelta} + def _log(self, *args, **kwargs): + _logger.log(self.loglevel, *args, **kwargs) + def _ref(self): return lambda xml_id: self.get_id(xml_id) @@ -484,12 +488,10 @@ class YamlInterpreter(object): self.noupdate = node.noupdate def process_python(self, node): - def log(msg, *args): - _logger.log(logging.TEST, msg, *args) python, statements = node.items()[0] model = self.get_model(python.model) statements = statements.replace("\r\n", "\n") - code_context = {'model': model, 'cr': self.cr, 'uid': self.uid, 'log': log, 'context': self.context} + code_context = {'model': model, 'cr': self.cr, 'uid': self.uid, 'log': self._log, 'context': self.context} code_context.update({'self': model}) # remove me when no !python block test uses 'self' anymore try: code_obj = compile(statements, self.filename, 'exec') @@ -720,7 +722,7 @@ class YamlInterpreter(object): if len(ids): self.pool.get(node.model).unlink(self.cr, self.uid, ids) else: - _logger.log(logging.TEST, "Record not deleted.") + self._log("Record not deleted.") def process_url(self, node): self.validate_xml_id(node.id) @@ -805,7 +807,7 @@ class YamlInterpreter(object): is_preceded_by_comment = False for node in yaml.load(yaml_string): - is_preceded_by_comment = self._log(node, is_preceded_by_comment) + is_preceded_by_comment = self._log_node(node, is_preceded_by_comment) try: self._process_node(node) except YamlImportException, e: @@ -852,26 +854,27 @@ class YamlInterpreter(object): else: raise YamlImportException("Can not process YAML block: %s" % node) - def _log(self, node, is_preceded_by_comment): + def _log_node(self, node, is_preceded_by_comment): if is_comment(node): is_preceded_by_comment = True - _logger.log(logging.TEST, node) + self._log(node) elif not is_preceded_by_comment: if isinstance(node, types.DictionaryType): msg = "Creating %s\n with %s" args = node.items()[0] - _logger.log(logging.TEST, msg, *args) + self._log(msg, *args) else: - _logger.log(logging.TEST, node) + self._log(node) else: is_preceded_by_comment = False return is_preceded_by_comment -def yaml_import(cr, module, yamlfile, idref=None, mode='init', noupdate=False, report=None): +def yaml_import(cr, module, yamlfile, kind, idref=None, mode='init', noupdate=False, report=None): if idref is None: idref = {} + loglevel = logging.TEST if kind == 'test' else logging.DEBUG yaml_string = yamlfile.read() - yaml_interpreter = YamlInterpreter(cr, module, idref, mode, filename=yamlfile.name, report=report, noupdate=noupdate) + yaml_interpreter = YamlInterpreter(cr, module, idref, mode, filename=yamlfile.name, report=report, noupdate=noupdate, loglevel=loglevel) yaml_interpreter.process(yaml_string) # keeps convention of convert.py