From 5daa2f6a58fddaef074b1ab226264f727cfd43d2 Mon Sep 17 00:00:00 2001 From: "mra (Open ERP)" Date: Tue, 23 Dec 2008 14:06:25 +0530 Subject: [PATCH 1/7] base module quality bzr revid: mra@tinyerp.com-20081223083625-50ecblg4n0ungj35 --- .../method_test/method_test.py | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/addons/base_module_quality/method_test/method_test.py b/addons/base_module_quality/method_test/method_test.py index 84f3f167247..c64ad468d2e 100644 --- a/addons/base_module_quality/method_test/method_test.py +++ b/addons/base_module_quality/method_test/method_test.py @@ -42,18 +42,20 @@ Method Test: return None def run_test(self, module_path, module_name=None, cr=None, uid=None): + model_list = [] pool = pooler.get_pool(cr.dbname) - ids2 = pool.get('ir.model.data').search(cr, uid, [('module','=', module_name), ('model','=','ir.model')]) + model_obj = pool.get('ir.model.data') + ids2 = model_obj.search(cr, uid, [('module','=', module_name), ('model','=','ir.model')]) + model_data = model_obj.browse(cr, uid, ids2) + for model in model_data: + model_list.append(model.res_id) obj_list = [] - for mod in pool.get('ir.model.data').browse(cr, uid, ids2): - object_name = mod.name.split('_') - object_name.pop(0) - object_name = '.'.join(object_name) - obj_list.append(str(object_name)) - result={} + for mod in pool.get('ir.model').browse(cr, uid, model_list): + obj_list.append(str(mod.model)) + result = {} self.result += "Module Name:" + module_name + '\n' + '===============\n' for obj in obj_list: - temp=[] + temp = [] try: res = pool.get(obj).search(cr, uid, []) temp.append('Ok') @@ -70,11 +72,11 @@ Method Test: except: temp.append('Exception') result[obj] = temp - self.result+=("%-40s %-12s \t %-16s %-12s")%('Object Name'.ljust(40),'search','fields_view_get','read') - self.result+='\n' + self.result += ("%-40s %12s %16s %12s")%('Object Name'.ljust(40),'search','fields_view_get','read') + self.result += '\n' for res in result: - self.result+=("%-40s %-12s \t %-16s \t %-12s")%(res.ljust(40),result[res][0],result[res][1],result[res][2]) - self.result+="\n" + self.result += ("%-40s %12s %16s %12s")%(res.ljust(40),result[res][0],result[res][1],result[res][2]) + self.result += "\n" return None From cd6b3e1941b30ae93d41ff64df04ae8df1ce1f90 Mon Sep 17 00:00:00 2001 From: qdp Date: Tue, 23 Dec 2008 16:58:47 +0100 Subject: [PATCH 2/7] improvement of base_module_quality: *changed signature of run_test() method, added cr and uid *switched wizard to osv_memory, to use text_wiki in the result window *improved method_test.py, added score computation, corrected self.bool_installed_only var, use text_wiki widget *implemented speed_test.py, first throw *improvement of base_module_quality/wizard/module_quality_check.py bzr revid: qdp@tinyerp.com-20081223155847-4qm6095jomgwvuju --- .../base_module_quality.py | 2 +- .../base_module_quality_wizard.xml | 26 +++++- .../method_test/method_test.py | 41 ++++++---- .../pylint_test/pylint_test.py | 2 +- .../speed_test/speed_test.py | 80 +++++++++++++++++-- .../wizard/module_quality_check.py | 67 +++++++++------- 6 files changed, 166 insertions(+), 52 deletions(-) diff --git a/addons/base_module_quality/base_module_quality.py b/addons/base_module_quality/base_module_quality.py index 2965ad41f16..195e345e8ef 100644 --- a/addons/base_module_quality/base_module_quality.py +++ b/addons/base_module_quality/base_module_quality.py @@ -49,7 +49,7 @@ class abstract_quality_check(object): ''' raise 'Not Implemented' - def run_test(self, module_path=""): + def run_test(self, cr, uid, module_path=""): ''' this method should do the test and fill the score, result and result_details var ''' diff --git a/addons/base_module_quality/base_module_quality_wizard.xml b/addons/base_module_quality/base_module_quality_wizard.xml index be0048feb80..df75c45715a 100644 --- a/addons/base_module_quality/base_module_quality_wizard.xml +++ b/addons/base_module_quality/base_module_quality_wizard.xml @@ -1,6 +1,28 @@ - + + + + Results of Quality Checks + wizard.quality.check + form + +
+ + + + +
+
-
\ No newline at end of file + + diff --git a/addons/base_module_quality/method_test/method_test.py b/addons/base_module_quality/method_test/method_test.py index c64ad468d2e..b89614331d2 100644 --- a/addons/base_module_quality/method_test/method_test.py +++ b/addons/base_module_quality/method_test/method_test.py @@ -31,52 +31,63 @@ class quality_test(base_module_quality.abstract_quality_check): def __init__(self): self.result = """ -Method Test: ------------- +===Method Test=== - This test checks if the class method has exception or not. +This test checks if the module classes are raising exception when calling basic methods or no. """ - self.bool_installed_only = False + self.bool_installed_only = True return None - def run_test(self, module_path, module_name=None, cr=None, uid=None): - model_list = [] + def run_test(self, cr, uid, module_path): pool = pooler.get_pool(cr.dbname) - model_obj = pool.get('ir.model.data') - ids2 = model_obj.search(cr, uid, [('module','=', module_name), ('model','=','ir.model')]) - model_data = model_obj.browse(cr, uid, ids2) + module_name = module_path.split('/')[-1] + ids2 = pool.get('ir.model.data').search(cr, uid, [('module','=', module_name), ('model','=','ir.model')]) + model_list = [] + model_data = pool.get('ir.model.data').browse(cr, uid, ids2) for model in model_data: model_list.append(model.res_id) obj_list = [] for mod in pool.get('ir.model').browse(cr, uid, model_list): obj_list.append(str(mod.model)) - result = {} - self.result += "Module Name:" + module_name + '\n' + '===============\n' + result={} + ok_count = 0 + ex_count = 0 + for obj in obj_list: temp = [] try: res = pool.get(obj).search(cr, uid, []) temp.append('Ok') + ok_count += 1 except: temp.append('Exception') + ex_count += 1 try: res1 = pool.get(obj).fields_view_get(cr, uid,) temp.append('Ok') + ok_count += 1 except: temp.append('Exception') + ex_count += 1 try: res2 = pool.get(obj).read(cr, uid, []) temp.append('Ok') + ok_count += 1 except: temp.append('Exception') + ex_count += 1 result[obj] = temp - self.result += ("%-40s %12s %16s %12s")%('Object Name'.ljust(40),'search','fields_view_get','read') - self.result += '\n' + self.result+=('{| border="1" cellspacing="0" cellpadding="5" align="left" \n! %-40s \n! %-16s \n! %-20s \n! %-16s ') % ('Object Name'.ljust(40), 'search()'.ljust(16), 'fields_view_get()'.ljust(20), 'read()'.ljust(16)) + for res in result: - self.result += ("%-40s %12s %16s %12s")%(res.ljust(40),result[res][0],result[res][1],result[res][2]) - self.result += "\n" + self.result += ('\n|-\n| %s \n| %s \n| %s \n| %s ') % (res, result[res][0],result[res][1], result[res][2]) + + self.result += '\n|}' + print "RES", self.result + self.score = (ok_count + ex_count) and float(ok_count)/float(ok_count + ex_count) or 0.0 + return None diff --git a/addons/base_module_quality/pylint_test/pylint_test.py b/addons/base_module_quality/pylint_test/pylint_test.py index bb31eef5e3a..41c2529d29a 100644 --- a/addons/base_module_quality/pylint_test/pylint_test.py +++ b/addons/base_module_quality/pylint_test/pylint_test.py @@ -41,7 +41,7 @@ Pylint Test: self.bool_installed_only = False return None - def run_test(self, module_path): + def run_test(self, cr, uid, module_path): config_file_path = config['addons_path']+'/base_module_quality/pylint_test/pylint_test_config.txt' list_files = os.listdir(module_path) for i in list_files: diff --git a/addons/base_module_quality/speed_test/speed_test.py b/addons/base_module_quality/speed_test/speed_test.py index 89479ddf18b..7858974dd00 100644 --- a/addons/base_module_quality/speed_test/speed_test.py +++ b/addons/base_module_quality/speed_test/speed_test.py @@ -24,6 +24,9 @@ import netsvc from osv import fields, osv import os from tools import config +import pooler +import time + from base_module_quality import base_module_quality @@ -32,19 +35,84 @@ class quality_test(base_module_quality.abstract_quality_check): def __init__(self): self.result = """ -Speed Test: ------------- - - This test checks the speed of the module +===Speed Test=== - to be continued... +This test checks the speed of the module. + """ self.bool_installed_only = True return None - def run_test(self, module_path): + def run_test(self, cr, uid, module_path): + pool = pooler.get_pool(cr.dbname) + module_name = module_path.split('/')[-1] + self.result+=('{| border="1" cellspacing="0" cellpadding="5" align="left" \n! %-40s \n! %-10s \n! %-10s \n! %-10s \n! %-10s \n! %-20s') % ('Object Name'.ljust(40), 'Size (S)'.ljust(10), '1'.ljust(10), 'S/2'.ljust(10), 'S'.ljust(10), 'Complexity'.ljust(20)) + ids2 = pool.get('ir.model.data').search(cr, uid, [('module','=', module_name), ('model','=','ir.model')]) + model_data = pool.get('ir.model.data').browse(cr, uid, ids2) + model_list = [] + for model in model_data: + model_list.append(model.res_id) + obj_list = [] + for mod in pool.get('ir.model').browse(cr, uid, model_list): + obj_list.append(str(mod.model)) + + obj_counter = 0 + score = 0 + for obj in obj_list: + obj_counter += 1 + ids = pool.get(obj).search(cr, uid, []) + ids = ids[:100] + size = len(ids) + if size: + c1 = time.time() + pool.get(obj).read(cr, uid, ids[0]) + c2 = time.time() + base_time = c2 - c1 + + c1 = time.time() + pool.get(obj).read(cr, uid, ids[:size/2]) + c2 = time.time() + halfsize_time = c2 - c1 + + c1 = time.time() + pool.get(obj).read(cr, uid, ids) + c2 = time.time() + size_time = c2 - c1 + if size < 5: + self.score += -2 + self.result += ('\n|-\n| %s \n| %s \n| %s \n| %s \n| %s \n| %s ') % (obj, size, base_time, halfsize_time, size_time, "Warning! Not enough demo data") + else: + tolerated_margin = 5/100 + complexity = "not recognized" + if min(size_time,base_time,halfsize_time) != base_time: + complexity = "O(1)" + score += 10 + + else: + k1 = (halfsize_time - base_time)*1000 / ((size/2) - 1) + k2 = (size_time - base_time)*1000 / ((size) - 1) + tmp = k1 * tolerated_margin + if (k1 - tmp) < k2 and k2 < (k1 + tmp): + complexity = "O(n)" + if round(tmp) == 0: + complexity = "O(1)" + score += 10 + else: + score += 5 + else: + complexity = "O(n²) or worst" + score += 0 + + self.result += ('\n|-\n| %s \n| %s \n| %s \n| %s \n| %s \n| %s ') % (obj, size, base_time, halfsize_time, size_time, complexity) + else: + score += -5 + self.result += ('\n|-\n| %s \n| %s \n| %s \n| %s \n| %s \n| %s ') % (obj, size, "", "", "", "Warning! Object has no demo data") + + + self.result += '\n|}' + self.score = obj_counter and score/obj_counter or 0.0 return None # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_module_quality/wizard/module_quality_check.py b/addons/base_module_quality/wizard/module_quality_check.py index da067551e6d..7eafc24e933 100644 --- a/addons/base_module_quality/wizard/module_quality_check.py +++ b/addons/base_module_quality/wizard/module_quality_check.py @@ -21,81 +21,94 @@ ############################################################################## import wizard import pooler +from osv import osv, fields import tools import os #TODO: (utiliser les nouveaux wizards pour heriter la vue et rajouter un onglet par test?) -#TODO: configure pylint #TODO: implement the speed test -#TODO: implement the simple test #TODO: add cheks: do the class quality_check inherits the class abstract_quality_check? #TODO: improve translability +#TODO: clean #To keep or not? to be discussed... -view_form = """ -
- - - - - -
""" +#~ view_form = """ +#~
+ #~ + #~ + #~ + #~ + #~ +#~
""" -view_field = { - "general_info": {'type': 'text', 'string': 'General Info', 'readonly':True}, -} +#~ view_field = { + #~ "general_info": {'type': 'text', 'string': 'General Info', 'readonly':True}, +#~ } -class wiz_quality_check(wizard.interface): +class wiz_quality_check(osv.osv_memory): + +# general_info = "" + _name = 'wizard.quality.check' def _check(self, cr, uid, data, context={}): string_ret = "" from tools import config + print data + data['ids'] = data.get('module_id', False) pool = pooler.get_pool(cr.dbname) - module_data = pool.get('ir.module.module').browse(cr, uid, data['ids']) + module_data = pool.get('ir.module.module').browse(cr, uid, [data['ids']]) list_folders = os.listdir(config['addons_path']+'/base_module_quality/') module_name = module_data[0].name for item in list_folders: path = config['addons_path']+'/base_module_quality/'+item if os.path.exists(path+'/'+item+'.py') and item not in ['report', 'wizard', 'security']: ad = tools.config['addons_path'] + if module_data[0].name == 'base': + ad = tools.config['root_path']+'/addons' module_path = os.path.join(ad, module_data[0].name) item2 = 'base_module_quality.'+item+'.'+item x = __import__(item2) x2 = getattr(x, item) x3 = getattr(x2, item) val = x3.quality_test() - if (not val.bool_installed_only or module_data[0].state == "installed") and item == 'method_test': - val.run_test(str(module_path), module_name, cr, uid) - elif not val.bool_installed_only or module_data[0].state == "installed" : - val.run_test(str(module_path)) + if (not val.bool_installed_only or module_data[0].state == "installed"): + val.run_test(cr, uid, str(module_path)) else: val.result += "The module has to be installed before running this test." string_ret += val.result + return string_ret - return {'general_info':string_ret} +# def _general_info(self, cr, uid, data, context={}): +# return self.general_info - states = { + #~ states = { + #~ 'init': { + #~ 'actions': [_check], + #~ 'result': {'type':'form', 'arch':view_form, 'fields':view_field, 'state':[('end','Ok')]}, + #~ }, + #~ } #To keep or not? to be discussed... #~ 'init': { #~ 'actions': [], #~ 'result': {'type':'form', 'arch':form_check, 'fields':fields_check, 'state':[('end','Cancel'),('do','Do Test')]} #~ }, - 'init': { - 'actions': [_check], - 'result': {'type':'form', 'arch':view_form, 'fields':view_field, 'state':[('end','Ok')]}, - }, - } + _columns = { + 'general_info': fields.text('General Info', readonly="1",), + } + _defaults = { + 'general_info': _check + } -wiz_quality_check('base.module.quality') +wiz_quality_check() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 1babad50c2aa1b3a5aa960eeeef41754cc6698cc Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 23 Dec 2008 17:22:10 +0100 Subject: [PATCH 3/7] [FIX] bug with invoice lp bug: https://launchpad.net/bugs/310919 fixed bzr revid: christophe@cobalt-20081223162210-chbr8wg9ae19cwbm --- addons/account/invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account/invoice.py b/addons/account/invoice.py index 5887613940c..39e03c710ad 100644 --- a/addons/account/invoice.py +++ b/addons/account/invoice.py @@ -448,10 +448,10 @@ class account_invoice(osv.osv): ait_obj = self.pool.get('account.invoice.tax') cur_obj = self.pool.get('res.currency') acc_obj = self.pool.get('account.account') + self.button_compute(cr, uid, ids, context={}, set_total=True) for inv in self.browse(cr, uid, ids): if inv.move_id: continue - self.button_compute(cr, uid, ids, context={},set_total=True) if inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0): raise osv.except_osv(_('Bad total !'), _('Please verify the price of the invoice !\nThe real total does not match the computed total.')) if not inv.date_invoice: From 0589e6e2855c075678e1e8715b1c085bc9b9f92f Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 23 Dec 2008 18:38:53 +0100 Subject: [PATCH 4/7] [FIX] change parameters position to be compatible with the herited function lp bug: https://launchpad.net/bugs/310939 fixed bzr revid: christophe@cobalt-20081223173853-x9hxv0ag3bmuvlz0 --- .../analytic_journal_billing_rate.py | 2 +- .../analytic_journal_billing_rate_view.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/analytic_journal_billing_rate/analytic_journal_billing_rate.py b/addons/analytic_journal_billing_rate/analytic_journal_billing_rate.py index 58e9d9a7fb8..471421638de 100644 --- a/addons/analytic_journal_billing_rate/analytic_journal_billing_rate.py +++ b/addons/analytic_journal_billing_rate/analytic_journal_billing_rate.py @@ -48,7 +48,7 @@ class hr_analytic_timesheet(osv.osv): _inherit = "hr.analytic.timesheet" - def on_change_account_id(self, cr, uid, ids,user_id, account_id, journal_id,unit_amount=0): + def on_change_account_id(self, cr, uid, ids,user_id, account_id, unit_amount=0, journal_id=0): res = {} if not (account_id): #avoid a useless call to super diff --git a/addons/analytic_journal_billing_rate/analytic_journal_billing_rate_view.xml b/addons/analytic_journal_billing_rate/analytic_journal_billing_rate_view.xml index cc5219efb30..c5c797a3a83 100644 --- a/addons/analytic_journal_billing_rate/analytic_journal_billing_rate_view.xml +++ b/addons/analytic_journal_billing_rate/analytic_journal_billing_rate_view.xml @@ -49,7 +49,7 @@ - + @@ -62,7 +62,7 @@ - + From 7dbde98cc6fa77aed11170ebe4f72a347832aed3 Mon Sep 17 00:00:00 2001 From: apa-tiny Date: Wed, 24 Dec 2008 12:13:39 +0530 Subject: [PATCH 5/7] Add payment_order.py for Payment order report-vir bzr revid: patelamit2003@gmail.com-20081224064339-djlcd233355v437u --- addons/account_payment/report/__init__.py | 23 +++++++++++++ .../account_payment/report/payment_order.py | 34 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 addons/account_payment/report/__init__.py create mode 100644 addons/account_payment/report/payment_order.py diff --git a/addons/account_payment/report/__init__.py b/addons/account_payment/report/__init__.py new file mode 100644 index 00000000000..a9cc99d8279 --- /dev/null +++ b/addons/account_payment/report/__init__.py @@ -0,0 +1,23 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + +import payment_order diff --git a/addons/account_payment/report/payment_order.py b/addons/account_payment/report/payment_order.py new file mode 100644 index 00000000000..f3e9b612d62 --- /dev/null +++ b/addons/account_payment/report/payment_order.py @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + +import time +import datetime +from report import report_sxw + +class payment_order(report_sxw.rml_parse): + def __init__(self, cr, uid, name, context): + super(payment_order, self).__init__(cr, uid, name, context) + self.localcontext.update( { + 'time': time, + + }) +report_sxw.report_sxw('report.payment.order', 'payement.order', 'addons/account_payment/report/payment_order.rml', parser=payment_order,header=False) \ No newline at end of file From 22e08146f917b7408d4feac17be10b7f30bb038b Mon Sep 17 00:00:00 2001 From: apa-tiny Date: Wed, 24 Dec 2008 12:18:04 +0530 Subject: [PATCH 6/7] modify for payment orrder report-vir bzr revid: patelamit2003@gmail.com-20081224064804-8kqv94b2yfdcfco1 --- addons/account_payment/payment_report.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account_payment/payment_report.xml b/addons/account_payment/payment_report.xml index 16e1185355e..0f39148f719 100644 --- a/addons/account_payment/payment_report.xml +++ b/addons/account_payment/payment_report.xml @@ -1,6 +1,6 @@ - + From dd30ce0e8baf788ee77bd829f8e8cc7eff05cf0a Mon Sep 17 00:00:00 2001 From: "mra (Open ERP)" Date: Wed, 24 Dec 2008 12:50:46 +0530 Subject: [PATCH 7/7] base module quality..format the form bzr revid: mra@tinyerp.com-20081224072046-i2e91527kxqy6iia --- .../base_module_quality/base_module_quality_wizard.xml | 6 +++--- addons/base_module_quality/method_test/method_test.py | 7 ++----- addons/base_module_quality/pylint_test/pylint_test.py | 10 ++++------ addons/base_module_quality/speed_test/speed_test.py | 6 ++---- .../base_module_quality/wizard/module_quality_check.py | 1 - 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/addons/base_module_quality/base_module_quality_wizard.xml b/addons/base_module_quality/base_module_quality_wizard.xml index df75c45715a..c99b949be35 100644 --- a/addons/base_module_quality/base_module_quality_wizard.xml +++ b/addons/base_module_quality/base_module_quality_wizard.xml @@ -15,9 +15,9 @@