diff --git a/addons/base_module_quality/base_module_quality.py b/addons/base_module_quality/base_module_quality.py index 637eb9e22b6..d7ac2f77700 100644 --- a/addons/base_module_quality/base_module_quality.py +++ b/addons/base_module_quality/base_module_quality.py @@ -21,13 +21,10 @@ import os import pooler -import osv -import tools -from tools import config from tools.translate import _ from osv import osv, fields import logging - +import addons class abstract_quality_check(object): ''' This Class is abstract class for all test @@ -86,12 +83,10 @@ class abstract_quality_check(object): #The tests have to subscribe itselfs in this list, that contains #all the test that have to be performed. self.tests = [] - self.list_folders = os.listdir(config['addons_path'] + - '/base_module_quality/') - for item in self.list_folders: - self.item = item - path = config['addons_path']+'/base_module_quality/'+item - if os.path.exists(path + '/' + item + '.py') and item not in ['report', 'wizard', 'security']: + module_path = addons.get_module_path('base_module_quality') + for item in os.listdir(module_path): + path = module_path + '/' + item + if os.path.isdir(path) and os.path.exists(path + '/' + item + '.py') and item not in ['report', 'wizard', 'security']: item2 = 'base_module_quality.' + item +'.' + item x_module = __import__(item2) x_file = getattr(x_module, item) @@ -216,6 +211,7 @@ class module_quality_check(osv.osv): So here the detail result is in html format and summary will be in text_wiki format. ''' pool = pooler.get_pool(cr.dbname) + log = logging.getLogger('module.quality') obj_module = pool.get('ir.module.module') if not module_state: module_id = obj_module.search(cr, uid, [('name', '=', module_name)]) @@ -226,15 +222,22 @@ class module_quality_check(osv.osv): score_sum = 0.0 ponderation_sum = 0.0 create_ids = [] + module_path = addons.get_module_path(module_name) + log.info('Performing quality tests for %s', module_name) for test in abstract_obj.tests: - ad = tools.config['addons_path'] - if module_name == 'base': - ad = tools.config['root_path']+'/addons' - module_path = os.path.join(ad, module_name) val = test.quality_test() - if val.active: + if not val.active: + log.info('Skipping inactive step %s for %s', val.name, module_name) + continue + + log.info('Performing step %s for %s', val.name, module_name) + # Get a separate cursor per test, so that an SQL error in one + # will not block the others. + cr2 = pooler.get_db(cr.dbname).cursor() + + try: if not val.bool_installed_only or module_state == "installed": - val.run_test(cr, uid, str(module_path)) + val.run_test(cr2, uid, str(module_path)) if not val.error: data = { 'name': val.name, @@ -266,6 +269,12 @@ class module_quality_check(osv.osv): 'summary': _("The module has to be installed before running this test.") } create_ids.append((0, 0, data)) + log.info('Finished quality test step') + except Exception, e: + log.exception("Could not finish test step %s due to %s", val.name, e) + finally: + cr2.rollback() + cr2.close() final_score = ponderation_sum and '%.2f' % (score_sum / ponderation_sum * 100) or 0 data = { 'name': module_name, diff --git a/addons/base_module_quality/method_test/method_test.py b/addons/base_module_quality/method_test/method_test.py index ef4e3f59ea3..2884e064b54 100644 --- a/addons/base_module_quality/method_test/method_test.py +++ b/addons/base_module_quality/method_test/method_test.py @@ -53,21 +53,21 @@ This test checks if the module classes are raising exception when calling basic pool.get(obj).search(cr, uid, []) temp.append(_('Ok')) ok_count += 1 - except: + except Exception: temp.append(_('Exception')) ex_count += 1 try: pool.get(obj).fields_view_get(cr, uid,) temp.append(_('Ok')) ok_count += 1 - except: + except Exception: temp.append(_('Exception')) ex_count += 1 try: pool.get(obj).read(cr, uid, []) temp.append(_('Ok')) ok_count += 1 - except: + except Exception: temp.append(_('Exception')) ex_count += 1 result_dict[obj] = temp @@ -78,6 +78,7 @@ This test checks if the module classes are raising exception when calling basic return None def get_result(self, dict_method): + # TODO: improve header = ('{| border="1" cellspacing="0" cellpadding="5" align="left" \n! %-40s \n! %-16s \n! %-20s \n! %-16s ', [_('Object Name'), 'search()', 'fields_view_get()', 'read()']) detail = "" if not self.error: diff --git a/addons/base_module_quality/pylint_test/pylint_test.py b/addons/base_module_quality/pylint_test/pylint_test.py index dfae53fbbae..f30a7b34be8 100644 --- a/addons/base_module_quality/pylint_test/pylint_test.py +++ b/addons/base_module_quality/pylint_test/pylint_test.py @@ -20,8 +20,7 @@ ############################################################################## import os - -from tools import config +import addons from tools.translate import _ from base_module_quality import base_module_quality @@ -36,7 +35,7 @@ class quality_test(base_module_quality.abstract_quality_check): return None def run_test(self, cr, uid, module_path): - config_file_path = config['addons_path']+'/base_module_quality/pylint_test/pylint_test_config.txt' + config_file_path = addons.get_module_resource('base_module_quality','pylint_test', 'pylint_test_config.txt') list_files = os.listdir(module_path) for i in list_files: path = os.path.join(module_path, i) @@ -57,10 +56,9 @@ class quality_test(base_module_quality.abstract_quality_check): try: import pylint res = os.popen('pylint --rcfile=' + config_file_path + ' ' + file_path).read() - except: + except Exception, e: self.error = True - import netsvc - netsvc.Logger().notifyChannel('Pylint:', netsvc.LOG_WARNING, "Is pylint correctly installed? (http://pypi.python.org/pypi/pylint)") + self.log.exception("Cannot run pylint test for %s", file_path) self.result += _("Error. Is pylint correctly installed? (http://pypi.python.org/pypi/pylint)")+"\n" return None count += 1 @@ -68,7 +66,8 @@ class quality_test(base_module_quality.abstract_quality_check): scr = res.split("Your code has been rated at")[1].split("")[0].split("/")[0] score += float(scr) dict_py[file_py] = [file_py, scr] - except: + except Exception: + self.log.warning("Cannot parse pylint result", exc_info=True) score += 0 dict_py[file_py] = [file_py, _("Unable to parse the result. Check the details.")] replace_string = '' @@ -103,4 +102,4 @@ class quality_test(base_module_quality.abstract_quality_check): return self.format_table(header, data_list=dict_py) return "" -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_module_quality/speed_test/speed_test.py b/addons/base_module_quality/speed_test/speed_test.py index 5b78b5e096f..d8445afcdee 100644 --- a/addons/base_module_quality/speed_test/speed_test.py +++ b/addons/base_module_quality/speed_test/speed_test.py @@ -32,10 +32,10 @@ class CounterCursor(object): def reset(self): self.count = 0 - def execute(self, query, params=None): + def execute(self, query, *args, **kwargs): if query.lower().startswith('select '): self.count += 1 - return self.cr.execute(query, params) + return self.cr.execute(query, *args, **kwargs) def __getattr__(self, attr): return getattr(self.cr, attr) @@ -63,7 +63,6 @@ This test checks the speed of the module. Note that at least 5 demo data is need if obj_list: cr.execute("select w.res_model from ir_actions_todo as t left join ir_act_window as w on t.action_id=w.id where w.res_model IN %s",(tuple(obj_list),)) res = cr.fetchall() - print res for remove_obj in res: if remove_obj and (remove_obj[0] in obj_list): obj_list.remove(remove_obj[0]) @@ -75,10 +74,15 @@ This test checks the speed of the module. Note that at least 5 demo data is need return None obj_counter = 0 score = 0.0 - obj_ids = self.get_ids(cr, uid, obj_list) + try: + obj_ids = self.get_ids(cr, uid, obj_list) + except Exception,e: + self.log.warning("Cannot get ids:", exc_info=True) + obj_ids= {} + self.result_details += e.message result_dict = {} result_dict2 = {} - self.result_details += _("O(1) means that the number of SQL requests to read the object does not depand on the number of objects we are reading. This feature is hardly wished.\n") + self.result_details += _("O(1) means that the number of SQL requests to read the object does not depand on the number of objects we are reading. This feature is mostly wished.\n") ccr = CounterCursor(cr) for obj, ids in obj_ids.items(): code_base_complexity = 0 @@ -107,6 +111,7 @@ This test checks the speed of the module. Note that at least 5 demo data is need code_size_complexity = ccr.count except Exception, e: + self.log.warning('Error in read method', exc_info=True) list2 = [obj, _("Error in Read method")] speed_list = [obj, size, code_base_complexity, code_half_complexity, code_size_complexity, _("Error in Read method:" + str(e))] else: @@ -130,7 +135,7 @@ This test checks the speed of the module. Note that at least 5 demo data is need result_dict2[obj] = list2 self.score = obj_counter and score / obj_counter or 0.0 if self.score*100 < self.min_score: - self.message = 'Score is below than minimal score(%s%%)' % self.min_score + self.message = _('Score is below than minimal score(%s%%)') % self.min_score self.result_details += self.get_result_details(result_dict) self.result += self.get_result(result_dict2) return None