From f2087d57f3ca135493aeb89f180b939b2a607f29 Mon Sep 17 00:00:00 2001 From: "Harry (Open ERP)" Date: Wed, 23 Sep 2009 14:42:19 +0530 Subject: [PATCH 01/19] [IMP]quality_integration_server: quality log : add new option to specify qualitylog path to store html pages of log bzr revid: hmo@tinyerp.com-20090923091219-owu6zi4jio20xt1f --- .../base_quality_interrogation.py | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/bin/addons/quality_integration_server/base_quality_interrogation.py b/bin/addons/quality_integration_server/base_quality_interrogation.py index f4e84f5194a..3f3010350f3 100755 --- a/bin/addons/quality_integration_server/base_quality_interrogation.py +++ b/bin/addons/quality_integration_server/base_quality_interrogation.py @@ -101,8 +101,9 @@ def import_translate(uri, user, pwd, dbname, translate_in): state = res['state'] -def check_quality(uri, user, pwd, dbname, modules): +def check_quality(uri, user, pwd, dbname, modules, quality_logs): uid = login(uri, dbname, user, pwd) + quality_logs += 'quality-logs' if uid: conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object') final = {} @@ -111,7 +112,7 @@ def check_quality(uri, user, pwd, dbname, modules): test_detail = {} quality_result = execute(conn,'execute', dbname, uid, pwd,'module.quality.check','check_quality',module) detail_html = '' - html = '''''' + html = '''''' html +="

Module : %s

"%(quality_result['name']) html += "

Final score : %s

"%(quality_result['final_score']) html += "
" @@ -126,15 +127,21 @@ def check_quality(uri, user, pwd, dbname, modules): detail['detail'] = '''%s'''%(detail.get('summary','')) detail_html +="

%s (Score : %s)

%s
"%(test.replace(' ','-'),test,score,detail.get('detail','')) test_detail[test] = (score,msg,detail.get('detail','')) - html += "%s"%(detail_html) - html += "
" - final[quality_result['name']] = (quality_result['final_score'],html,test_detail) + html += "" + html += "%s"%(detail_html) + html += "" + if not os.path.isdir(quality_logs): + os.mkdir(quality_logs) + fp = open('%s/%s.html'%(quality_logs,module),'wb') + fp.write(str(html)) + fp.close() + #final[quality_result['name']] = (quality_result['final_score'],html,test_detail) - fp = open('quality_log.pck','wb') - pck_obj = pickle.dump(final,fp) - fp.close() - print "LOG PATH%s"%(os.path.realpath('quality_log.pck')) - return final + #fp = open('quality_log.pck','wb') + #pck_obj = pickle.dump(final,fp) + #fp.close() + #print "LOG PATH%s"%(os.path.realpath('quality_log.pck')) + return True else: print 'Login Failed...' clean() @@ -273,6 +280,7 @@ parser = optparse.OptionParser(usage) parser.add_option("--modules", dest="modules", help="specify modules to install or check quality") parser.add_option("--addons-path", dest="addons_path", help="specify the addons path") +parser.add_option("--quality-logs", dest="quality_logs", help="specify the path of quality logs files which has to stores") parser.add_option("--root-path", dest="root_path", help="specify the root path") parser.add_option("-p", "--port", dest="port", help="specify the TCP port", type="int") parser.add_option("-d", "--database", dest="db_name", help="specify the database name") @@ -303,6 +311,7 @@ die(opt.translate_in and (not opt.db_name), options = { 'addons-path' : opt.addons_path or 'addons', + 'quality-logs' : opt.quality_logs or '', 'root-path' : opt.root_path or '', 'translate-in': [], 'port' : opt.port or 8069, @@ -337,7 +346,7 @@ try: if command == 'upgrade-module': upgrade_module(uri, options['database'], options['modules'], options['login'], options['pwd']) if command == 'check-quality': - check_quality(uri, options['login'], options['pwd'], options['database'], options['modules']) + check_quality(uri, options['login'], options['pwd'], options['database'], options['modules'], options['quality-logs']) if command == 'install-translation': import_translate(uri, options['login'], options['pwd'], options['database'], options['translate-in']) clean() From 244de09ee563f0e72fa6330c71f316415bb690ad Mon Sep 17 00:00:00 2001 From: "uco(OpenERP)" <> Date: Thu, 24 Sep 2009 19:52:27 +0530 Subject: [PATCH 02/19] [FIX] Update Module : Float8 to float and numeric to float casting made possible lp bug: https://launchpad.net/bugs/433886 fixed bzr revid: jvo@tinyerp.com-20090924142227-qbx2y0a56r6d263n --- bin/osv/orm.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index cf215adf12e..812c5de3791 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1786,6 +1786,8 @@ class orm(orm_template): ('varchar', 'text', 'TEXT', ''), ('int4', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), ('date', 'datetime', 'TIMESTAMP', '::TIMESTAMP'), + ('numeric', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), + ('float8', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), ] # !!! Avoid reduction of varchar field !!! if f_pg_type == 'varchar' and f._type == 'char' and f_pg_size < f.size: @@ -1798,13 +1800,15 @@ class orm(orm_template): cr.commit() for c in casts: if (f_pg_type==c[0]) and (f._type==c[1]): - logger.notifyChannel('orm', netsvc.LOG_INFO, "column '%s' in table '%s' changed type to %s." % (k, self._table, c[1])) - ok = True - cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k)) - cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2])) - cr.execute(('UPDATE "%s" SET "%s"=temp_change_size'+c[3]) % (self._table, k)) - cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,)) - cr.commit() + if f_pg_type != f_obj_type: + logger.notifyChannel('orm', netsvc.LOG_INFO, "column '%s' in table '%s' changed type to %s." % (k, self._table, c[1])) + ok = True + cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k)) + cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2])) + cr.execute(('UPDATE "%s" SET "%s"=temp_change_size'+c[3]) % (self._table, k)) + cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,)) + cr.commit() + break if f_pg_type != f_obj_type: if not ok: From 369755e92a0f235901f13d114171839b2a379100 Mon Sep 17 00:00:00 2001 From: nch-openerp <> Date: Fri, 25 Sep 2009 13:10:13 +0530 Subject: [PATCH 03/19] [FIX]quality_integration_server: ascci encoding problem in quality html log bzr revid: hmo@tinyerp.com-20090925074013-dsnxc54vo7t7payg --- .../base_quality_interrogation.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/bin/addons/quality_integration_server/base_quality_interrogation.py b/bin/addons/quality_integration_server/base_quality_interrogation.py index 3f3010350f3..aae89368a8f 100755 --- a/bin/addons/quality_integration_server/base_quality_interrogation.py +++ b/bin/addons/quality_integration_server/base_quality_interrogation.py @@ -37,6 +37,18 @@ waittime = 10 wait_count = 0 wait_limit = 12 +def to_decode(s): + try: + return s.encode('utf-8') + except UnicodeError: + try: + return s.encode('latin') + except UnicodeError: + try: + return s.decode('ascii') + except UnicodeError: + return s + def start_server(root_path, port, addons_path): os.system('python2.5 %sopenerp-server.py --pidfile=openerp.pid --port=%s --no-netrpc --addons-path=%s' %(root_path, str(port), addons_path)) def clean(): @@ -133,7 +145,7 @@ def check_quality(uri, user, pwd, dbname, modules, quality_logs): if not os.path.isdir(quality_logs): os.mkdir(quality_logs) fp = open('%s/%s.html'%(quality_logs,module),'wb') - fp.write(str(html)) + fp.write(to_decode(html)) fp.close() #final[quality_result['name']] = (quality_result['final_score'],html,test_detail) From a5d33505a8864949d73ad8200be86d5b291a4033 Mon Sep 17 00:00:00 2001 From: "Jay (Open ERP)" Date: Tue, 29 Sep 2009 18:09:23 +0530 Subject: [PATCH 04/19] [FIX] Export Translation : Warning on Non-existing record instead of breaking flow lp bug: https://launchpad.net/bugs/437729 fixed bzr revid: jvo@tinyerp.com-20090929123923-yw60232e0sgu5nbp --- bin/tools/translate.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/tools/translate.py b/bin/tools/translate.py index 51966b992bc..62f48aaa3c6 100644 --- a/bin/tools/translate.py +++ b/bin/tools/translate.py @@ -424,14 +424,14 @@ def trans_generate(lang, modules, dbname=None): xml_name = "%s.%s" % (module, encode(xml_name)) if not pool.get(model): - logger.notifyChannel("db", netsvc.LOG_ERROR, "unable to find object %r" % (model,)) + logger.notifyChannel("db", netsvc.LOG_ERROR, "Unable to find object %r" % (model,)) continue - try: - obj = pool.get(model).browse(cr, uid, res_id) - except BrowseRecordError: - logger.notifyChannel("db", netsvc.LOG_ERROR, "unable to find object %r with id %d" % (model, res_id)) + exists = pool.get(model).exists(cr, uid, res_id) + if not exists: + logger.notifyChannel("db", netsvc.LOG_WARNING, "Unable to find object %r with id %d" % (model, res_id)) continue + obj = pool.get(model).browse(cr, uid, res_id) if model=='ir.ui.view': d = xml.dom.minidom.parseString(encode(obj.arch)) From 92df67814c628cb475ebd5fd4921c4bed570f31b Mon Sep 17 00:00:00 2001 From: "mra (Open ERP)" Date: Wed, 30 Sep 2009 12:24:19 +0530 Subject: [PATCH 05/19] [IMP] base_quality_interrrogation: put message if the score of quality less then minimal and remove unit test condition bzr revid: mra@tinyerp.com-20090930065419-23hlpso95d35z810 --- .../base_quality_interrogation.py | 165 +++++++++--------- 1 file changed, 81 insertions(+), 84 deletions(-) diff --git a/bin/addons/quality_integration_server/base_quality_interrogation.py b/bin/addons/quality_integration_server/base_quality_interrogation.py index aae89368a8f..ca9bbddc593 100755 --- a/bin/addons/quality_integration_server/base_quality_interrogation.py +++ b/bin/addons/quality_integration_server/base_quality_interrogation.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution +# OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved # $Id$ # @@ -49,24 +49,24 @@ def to_decode(s): except UnicodeError: return s -def start_server(root_path, port, addons_path): - os.system('python2.5 %sopenerp-server.py --pidfile=openerp.pid --port=%s --no-netrpc --addons-path=%s' %(root_path, str(port), addons_path)) +def start_server(root_path, port, addons_path): + os.system('python2.5 %sopenerp-server.py --pidfile=openerp.pid --port=%s --no-netrpc --addons-path=%s' %(root_path, str(port), addons_path)) def clean(): if os.path.isfile('openerp.pid'): - ps = open('openerp.pid') + ps = open('openerp.pid') if ps: pid = int(ps.read()) - ps.close() - if pid: + ps.close() + if pid: os.kill(pid,9) def execute(connector, method, *args): - global wait_count + global wait_count res = False - try: + try: res = getattr(connector,method)(*args) - except socket.error,e: - if e.args[0] == 111: + except socket.error,e: + if e.args[0] == 111: if wait_count > wait_limit: print "Server is taking too long to start, it has exceeded the maximum limit of %d seconds."%(wait_limit) clean() @@ -78,23 +78,23 @@ def execute(connector, method, *args): else: raise e wait_count = 0 - return res + return res def login(uri, dbname, user, pwd): conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common') - uid = execute(conn,'login',dbname, user, pwd) + uid = execute(conn,'login',dbname, user, pwd) return uid -def import_translate(uri, user, pwd, dbname, translate_in): - uid = login(uri, dbname, user, pwd) - if uid: +def import_translate(uri, user, pwd, dbname, translate_in): + uid = login(uri, dbname, user, pwd) + if uid: conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard') wiz_id = execute(conn,'create',dbname, uid, pwd, 'module.lang.import') for trans_in in translate_in: - lang,ext = os.path.splitext(trans_in.split('/')[-1]) - state = 'init' + lang,ext = os.path.splitext(trans_in.split('/')[-1]) + state = 'init' datas = {'form':{}} - while state!='end': + while state!='end': res = execute(conn,'execute',dbname, uid, pwd, wiz_id, datas, state, {}) if 'datas' in res: datas['form'].update( res['datas'].get('form',{}) ) @@ -110,34 +110,31 @@ def import_translate(uri, user, pwd, dbname, translate_in): }) trans_obj.close() elif res['type']=='action': - state = res['state'] - - -def check_quality(uri, user, pwd, dbname, modules, quality_logs): + state = res['state'] + + +def check_quality(uri, user, pwd, dbname, modules, quality_logs): uid = login(uri, dbname, user, pwd) quality_logs += 'quality-logs' if uid: conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object') - final = {} - for module in modules: + final = {} + for module in modules: qualityresult = {} - test_detail = {} + test_detail = {} quality_result = execute(conn,'execute', dbname, uid, pwd,'module.quality.check','check_quality',module) detail_html = '' html = '''''' - html +="

Module : %s

"%(quality_result['name']) - html += "

Final score : %s

"%(quality_result['final_score']) + html +="

Module: %s

"%(quality_result['name']) + html += "

Final score: %s

"%(quality_result['final_score']) html += "
" html += "
    " - for x,y,detail in quality_result['check_detail_ids']: + for x,y,detail in quality_result['check_detail_ids']: test = detail.get('name') msg = detail.get('message','') score = round(float(detail.get('score',0)),2) html += "
  • %s
  • "%(test.replace(' ','-'),test) - if test == 'Unit Test': - if not detail.get('detail',''): - detail['detail'] = '''%s'''%(detail.get('summary','')) - detail_html +="

    %s (Score : %s)

    %s
    "%(test.replace(' ','-'),test,score,detail.get('detail','')) + detail_html +='''

    %s (Score : %s)

    %s
    %s
    '''%(test.replace(' ', '-'), test, score, msg, detail.get('detail', '')) test_detail[test] = (score,msg,detail.get('detail','')) html += "
" html += "%s"%(detail_html) @@ -155,9 +152,9 @@ def check_quality(uri, user, pwd, dbname, modules, quality_logs): #print "LOG PATH%s"%(os.path.realpath('quality_log.pck')) return True else: - print 'Login Failed...' + print 'Login Failed...' clean() - sys.exit(1) + sys.exit(1) @@ -176,25 +173,25 @@ def create_db(uri, dbname, user='admin', pwd='admin', lang='en_US'): login_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/common') db_list = execute(conn, 'list') if dbname not in db_list: - id = execute(conn,'create',admin_passwd, dbname, True, lang) + id = execute(conn,'create',admin_passwd, dbname, True, lang) wait(id,uri) - uid = login_conn.login(dbname, user, pwd) + uid = login_conn.login(dbname, user, pwd) wiz_id = execute(wiz_conn,'create', dbname, uid, user, 'base_setup.base_setup') state = 'init' datas = {'form':{}} - while state!='config': + while state!='config': res = execute(wiz_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {}) if state=='init': datas['form'].update( res['datas'] ) if res['type']=='form': - for field in res['fields'].keys(): + for field in res['fields'].keys(): datas['form'][field] = datas['form'].get(field,False) state = res['state'][-1][0] datas['form'].update({ - 'profile': -1 + 'profile': -1 }) elif res['type']=='state': state = res['state'] @@ -206,71 +203,71 @@ def drop_db(uri, dbname): conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db') db_list = execute(conn,'list') if dbname in db_list: - execute(conn, 'drop', admin_passwd, dbname) + execute(conn, 'drop', admin_passwd, dbname) return True - + def make_links(uri, uid, dbname, source, destination, module, user, pwd): if module in ('base','quality_integration_server'): - return True - if not os.path.islink(destination + '/' + module): - if not os.path.isdir(destination + '/' + module): + return True + if not os.path.islink(destination + '/' + module): + if not os.path.isdir(destination + '/' + module): for path in source: if os.path.isdir(path + '/' + module): os.symlink(path + '/' + module, destination + '/' + module) obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object') execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'update_list') module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','=',module)]) - if len(module_ids): + if len(module_ids): data = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'read', module_ids[0],['name','dependencies_id']) dep_datas = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module.dependency', 'read', data['dependencies_id'],['name']) - for dep_data in dep_datas: + for dep_data in dep_datas: make_links(uri, uid, dbname, source, destination, dep_data['name'], user, pwd) - return True - return False + return True + return False def install_module(uri, dbname, modules, addons='', extra_addons='', user='admin', pwd='admin'): uid = login(uri, dbname, user, pwd) if extra_addons: extra_addons = extra_addons.split(',') - if uid: + if uid: if addons and extra_addons: - for module in modules: - make_links(uri, uid, dbname, extra_addons, addons, module, user, pwd) + for module in modules: + make_links(uri, uid, dbname, extra_addons, addons, module, user, pwd) obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object') wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard') module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)]) - execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_install', module_ids) + execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_install', module_ids) wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple') state = 'init' datas = {} #while state!='menu': - while state!='end': - res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {}) + while state!='end': + res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {}) if state == 'init': state = 'start' elif state == 'start': - state = 'end' + state = 'end' return True def upgrade_module(uri, dbname, modules, user='admin', pwd='admin'): uid = login(uri, dbname, user, pwd) - if uid: + if uid: obj_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/object') - wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard') - module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)]) - execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_upgrade', module_ids) + wizard_conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/wizard') + module_ids = execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'search', [('name','in',modules)]) + execute(obj_conn, 'execute', dbname, uid, pwd, 'ir.module.module', 'button_upgrade', module_ids) wiz_id = execute(wizard_conn, 'create', dbname, uid, pwd, 'module.upgrade.simple') state = 'init' datas = {} #while state!='menu': - while state!='end': - res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {}) + while state!='end': + res = execute(wizard_conn, 'execute', dbname, uid, pwd, wiz_id, datas, state, {}) if state == 'init': state = 'start' elif state == 'start': - state = 'end' - + state = 'end' + return True @@ -283,21 +280,21 @@ Basic Commands: start-server Start Server create-db Create new database drop-db Drop database - install-module Install module + install-module Install module upgrade-module Upgrade module install-translation Install translation file check-quality Calculate quality and dump quality result into quality_log.pck using pickle """ -parser = optparse.OptionParser(usage) +parser = optparse.OptionParser(usage) parser.add_option("--modules", dest="modules", help="specify modules to install or check quality") parser.add_option("--addons-path", dest="addons_path", help="specify the addons path") parser.add_option("--quality-logs", dest="quality_logs", help="specify the path of quality logs files which has to stores") parser.add_option("--root-path", dest="root_path", help="specify the root path") parser.add_option("-p", "--port", dest="port", help="specify the TCP port", type="int") -parser.add_option("-d", "--database", dest="db_name", help="specify the database name") -parser.add_option("--login", dest="login", help="specify the User Login") -parser.add_option("--password", dest="pwd", help="specify the User Password") +parser.add_option("-d", "--database", dest="db_name", help="specify the database name") +parser.add_option("--login", dest="login", help="specify the User Login") +parser.add_option("--password", dest="pwd", help="specify the User Password") parser.add_option("--translate-in", dest="translate_in", help="specify .po files to import translation terms") parser.add_option("--extra-addons", dest="extra_addons", @@ -308,7 +305,7 @@ if len(args) != 1: parser.error("incorrect number of arguments") command = args[0] if command not in ('start-server','create-db','drop-db','install-module','upgrade-module','check-quality','install-translation'): - parser.error("incorrect command") + parser.error("incorrect command") def die(cond, msg): if cond: @@ -326,7 +323,7 @@ options = { 'quality-logs' : opt.quality_logs or '', 'root-path' : opt.root_path or '', 'translate-in': [], - 'port' : opt.port or 8069, + 'port' : opt.port or 8069, 'database': opt.db_name or 'terp', 'modules' : opt.modules or [], 'login' : opt.login or 'admin', @@ -337,33 +334,33 @@ options = { options['modules'] = opt.modules and map(lambda m: m.strip(), opt.modules.split(',')) or [] # Hint:i18n-import=purchase:ar_AR.po+sale:fr_FR.po,nl_BE.po if opt.translate_in: - translate = opt.translate_in - for module_name,po_files in map(lambda x:tuple(x.split(':')),translate.split('+')): - for po_file in po_files.split(','): + translate = opt.translate_in + for module_name,po_files in map(lambda x:tuple(x.split(':')),translate.split('+')): + for po_file in po_files.split(','): po_link = '%s/%s/i18n/%s'%(options['addons-path'], module_name, po_file) - options['translate-in'].append(po_link) - + options['translate-in'].append(po_link) + uri = 'http://localhost:' + str(options['port']) server_thread = threading.Thread(target=start_server, args=(options['root-path'], options['port'], options['addons-path'])) -try: - server_thread.start() - if command == 'create-db': +try: + server_thread.start() + if command == 'create-db': create_db(uri, options['database'], options['login'], options['pwd']) - if command == 'drop-db': + if command == 'drop-db': drop_db(uri, options['database']) - if command == 'install-module': + if command == 'install-module': install_module(uri, options['database'], options['modules'],options['addons-path'],options['extra-addons'],options['login'], options['pwd']) - if command == 'upgrade-module': + if command == 'upgrade-module': upgrade_module(uri, options['database'], options['modules'], options['login'], options['pwd']) if command == 'check-quality': check_quality(uri, options['login'], options['pwd'], options['database'], options['modules'], options['quality-logs']) - if command == 'install-translation': + if command == 'install-translation': import_translate(uri, options['login'], options['pwd'], options['database'], options['translate-in']) clean() sys.exit(0) - + except xmlrpclib.Fault, e: print e.faultString clean() @@ -372,7 +369,7 @@ except Exception, e: print e clean() sys.exit(1) - + From 22bb413066964ad4a1aafe66da52e8e3a3451e15 Mon Sep 17 00:00:00 2001 From: "uco(Open ERP)" <> Date: Thu, 1 Oct 2009 16:36:41 +0530 Subject: [PATCH 06/19] [FIX] Allowing sql keywords as fields(don't use them in order by clause) lp bug: https://launchpad.net/bugs/430728 fixed bzr revid: jvo@tinyerp.com-20091001110641-jks9s9pntnmewvgm --- bin/osv/orm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index 812c5de3791..f46788bcf88 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1773,7 +1773,7 @@ class orm(orm_template): f_pg_notnull = f_pg_def['attnotnull'] if isinstance(f, fields.function) and not f.store: logger.notifyChannel('orm', netsvc.LOG_INFO, 'column %s (%s) in table %s removed: converted to a function !\n' % (k, f.string, self._table)) - cr.execute('ALTER TABLE %s DROP COLUMN %s'% (self._table, k)) + cr.execute('ALTER TABLE "%s" DROP COLUMN "%s"'% (self._table, k)) cr.commit() f_obj_type = None else: @@ -1821,7 +1821,7 @@ class orm(orm_template): default = self._defaults[k](self, cr, 1, {}) if (default is not None): ss = self._columns[k]._symbol_set - query = 'UPDATE "%s" SET "%s"=%s WHERE %s is NULL' % (self._table, k, ss[0], k) + query = 'UPDATE "%s" SET "%s"=%s WHERE "%s" is NULL' % (self._table, k, ss[0], k) cr.execute(query, (ss[1](default),)) # add the NOT NULL constraint cr.commit() From 1b607549a7281cba356e71492737284ff9da15bb Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Fri, 2 Oct 2009 18:00:07 +0200 Subject: [PATCH 07/19] [IMP] cron: check the arguments to avoid security issues [IMP] cron: failed jobs are logged [IMP] cron: clean code lp bug: https://launchpad.net/bugs/433395 fixed bzr revid: christophe@tinyerp.com-20091002160007-mw7a55oy0l6bp5xd --- bin/addons/base/ir/ir_cron.py | 69 +++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/bin/addons/base/ir/ir_cron.py b/bin/addons/base/ir/ir_cron.py index 166a5781d44..0ef23a6c423 100644 --- a/bin/addons/base/ir/ir_cron.py +++ b/bin/addons/base/ir/ir_cron.py @@ -27,6 +27,9 @@ import tools import pooler from osv import fields,osv +def str2tuple(s): + return eval('tuple(%s)' % s) + _intervalTypes = { 'work_days': lambda interval: DateTime.RelativeDateTime(days=interval), 'days': lambda interval: DateTime.RelativeDateTime(days=interval), @@ -65,25 +68,39 @@ class ir_cron(osv.osv, netsvc.Agent): 'doall' : lambda *a: 1 } + def _check_args(self, cr, uid, ids, context=None): + try: + for this in self.browse(cr, uid, ids, context): + str2tuple(this.args) + except: + return False + return True + + _constraints= [ + (_check_args, 'Invalid arguments', ['args']), + ] + def _callback(self, cr, uid, model, func, args): - args = (args or []) and eval(args) - m=self.pool.get(model) + args = str2tuple(args) + m = self.pool.get(model) if m and hasattr(m, func): f = getattr(m, func) - f(cr, uid, *args) + try: + f(cr, uid, *args) + except Exception, e: + self._logger.notifyChannel('timers', netsvc.LOG_ERROR, "Job call of self.pool.get('%s').%s(cr, uid, *%r) failed" % (model, func, args)) + self._logger.notifyChannel('timers', netsvc.LOG_ERROR, tools.exception_to_unicode(e)) + def _poolJobs(self, db_name, check=False): try: db, pool = pooler.get_db_and_pool(db_name) except: return False - if pool._init: - # retry in a few minutes - next_call = 600 - else: - now = DateTime.now() - try: - cr = db.cursor() + try: + cr = db.cursor() + if not pool._init: + now = DateTime.now() cr.execute('select * from ir_cron where numbercall<>0 and active and nextcall<=now() order by priority') for job in cr.dictfetchall(): nextcall = DateTime.strptime(job['nextcall'], '%Y-%m-%d %H:%M:%S') @@ -103,24 +120,22 @@ class ir_cron(osv.osv, netsvc.Agent): addsql = ', active=False' cr.execute("update ir_cron set nextcall=%s, numbercall=%s"+addsql+" where id=%s", (nextcall.strftime('%Y-%m-%d %H:%M:%S'), numbercall, job['id'])) cr.commit() - finally: - cr.commit() - cr.close() - # - # Can be improved to do at the min(min(nextcalls), time()+next_call) - # But is this an improvement ? - # - cr = db.cursor() - cr.execute('select min(nextcall) as min_next_call from ir_cron where numbercall<>0 and active and nextcall>=now()') - next_call = cr.dictfetchone()['min_next_call'] - cr.close() - if next_call: - next_call = time.mktime(time.strptime(next_call, '%Y-%m-%d %H:%M:%S')) - else: - next_call = int(time.time()) + 3600 # if do not find active cron job from database, it will run again after 1 day - if not check: - self.setAlarm(self._poolJobs, next_call, db_name, db_name) + + cr.execute('select min(nextcall) as min_next_call from ir_cron where numbercall<>0 and active and nextcall>=now()') + next_call = cr.dictfetchone()['min_next_call'] + if next_call: + next_call = time.mktime(time.strptime(next_call, '%Y-%m-%d %H:%M:%S')) + else: + next_call = int(time.time()) + 3600 # if do not find active cron job from database, it will run again after 1 day + + if not check: + self.setAlarm(self._poolJobs, next_call, db_name, db_name) + + finally: + cr.commit() + cr.close() + def create(self, cr, uid, vals, context=None): res = super(ir_cron, self).create(cr, uid, vals, context=context) From f822efa07454eb09f52216d1408f3b55739de85b Mon Sep 17 00:00:00 2001 From: "Jay (Open ERP)" Date: Sat, 3 Oct 2009 15:18:58 +0530 Subject: [PATCH 08/19] [FIX] Name_search() is having now record limit to be 80 instead of None lp bug: https://launchpad.net/bugs/430133 fixed bzr revid: jvo@tinyerp.com-20091003094858-njohqhj91rc6is6n --- bin/osv/orm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index f46788bcf88..e4f36a041bd 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1332,7 +1332,7 @@ class orm_template(object): def name_get(self, cr, user, ids, context=None): raise _('The name_get method is not implemented on this object !') - def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=None): + def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=80): raise _('The name_search method is not implemented on this object !') def copy(self, cr, uid, id, default=None, context=None): @@ -2880,7 +2880,7 @@ class orm(orm_template): return [(r['id'], tools.ustr(r[self._rec_name])) for r in self.read(cr, user, ids, [self._rec_name], context, load='_classic_write')] - def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=None): + def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=80): if not args: args = [] if not context: From f590b743189f5d20068905a3dfd5581f11ac2006 Mon Sep 17 00:00:00 2001 From: "Jay (Open ERP)" Date: Mon, 5 Oct 2009 17:40:29 +0530 Subject: [PATCH 09/19] [FIX] Import : Context of the action/screen passed,taken into consideration while importing bzr revid: jvo@tinyerp.com-20091005121029-6sy1k3uvkpi2i8of --- bin/addons/base/ir/ir_model.py | 25 +++++++++++++------------ bin/osv/orm.py | 3 ++- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/bin/addons/base/ir/ir_model.py b/bin/addons/base/ir/ir_model.py index 2fe3375d0a0..d69688bf6fc 100644 --- a/bin/addons/base/ir/ir_model.py +++ b/bin/addons/base/ir/ir_model.py @@ -445,10 +445,11 @@ class ir_model_data(osv.osv): id = False return id - def _update(self,cr, uid, model, module, values, xml_id=False, store=True, noupdate=False, mode='init', res_id=False): + def _update(self,cr, uid, model, module, values, xml_id=False, store=True, noupdate=False, mode='init', res_id=False, context=None): warning = True model_obj = self.pool.get(model) - context = {} + if not context: + context = {} if xml_id and ('.' in xml_id): assert len(xml_id.split('.'))==2, _('"%s" contains too many dots. XML ids should not contain dots ! These are used to refer to other modules data, as in module.reference_id') % (xml_id) warning = False @@ -471,12 +472,12 @@ class ir_model_data(osv.osv): res_id,action_id = res_id2,action_id2 if action_id and res_id: - model_obj.write(cr, uid, [res_id], values) + model_obj.write(cr, uid, [res_id], values, context=context) self.write(cr, uid, [action_id], { 'date_update': time.strftime('%Y-%m-%d %H:%M:%S'), - }) + },context=context) elif res_id: - model_obj.write(cr, uid, [res_id], values) + model_obj.write(cr, uid, [res_id], values, context=context) if xml_id: self.create(cr, uid, { 'name': xml_id, @@ -484,21 +485,21 @@ class ir_model_data(osv.osv): 'module':module, 'res_id':res_id, 'noupdate': noupdate, - }) + },context=context) if model_obj._inherits: for table in model_obj._inherits: inherit_id = model_obj.browse(cr, uid, - res_id)[model_obj._inherits[table]] + res_id,context=context)[model_obj._inherits[table]] self.create(cr, uid, { 'name': xml_id + '_' + table.replace('.', '_'), 'model': table, 'module': module, 'res_id': inherit_id, 'noupdate': noupdate, - }) + },context=context) else: if mode=='init' or (mode=='update' and xml_id): - res_id = model_obj.create(cr, uid, values) + res_id = model_obj.create(cr, uid, values, context=context) if xml_id: self.create(cr, uid, { 'name': xml_id, @@ -506,18 +507,18 @@ class ir_model_data(osv.osv): 'module': module, 'res_id': res_id, 'noupdate': noupdate - }) + },context=context) if model_obj._inherits: for table in model_obj._inherits: inherit_id = model_obj.browse(cr, uid, - res_id)[model_obj._inherits[table]] + res_id,context=context)[model_obj._inherits[table]] self.create(cr, uid, { 'name': xml_id + '_' + table.replace('.', '_'), 'model': table, 'module': module, 'res_id': inherit_id, 'noupdate': noupdate, - }) + },context=context) if xml_id: if res_id: self.loads[(module, xml_id)] = (model, res_id) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index e4f36a041bd..f9a62a02f18 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -577,6 +577,7 @@ class orm_template(object): raise Exception(_('Please check that all your lines have %d columns.') % (len(fields),)) if not line[i]: continue + field = fields[i] if (len(field)==len(prefix)+1) and field[len(prefix)].endswith(':db_id'): # Database ID @@ -811,7 +812,7 @@ class orm_template(object): try: id = ir_model_data_obj._update(cr, uid, self._name, current_module, res, xml_id=data_id, mode=mode, - noupdate=noupdate, res_id=res_id) + noupdate=noupdate, res_id=res_id, context=context) except Exception, e: import psycopg2 if isinstance(e,psycopg2.IntegrityError): From 3c28a101b9c353973a7516c710134405ba55baca Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Wed, 7 Oct 2009 14:38:07 +0200 Subject: [PATCH 10/19] [FIX] Use an alternative for the locale.RADIXCHAR if this one doesn't exist lp bug: https://launchpad.net/bugs/400614 fixed bzr revid: stephane@openerp.com-20091007123807-qsn2uk6jarosd7nz --- bin/report/render/rml2pdf/utils.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bin/report/render/rml2pdf/utils.py b/bin/report/render/rml2pdf/utils.py index 59724d7d1b4..8e747f5b02a 100644 --- a/bin/report/render/rml2pdf/utils.py +++ b/bin/report/render/rml2pdf/utils.py @@ -42,6 +42,7 @@ import reportlab from lxml import etree import copy import tools +import locale _regex = re.compile('\[\[(.+?)\]\]') @@ -133,6 +134,15 @@ units = [ def unit_get(size): global units if size: + if size.find('.') == -1: + decimal_point = '.' + try: + decimal_point = locale.RADIXCHAR + except: + decimal_point = locale.localeconv()['decimal_point'] + + size = size.replace(decimal_point, '.') + for unit in units: res = unit[0].search(size, 0) if res: From bebd7fd223a96b390558211ce92b753ab8dff955 Mon Sep 17 00:00:00 2001 From: "Jay (Open ERP)" Date: Thu, 8 Oct 2009 11:03:44 +0530 Subject: [PATCH 11/19] [FIX] Improved Previous bad commit for pagelayout error bzr revid: jvo@tinyerp.com-20091008053344-rkh1m6oaxw2kjlwd --- bin/report/render/rml2pdf/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/report/render/rml2pdf/utils.py b/bin/report/render/rml2pdf/utils.py index 8e747f5b02a..07bbbbcd05e 100644 --- a/bin/report/render/rml2pdf/utils.py +++ b/bin/report/render/rml2pdf/utils.py @@ -137,7 +137,7 @@ def unit_get(size): if size.find('.') == -1: decimal_point = '.' try: - decimal_point = locale.RADIXCHAR + decimal_point = locale.nl_langinfo(locale.RADIXCHAR) except: decimal_point = locale.localeconv()['decimal_point'] From 90d81da72bf57b7ed2acfb750ddc32cf27c76afb Mon Sep 17 00:00:00 2001 From: "Jay (Open ERP)" Date: Thu, 8 Oct 2009 13:23:35 +0530 Subject: [PATCH 12/19] [FIX] Domain was getting failed when trying to work upon M2M,O2M field of object lp bug: https://launchpad.net/bugs/420507 fixed bzr revid: jvo@tinyerp.com-20091008075335-obo9xs9usni3ey4n --- bin/osv/expression.py | 93 +++++++++++++++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 22 deletions(-) diff --git a/bin/osv/expression.py b/bin/osv/expression.py index 3c330aaaa1a..23ac071e6dd 100644 --- a/bin/osv/expression.py +++ b/bin/osv/expression.py @@ -44,14 +44,25 @@ class expression(object): and (((not internal) and element[1] in OPS) \ or (internal and element[1] in INTERNAL_OPS)) - def __execute_recursive_in(self, cr, s, f, w, ids): + def __execute_recursive_in(self, cr, s, f, w, ids, op, type): res = [] - for i in range(0, len(ids), cr.IN_MAX): - subids = ids[i:i+cr.IN_MAX] - cr.execute('SELECT "%s"' \ - ' FROM "%s"' \ - ' WHERE "%s" in (%s)' % (s, f, w, ','.join(['%s']*len(subids))), - subids) + if ids: + if op in ['<','>','>=','<=']: + cr.execute('SELECT "%s"' \ + ' FROM "%s"' \ + ' WHERE "%s" %s %s' % (s, f, w, op, ids[0])) + res.extend([r[0] for r in cr.fetchall()]) + else: + for i in range(0, len(ids), cr.IN_MAX): + subids = ids[i:i+cr.IN_MAX] + cr.execute('SELECT "%s"' \ + ' FROM "%s"' \ + ' WHERE "%s" in (%s)' % (s, f, w, ','.join(['%s']*len(subids))), + subids) + res.extend([r[0] for r in cr.fetchall()]) + else: + cr.execute('SELECT distinct("%s")' \ + ' FROM "%s" where "%s" is not null' % (s, f, s)), res.extend([r[0] for r in cr.fetchall()]) return res @@ -101,7 +112,6 @@ class expression(object): if self._is_operator(e) or e == self.__DUMMY_LEAF: continue left, operator, right = e - working_table = table main_table = table fargs = left.split('.', 1) @@ -154,14 +164,32 @@ class expression(object): elif field._type == 'one2many': - if isinstance(right, basestring): - ids2 = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator, limit=None)] - else: - ids2 = list(right) - if not ids2: - self.__exp[i] = ('id', '=', '0') - else: - self.__exp[i] = ('id', 'in', self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', ids2)) + call_null = True + + if right: + if isinstance(right, basestring): + ids2 = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator, limit=None)] + operator = 'in' + else: + if not isinstance(right,list): + ids2 = [right] + else: + ids2 = right + if not ids2: + call_null = True + operator = 'in' # operator changed because ids are directly related to main object + else: + call_null = False + o2m_op = 'in' + if operator in ['not like','not ilike','not in','<>','!=']: + o2m_op = 'not in' + self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', ids2, operator, field._type)) + + if call_null: + o2m_op = 'not in' + if operator in ['not like','not ilike','not in','<>','!=']: + o2m_op = 'in' + self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', [], operator, field._type) or [0]) elif field._type == 'many2many': #FIXME @@ -174,17 +202,38 @@ class expression(object): def _rec_convert(ids): if field_obj == table: return ids - return self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, ids) + return self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, ids, operator, field._type) dom = _rec_get(ids2, field_obj) ids2 = field_obj.search(cr, uid, dom, context=context) self.__exp[i] = ('id', 'in', _rec_convert(ids2)) else: - if isinstance(right, basestring): - res_ids = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator)] - else: - res_ids = list(right) - self.__exp[i] = ('id', 'in', self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, res_ids) or [0]) + call_null_m2m = True + if right: + if isinstance(right, basestring): + res_ids = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator)] + operator = 'in' + else: + if not isinstance(right, list): + res_ids = [right] + else: + res_ids = right + if not res_ids: + call_null_m2m = True + operator = 'in' # operator changed because ids are directly related to main object + else: + call_null_m2m = False + m2m_op = 'in' + if operator in ['not like','not ilike','not in','<>','!=']: + m2m_op = 'not in' + + self.__exp[i] = ('id', m2m_op, self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, res_ids, operator, field._type) or [0]) + if call_null_m2m: + m2m_op = 'not in' + if operator in ['not like','not ilike','not in','<>','!=']: + m2m_op = 'in' + self.__exp[i] = ('id', m2m_op, self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, [], operator, field._type) or [0]) + elif field._type == 'many2one': if operator == 'child_of': if isinstance(right, basestring): From fbee346b9261dc633c438e1335656f5f7cfd43f6 Mon Sep 17 00:00:00 2001 From: "YSA(OpenERP)" <> Date: Thu, 8 Oct 2009 15:14:57 +0530 Subject: [PATCH 13/19] [FIX] Import made successful when field is O2M and it has relation under that. lp bug: https://launchpad.net/bugs/430805 fixed bzr revid: jvo@tinyerp.com-20091008094457-3ta5gkrhqspiiqyr --- bin/osv/orm.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index f9a62a02f18..8c87b1bccf1 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -579,6 +579,9 @@ class orm_template(object): continue field = fields[i] + if prefix and not prefix[0] in field: + continue + if (len(field)==len(prefix)+1) and field[len(prefix)].endswith(':db_id'): # Database ID res = False @@ -635,7 +638,7 @@ class orm_template(object): id = ir_model_data_obj._get_id(cr, uid, module, xml_id) res_id = ir_model_data_obj.read(cr, uid, [id], ['res_id'])[0]['res_id'] - row[field[0][:-3]] = res_id or False + row[field[-1][:-3]] = res_id or False continue if (len(field) == len(prefix)+1) and \ len(field[len(prefix)].split(':lang=')) == 2: @@ -671,7 +674,7 @@ class orm_template(object): try: _check_db_id(self, model_name, line[i]) data_res_id = is_db_id = int(line[i]) - except Exception,e: + except Exception,e: warning += [tools.exception_to_unicode(e)] logger.notifyChannel("import", netsvc.LOG_ERROR, tools.exception_to_unicode(e)) From 9a0d6aa9471287f7e43b567eb2de560587fc0e4d Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 8 Oct 2009 15:30:57 +0200 Subject: [PATCH 14/19] [MERGE] Backport: http://bazaar.launchpad.net/~openobject-training/+junk/server/revision/1821 [FIX] Workflow button desactivation regarding user roles bzr revid: stephane@openerp.com-20091008133057-3htx9jwebv9pprgd --- bin/osv/orm.py | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index 8c87b1bccf1..7c2c6718915 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1062,19 +1062,37 @@ class orm_template(object): buttons = (n for n in node.getElementsByTagName('button') if n.getAttribute('type') != 'object') for button in buttons: - ok = True + can_click = True if user != 1: # admin user has all roles user_roles = usersobj.read(cr, user, [user], ['roles_id'])[0]['roles_id'] - cr.execute("select role_id from wkf_transition where signal=%s", (button.getAttribute('name'),)) + # TODO handle the case of more than one workflow for a model + cr.execute("""SELECT DISTINCT t.role_id + FROM wkf + INNER JOIN wkf_activity a ON a.wkf_id = wkf.id + INNER JOIN wkf_transition t ON (t.act_to = a.id) + WHERE wkf.osv = %s + AND t.signal = %s + """, (self._name, button.getAttribute('name'),)) roles = cr.fetchall() - for role in roles: - if role[0]: - ok = ok and rolesobj.check(cr, user, user_roles, role[0]) + + # draft -> valid = signal_next (role X) + # draft -> cancel = signal_cancel (no role) + # + # valid -> running = signal_next (role Y) + # valid -> cancel = signal_cancel (role Z) + # + # running -> done = signal_next (role Z) + # running -> cancel = signal_cancel (role Z) + - if not ok: - button.setAttribute('readonly', '1') - else: - button.setAttribute('readonly', '0') + # As we don't know the object state, in this scenario, + # the button "signal_cancel" will be always shown as there is no restriction to cancel in draft + # the button "signal_next" will be show if the user has any of the roles (X Y or Z) + # The verification will be made later in workflow process... + if roles: + can_click = any((not role) or rolesobj.check(cr, user, user_roles, role) for (role,) in roles) + + button.setAttribute('readonly', str(int(not can_click))) arch = node.toxml(encoding="utf-8").replace('\t', '') fields = self.fields_get(cr, user, fields_def.keys(), context) From 1052e1213dd405fb9050ac6e9e3b5e25d68b4e61 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 8 Oct 2009 15:32:35 +0200 Subject: [PATCH 15/19] [MERGE] Backport: http://bazaar.launchpad.net/~openobject-training/+junk/server/revision/1822 [IMP] Allow to specify the view via the context bzr revid: stephane@openerp.com-20091008133235-3ogpljqem67ae032 --- bin/osv/orm.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index 7c2c6718915..73015dffbde 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1230,6 +1230,15 @@ class orm_template(object): model = True sql_res = False while ok: + view_ref = context.get(view_type + '_view_ref', False) + if view_ref: + if '.' in view_ref: + module, view_ref = view_ref.split('.', 1) + cr.execute("SELECT res_id FROM ir_model_data WHERE model='ir.ui.view' AND module=%s AND name=%s", (module, view_ref)) + view_ref_res = cr.fetchone() + if view_ref_res: + view_id = view_ref_res[0] + if view_id: where = (model and (" and model='%s'" % (self._name,))) or '' cr.execute('SELECT arch,name,field_parent,id,type,inherit_id FROM ir_ui_view WHERE id=%s'+where, (view_id,)) From dcf275be04ff1c1733cca09613fda61e6d241e32 Mon Sep 17 00:00:00 2001 From: "nch@tinyerp.com" <> Date: Fri, 9 Oct 2009 16:03:54 +0530 Subject: [PATCH 16/19] [FIX]: problem Report Engine bzr revid: nch@tinyerp.com-20091009103354-u2z9v03jc864yekh --- bin/report/render/rml2pdf/trml2pdf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/report/render/rml2pdf/trml2pdf.py b/bin/report/render/rml2pdf/trml2pdf.py index f4b70a2da27..b3585254eb3 100644 --- a/bin/report/render/rml2pdf/trml2pdf.py +++ b/bin/report/render/rml2pdf/trml2pdf.py @@ -455,10 +455,10 @@ class _rml_flowable(object): if key in ('rml_except', 'rml_loop', 'rml_tag'): del txt_n.attrib[key] if True or not self._textual(n).isspace(): - txt_n.text = utils.xml2str(self._textual(n)) - txt_n.tail = '' + if not n.tag == 'bullet': + txt_n.text = utils.xml2str(self._textual(n)) + txt_n.tail = n.tail and utils._process_text(self, n.tail.replace('\n','')) or '' rc1 += etree.tostring(txt_n) - #rc1 += utils._process_text(self, node.tail or '') return rc1 def _table(self, node): From efc0d3b001b9252b367d1b1f1dd7b088ff6395d7 Mon Sep 17 00:00:00 2001 From: "nch@tinyerp.com" <> Date: Fri, 9 Oct 2009 16:15:47 +0530 Subject: [PATCH 17/19] [REF]:notified channel when there is an exception in eval() bzr revid: nch@tinyerp.com-20091009104547-t88ktqax7p5q57bz --- bin/report/render/rml2pdf/utils.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/bin/report/render/rml2pdf/utils.py b/bin/report/render/rml2pdf/utils.py index 07bbbbcd05e..abc421a0f2f 100644 --- a/bin/report/render/rml2pdf/utils.py +++ b/bin/report/render/rml2pdf/utils.py @@ -43,6 +43,8 @@ from lxml import etree import copy import tools import locale +import netsvc +import traceback, sys _regex = re.compile('\[\[(.+?)\]\]') @@ -108,9 +110,13 @@ def _process_text(self, txt): result += self.localcontext.get('translate', lambda x:x)(sps.pop(0)) if sps: try: - txt = eval(sps.pop(0),self.localcontext) - except: - pass + expr = sps.pop(0) + txt = eval(expr,self.localcontext) + except Exception,e: + tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) + netsvc.Logger().notifyChannel('report', netsvc.LOG_ERROR, + 'report :\n%s\n%s\nexpr: %s' % (tb_s, str(e), + expr.encode('utf-8'))) if type(txt)==type('') or type(txt)==type(u''): txt2 = str2xml(txt) result += tools.ustr(txt2) @@ -173,7 +179,7 @@ def attr_get(node, attrs, dict={}): res[key] = int(node.get(key)) elif dict[key]=='unit': res[key] = unit_get(node.get(key)) - elif dict[key] == 'float' : + elif dict[key] == 'float' : res[key] = float(node.get(key)) return res From 3d08c9c6f049ffce39bd91382cb096e846e90b18 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Fri, 9 Oct 2009 13:48:16 +0200 Subject: [PATCH 18/19] [FIX] Specify the name of the argument for the context, to avoir a critical bug bzr revid: stephane@openerp.com-20091009114816-5n518p74cm1k2pj1 --- bin/addons/base/module/report/ir_module_reference_print.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/addons/base/module/report/ir_module_reference_print.py b/bin/addons/base/module/report/ir_module_reference_print.py index 92029014bac..69de9ab9a09 100644 --- a/bin/addons/base/module/report/ir_module_reference_print.py +++ b/bin/addons/base/module/report/ir_module_reference_print.py @@ -25,7 +25,7 @@ from report import report_sxw class ir_module_reference_print(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): - super(ir_module_reference_print, self).__init__(cr, uid, name, context) + super(ir_module_reference_print, self).__init__(cr, uid, name, context=context) self.localcontext.update({ 'time': time, 'findobj': self._object_find, From 122230e73c8e863a3b405741d2495198abb24d22 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Fri, 16 Oct 2009 17:16:43 +0200 Subject: [PATCH 19/19] [FIX] allow to call write without ids on osv_memory objects bzr revid: chs@tinyerp.com-20091016151643-uh7a9m0lfeqajfqf --- bin/osv/orm.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index 73015dffbde..652bcafab0a 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1472,6 +1472,8 @@ class orm_memory(orm_template): return result def write(self, cr, user, ids, vals, context=None): + if not ids: + return True vals2 = {} upd_todo = [] for field in vals: