From 9dec41a7b15e841c7332edae17d34cd3dfea5bb8 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Tue, 16 Dec 2008 10:45:49 +0100 Subject: [PATCH 01/10] [FIX] Add the dot in the object name lp bug: https://launchpad.net/bugs/300646 fixed bzr revid: stephane@tinyerp.com-20081216094549-e5493sdtjwm4k99y --- bin/addons/base/ir/ir_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/addons/base/ir/ir_model.py b/bin/addons/base/ir/ir_model.py index 40ce882e280..66cbd98e52d 100644 --- a/bin/addons/base/ir/ir_model.py +++ b/bin/addons/base/ir/ir_model.py @@ -55,7 +55,7 @@ class ir_model(osv.osv): if model.state=='manual': if not model.model.startswith('x_'): return False - if not re.match('^[a-z_A-Z0-9]+$',model.model): + if not re.match('^[a-z_A-Z0-9.]+$',model.model): return False return True From ffc916aaa39d8cca186c10c5d506fc5a472f0e62 Mon Sep 17 00:00:00 2001 From: Olivier Laurent Date: Tue, 16 Dec 2008 11:14:22 +0100 Subject: [PATCH 02/10] wrong identifier: uid -> user bzr revid: olt@tinyerp.com-20081216101422-bk80ena85vj4y4kw --- bin/addons/base/ir/ir_model.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/bin/addons/base/ir/ir_model.py b/bin/addons/base/ir/ir_model.py index 40ce882e280..4d0cc16f21e 100644 --- a/bin/addons/base/ir/ir_model.py +++ b/bin/addons/base/ir/ir_model.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution +# OpenERP, Open Source Management Solution # Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved # $Id$ # @@ -233,7 +233,7 @@ class ir_model_fields(osv.osv): # MAY BE ADD A ALTER TABLE DROP ? # return super(ir_model_fields, self).unlink(cr, user, ids, context) - + def write(self, cr, uid, ids, vals, context=None): res = False if 'relation_id' in vals: @@ -242,29 +242,29 @@ class ir_model_fields(osv.osv): if 'relation_field_id' in vals: field_data = self.pool.get('ir.model.fields').browse(cr, uid, vals['relation_field_id']) vals['relation'] = field_data.name - + res = super(ir_model_fields, self).write(cr, uid, ids, vals, context) return res - + def create(self, cr, user, vals, context=None): if 'relation_id' in vals: - model_data = self.pool.get('ir.model').browse(cr,user,vals['relation_id']) + model_data = self.pool.get('ir.model').browse(cr, user, vals['relation_id']) vals['relation']=model_data.model if 'relation_field_id' in vals: - field_data = self.pool.get('ir.model.fields').browse(cr, uid, vals['relation_field_id']) + field_data = self.pool.get('ir.model.fields').browse(cr, user, vals['relation_field_id']) vals['relation_field'] = field_data.name if 'model_id' in vals: - model_data=self.pool.get('ir.model').browse(cr,user,vals['model_id']) - vals['model']=model_data.model + model_data = self.pool.get('ir.model').browse(cr, user, vals['model_id']) + vals['model'] = model_data.model if context and context.get('manual',False): - vals['state']='manual' + vals['state'] = 'manual' res = super(ir_model_fields,self).create(cr, user, vals, context) - if vals.get('state','base')=='manual': + if vals.get('state','base') == 'manual': if not vals['name'].startswith('x_'): raise except_orm(_('Error'), _("Custom fields must have a name that starts with 'x_' !")) if self.pool.get(vals['model']): self.pool.get(vals['model']).__init__(self.pool, cr) - self.pool.get(vals['model'])._auto_init(cr,{}) + self.pool.get(vals['model'])._auto_init(cr, {}) return res ir_model_fields() @@ -298,7 +298,7 @@ class ir_model_access(osv.osv): model_name = model.name else: model_name = model - + if isinstance(group_ids, (int, long)): group_ids = [group_ids] for group_id in group_ids: @@ -324,7 +324,7 @@ class ir_model_access(osv.osv): def check(self, cr, uid, model, mode='read', raise_exception=True): if uid==1: - # User root have all accesses + # User root have all accesses # TODO: exclude xml-rpc requests return True @@ -335,7 +335,7 @@ class ir_model_access(osv.osv): model_name = model.name else: model_name = model - + # We check if a specific rule exists cr.execute('SELECT MAX(CASE WHEN perm_' + mode + ' THEN 1 ELSE 0 END) ' ' FROM ir_model_access a ' @@ -394,7 +394,7 @@ class ir_model_access(osv.osv): res = super(ir_model_access, self).write(cr, uid, *args, **argv) self.check() # clear the cache of check function return res - + def create(self, cr, uid, *args, **argv): res = super(ir_model_access, self).create(cr, uid, *args, **argv) self.check() From d8e954618d08c55edcd297b02dbbcede305b4739 Mon Sep 17 00:00:00 2001 From: Mantavya Gajjar Date: Tue, 16 Dec 2008 15:48:09 +0530 Subject: [PATCH 03/10] activate the python code in the server action bzr revid: mga@tinyerp.com-20081216101809-ki2d8z3869qsm3dx --- bin/addons/base/ir/ir.xml | 6 ++++++ bin/addons/base/ir/ir_actions.py | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml index c649b12cf99..736f13b3507 100644 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -1142,6 +1142,12 @@ + + + + + + diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index c270557f6c5..3aa83ffbe26 100644 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -390,6 +390,7 @@ class actions_server(osv.osv): 'state': fields.selection([ ('client_action','Client Action'), ('dummy','Dummy'), + ('code','Python Code'), ('trigger','Trigger'), ('email','Email'), ('sms','SMS'), @@ -397,6 +398,7 @@ class actions_server(osv.osv): ('object_write','Write Object'), ('other','Multi Actions'), ], 'Action State', required=True, size=32), + 'code':fields.text('Python Code'), 'sequence': fields.integer('Sequence'), 'model_id': fields.many2one('ir.model', 'Object', required=True), 'action_id': fields.many2one('ir.actions.actions', 'Client Action'), @@ -418,6 +420,15 @@ class actions_server(osv.osv): 'state': lambda *a: 'dummy', 'type': lambda *a: 'ir.actions.server', 'sequence': lambda *a: 5, + 'code': lambda *a: """# You can use the following variables +# - object +# - object2 +# - time +# - cr +# - uid +# - ids +# If you plan to return an action, assign: action = {...} +""", } From 2b5169c00af8b7c2aa14218a4836722a4e2d4ab1 Mon Sep 17 00:00:00 2001 From: Olivier Laurent Date: Tue, 16 Dec 2008 11:18:25 +0100 Subject: [PATCH 04/10] 'e' is not an exception class bzr revid: olt@tinyerp.com-20081216101825-xxu1fg5jba7nrk30 --- bin/addons/base/res/partner/partner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/addons/base/res/partner/partner.py b/bin/addons/base/res/partner/partner.py index d17c696677f..56c01015287 100644 --- a/bin/addons/base/res/partner/partner.py +++ b/bin/addons/base/res/partner/partner.py @@ -255,7 +255,7 @@ class res_partner(osv.osv): ref = res and res[0]['ref'] or '0' try: nextref = int(ref)+1 - except e: + except: raise osv.except_osv(_('Warning'), _("Couldn't generate the next id because some partners have an alphabetic id !")) # update the current partner From 0c3a25a431295a324a454cc0fb33f22cc841b6ca Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Tue, 16 Dec 2008 11:23:23 +0100 Subject: [PATCH 05/10] [IMP] Log the error if it can load a module bzr revid: stephane@tinyerp.com-20081216102323-acn5tmtfpopwc5ch --- bin/addons/__init__.py | 172 ++++++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 81 deletions(-) diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py index e18213d466f..eec3f6b2370 100644 --- a/bin/addons/__init__.py +++ b/bin/addons/__init__.py @@ -24,6 +24,7 @@ import os, sys, imp from os.path import join as opj import itertools from sets import Set +import zipimport import osv import tools @@ -268,25 +269,32 @@ def init_module_objects(cr, module_name, obj_list): t[1](cr, *t[2]) cr.commit() -# -# Register module named m, if not already registered -# def register_class(m): + """ + Register module named m, if not already registered + """ global loaded if m in loaded: return logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: registering objects' % m) loaded.append(m) mod_path = get_module_path(m) - if not os.path.isfile(mod_path+'.zip'): - imp.load_module(m, *imp.find_module(m, [ad, _ad])) - else: - import zipimport - try: - zimp = zipimport.zipimporter(mod_path+'.zip') + try: + zip_mod_path = mod_path + '.zip' + if not os.path.isfile(zip_mod_path): + imp.load_module(m, *imp.find_module(m, [ad, _ad])) + else: + zimp = zipimport.zipimporter(zip_mod_path) zimp.load_module(m) - except zipimport.ZipImportError: - logger.notifyChannel('init', netsvc.LOG_ERROR, 'Couldn\'t find module %s' % m) + except zipimport.ZipImportError: + logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'Couldn\'t find zip module %s' % m) + raise + except ImportError: + logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'Couldn\'t find module %s' % m) + raise + except Exception: + logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'Couldn\'t find module %s' % (m)) + raise class MigrationManager(object): @@ -535,84 +543,86 @@ def load_module_graph(cr, graph, status=None, check_access_rules=True, **kwargs) def load_modules(db, force_demo=False, status=None, update_module=False): if not status: status={} + cr = db.cursor() - force = [] - if force_demo: - force.append('demo') - pool = pooler.get_pool(cr.dbname) - report = tools.assertion_report() - if update_module: - basegraph = create_graph(['base'], force) - load_module_graph(cr, basegraph, status, check_access_rules=False, report=report) + try: + force = [] + if force_demo: + force.append('demo') + pool = pooler.get_pool(cr.dbname) + report = tools.assertion_report() + if update_module: + basegraph = create_graph(['base'], force) + load_module_graph(cr, basegraph, status, check_access_rules=False, report=report) - modobj = pool.get('ir.module.module') - logger.notifyChannel('init', netsvc.LOG_INFO, 'updating modules list') - modobj.update_list(cr, 1) + modobj = pool.get('ir.module.module') + logger.notifyChannel('init', netsvc.LOG_INFO, 'updating modules list') + modobj.update_list(cr, 1) - mods = [k for k in tools.config['init'] if tools.config['init'][k]] - if mods: - ids = modobj.search(cr, 1, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)]) - if ids: - modobj.button_install(cr, 1, ids) + mods = [k for k in tools.config['init'] if tools.config['init'][k]] + if mods: + ids = modobj.search(cr, 1, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)]) + if ids: + modobj.button_install(cr, 1, ids) + + mods = [k for k in tools.config['update'] if tools.config['update'][k]] + if mods: + ids = modobj.search(cr, 1, ['&',('state', '=', 'installed'), ('name', 'in', mods)]) + if ids: + modobj.button_upgrade(cr, 1, ids) + + cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base')) + cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade')") + else: + cr.execute("select name from ir_module_module where state in ('installed', 'to upgrade')") + module_list = [name for (name,) in cr.fetchall()] + graph = create_graph(module_list, force) - mods = [k for k in tools.config['update'] if tools.config['update'][k]] - if mods: - ids = modobj.search(cr, 1, ['&',('state', '=', 'installed'), ('name', 'in', mods)]) - if ids: - modobj.button_upgrade(cr, 1, ids) - - cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base')) - cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade')") - else: - cr.execute("select name from ir_module_module where state in ('installed', 'to upgrade')") - module_list = [name for (name,) in cr.fetchall()] - graph = create_graph(module_list, force) - - # the 'base' module has already been updated - base = graph['base'] - base.state = 'installed' - for kind in ('init', 'demo', 'update'): - if hasattr(base, kind): - delattr(base, kind) + # the 'base' module has already been updated + base = graph['base'] + base.state = 'installed' + for kind in ('init', 'demo', 'update'): + if hasattr(base, kind): + delattr(base, kind) - load_module_graph(cr, graph, status, report=report) - if report.get_report(): - logger.notifyChannel('init', netsvc.LOG_INFO, report) + load_module_graph(cr, graph, status, report=report) + if report.get_report(): + logger.notifyChannel('init', netsvc.LOG_INFO, report) - for kind in ('init', 'demo', 'update'): - tools.config[kind]={} + for kind in ('init', 'demo', 'update'): + tools.config[kind]={} - cr.commit() - if update_module: - cr.execute("select id,name from ir_module_module where state in ('to remove')") - for mod_id, mod_name in cr.fetchall(): - pool = pooler.get_pool(cr.dbname) - cr.execute('select model,res_id from ir_model_data where not noupdate and module=%s order by id desc', (mod_name,)) - for rmod,rid in cr.fetchall(): - uid = 1 - pool.get(rmod).unlink(cr, uid, [rid]) - cr.commit() - # - # TODO: remove menu without actions of childs - # - while True: - cr.execute('''delete from - ir_ui_menu - where - (id not in (select parent_id from ir_ui_menu where parent_id is not null)) - and - (id not in (select res_id from ir_values where model='ir.ui.menu')) - and - (id not in (select res_id from ir_model_data where model='ir.ui.menu'))''') - if not cr.rowcount: - break - else: - logger.notifyChannel('init', netsvc.LOG_INFO, 'removed %d unused menus' % (cr.rowcount,)) - - cr.execute("update ir_module_module set state=%s where state in ('to remove')", ('uninstalled', )) cr.commit() - #pooler.restart_pool(cr.dbname) - cr.close() + if update_module: + cr.execute("select id,name from ir_module_module where state in ('to remove')") + for mod_id, mod_name in cr.fetchall(): + pool = pooler.get_pool(cr.dbname) + cr.execute('select model,res_id from ir_model_data where not noupdate and module=%s order by id desc', (mod_name,)) + for rmod,rid in cr.fetchall(): + uid = 1 + pool.get(rmod).unlink(cr, uid, [rid]) + cr.commit() + # + # TODO: remove menu without actions of childs + # + while True: + cr.execute('''delete from + ir_ui_menu + where + (id not in (select parent_id from ir_ui_menu where parent_id is not null)) + and + (id not in (select res_id from ir_values where model='ir.ui.menu')) + and + (id not in (select res_id from ir_model_data where model='ir.ui.menu'))''') + if not cr.rowcount: + break + else: + logger.notifyChannel('init', netsvc.LOG_INFO, 'removed %d unused menus' % (cr.rowcount,)) + + cr.execute("update ir_module_module set state=%s where state in ('to remove')", ('uninstalled', )) + cr.commit() + finally: + cr.close() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 348db86e03e021ad90474fe115e465c1cbce2bb3 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Tue, 16 Dec 2008 11:24:03 +0100 Subject: [PATCH 06/10] [FIX] Close the cursor if open bzr revid: stephane@tinyerp.com-20081216102403-7kpf1n7rcho3fk1i --- bin/pooler.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/pooler.py b/bin/pooler.py index 132e99b5089..250ee4f22e5 100644 --- a/bin/pooler.py +++ b/bin/pooler.py @@ -37,9 +37,11 @@ def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False) pool_dic[db_name] = pool addons.load_modules(db, force_demo, status, update_module) cr = db.cursor() - pool.init_set(cr, False) - cr.commit() - cr.close() + try: + pool.init_set(cr, False) + cr.commit() + finally: + cr.close() if not update_module: import report From 3d84754c694e8368a9d5a5c6dd915541dcaa245b Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Tue, 16 Dec 2008 11:36:20 +0100 Subject: [PATCH 07/10] commit bzr revid: fp@tinyerp.com-20081216103620-khy4x2gv3efvh0m1 --- 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 1375794aaf3..a81a8011d52 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -133,7 +133,6 @@ class browse_record(object): self._data[id] = {'id': id} self._cache = cache - pass def __getitem__(self, name): if name == 'id': @@ -2059,7 +2058,8 @@ class orm(orm_template): 'where id in ('+str_d+')', sub_ids) for order, object, ids, fields in result_store: - self.pool.get(object)._store_set_values(cr, uid, ids, fields, context) + if object<>self._name: + self.pool.get(object)._store_set_values(cr, uid, ids, fields, context) return True # From 3cf2202d87abf6b764df1aad655f44be31d2d611 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Tue, 16 Dec 2008 11:39:50 +0100 Subject: [PATCH 08/10] [FIX] Remove the unused constant bzr revid: stephane@tinyerp.com-20081216103950-cdcvcq0fnlt7cs27 --- setup.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/setup.py b/setup.py index 125f9e7b2a5..d7de94a7850 100755 --- a/setup.py +++ b/setup.py @@ -32,8 +32,6 @@ import sys import os import glob -from stat import ST_MODE - from distutils.core import setup, Command from distutils.command.install import install From 88c097516a5e5af5acee4655a276e5bf122b4051 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 16 Dec 2008 11:58:58 +0100 Subject: [PATCH 09/10] [FIX] handle the case when xml are in unicode bzr revid: christophe@cobalt-20081216105858-q0q02gxjt95qbmus --- bin/addons/base/ir/ir_ui_view.py | 2 +- bin/osv/orm.py | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/bin/addons/base/ir/ir_ui_view.py b/bin/addons/base/ir/ir_ui_view.py index afe4990aefc..70c336a7003 100644 --- a/bin/addons/base/ir/ir_ui_view.py +++ b/bin/addons/base/ir/ir_ui_view.py @@ -28,7 +28,7 @@ import os def _check_xml(self, cr, uid, ids, context={}): for view in self.browse(cr, uid, ids, context): - eview = etree.fromstring(view.arch) + eview = etree.fromstring(view.arch.encode('utf8')) frng = tools.file_open(os.path.join('base','rng','view.rng')) relaxng = etree.RelaxNG(file=frng) if not relaxng.validate(eview): diff --git a/bin/osv/orm.py b/bin/osv/orm.py index a81a8011d52..9b3487d71df 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -918,6 +918,12 @@ class orm_template(object): def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False): if not context: context = {} + + def encode(s): + if isinstance(s, unicode): + return s.encode('utf8') + return s + def _inherit_apply(src, inherit): def _find(node, node2): if node2.nodeType == node2.ELEMENT_NODE and node2.localName == 'xpath': @@ -940,9 +946,11 @@ class orm_template(object): if res: return res return None + - doc_src = dom.minidom.parseString(src) - doc_dest = dom.minidom.parseString(inherit) + netsvc.Logger().notifyChannel('orm', netsvc.LOG_DEBUG, type(src)) + doc_src = dom.minidom.parseString(encode(src)) + doc_dest = dom.minidom.parseString(encode(inherit)) toparse = doc_dest.childNodes while len(toparse): node2 = toparse.pop(0) @@ -1057,7 +1065,7 @@ class orm_template(object): result['field_parent'] = False result['view_id'] = 0 - doc = dom.minidom.parseString(result['arch'].encode('utf-8')) + doc = dom.minidom.parseString(encode(result['arch'])) xarch, xfields = self.__view_look_dom_arch(cr, user, doc, context=context) result['arch'] = xarch result['fields'] = xfields From 63f6d4e24ede40f11b7af29d73d6a20cf17edd17 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 16 Dec 2008 12:16:36 +0100 Subject: [PATCH 10/10] [IMP] downgrade the logging level to ERROR when the server cannot connect to the database bzr revid: christophe@cobalt-20081216111636-ahigto4u7l2kueeo --- bin/sql_db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/sql_db.py b/bin/sql_db.py index 3f4e23cc392..eef2a52e92b 100644 --- a/bin/sql_db.py +++ b/bin/sql_db.py @@ -215,7 +215,7 @@ class PoolManager(object): logger.notifyChannel('dbpool', netsvc.LOG_INFO, 'Connecting to %s' % (db_name,)) PoolManager._pools[db_name] = ConnectionPool(ThreadedConnectionPool(1, PoolManager.maxconn, PoolManager.dsn(db_name)), db_name) except Exception, e: - logger.notifyChannel('dbpool', netsvc.LOG_CRITICAL, 'Unable to connect to %s: %s' % (db_name, e.message)) + logger.notifyChannel('dbpool', netsvc.LOG_ERROR, 'Unable to connect to %s: %s' % (db_name, e.message)) raise return PoolManager._pools[db_name] get = staticmethod(get)