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:
diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml
index 53c9fb7e580..55792706bcf 100644
--- a/bin/addons/base/ir/ir.xml
+++ b/bin/addons/base/ir/ir.xml
@@ -1155,6 +1155,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 = {...}
+""",
}
diff --git a/bin/addons/base/ir/ir_model.py b/bin/addons/base/ir/ir_model.py
index 40ce882e280..471d4d2f6d9 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$
#
@@ -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
@@ -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()
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/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
diff --git a/bin/osv/orm.py b/bin/osv/orm.py
index 1375794aaf3..9b3487d71df 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':
@@ -919,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':
@@ -941,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)
@@ -1058,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
@@ -2059,7 +2066,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
#
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
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)
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