1 # -*- coding: utf-8 -*-
3 from functools import wraps
5 from psycopg2 import IntegrityError, errorcodes
9 from openerp.tools.translate import translate
10 from openerp.osv.orm import except_orm
14 _logger = logging.getLogger(__name__)
16 def dispatch(method, params):
17 (db, uid, passwd ) = params[0:3]
18 threading.current_thread().uid = uid
20 if method == 'obj_list':
21 raise NameError("obj_list has been discontinued via RPC as of 6.0, please query ir.model directly!")
22 if method not in ['execute', 'execute_kw', 'exec_workflow']:
23 raise NameError("Method not available %s" % method)
24 security.check(db,uid,passwd)
25 openerp.modules.registry.RegistryManager.check_registry_signaling(db)
26 fn = globals()[method]
27 res = fn(db, uid, *params)
28 openerp.modules.registry.RegistryManager.signal_caches_change(db)
33 def wrapper(dbname, *args, **kwargs):
34 """ Wraps around OSV functions and normalises a few exceptions
38 # We try to do the same as the _(), but without the frame
39 # inspection, since we aready are wrapping an osv function
40 # trans_obj = self.get('ir.translation') cannot work yet :(
43 if args and isinstance(args[-1], dict):
45 elif isinstance(kwargs, dict):
46 ctx = kwargs.get('context', {})
49 if args and isinstance(args[0], (long, int)):
52 lang = ctx and ctx.get('lang')
53 if not (lang or hasattr(src, '__call__')):
56 # We open a *new* cursor here, one reason is that failed SQL
57 # queries (as in IntegrityError) will invalidate the current one.
60 if hasattr(src, '__call__'):
61 # callable. We need to find the right parameters to call
62 # the orm._sql_message(self, cr, uid, ids, context) function,
64 # our signature is f(osv_pool, dbname [,uid, obj, method, args])
66 if args and len(args) > 1:
67 # TODO self doesn't exist, but was already wrong before (it was not a registry but just the object_service.
68 obj = self.get(args[1])
69 if len(args) > 3 and isinstance(args[3], (long, int, list)):
73 cr = openerp.sql_db.db_connect(dbname).cursor()
74 return src(obj, cr, uid, ids, context=(ctx or {}))
80 return False # so that the original SQL error will
81 # be returned, it is the best we have.
84 cr = openerp.sql_db.db_connect(dbname).cursor()
85 res = translate(cr, name=False, source_type=ttype,
86 lang=lang, source=src)
95 return tr(src, 'code')
98 if openerp.pooler.get_pool(dbname)._init:
99 raise openerp.exceptions.Warning('Currently, this database is not fully loaded and can not be used.')
100 return f(dbname, *args, **kwargs)
103 except IntegrityError, inst:
104 osv_pool = openerp.pooler.get_pool(dbname)
105 for key in osv_pool._sql_error.keys():
107 raise openerp.osv.orm.except_orm(_('Constraint Error'), tr(osv_pool._sql_error[key], 'sql_constraint') or inst[0])
108 if inst.pgcode in (errorcodes.NOT_NULL_VIOLATION, errorcodes.FOREIGN_KEY_VIOLATION, errorcodes.RESTRICT_VIOLATION):
109 msg = _('The operation cannot be completed, probably due to the following:\n- deletion: you may be trying to delete a record while other records still reference it\n- creation/update: a mandatory field is not correctly set')
110 _logger.debug("IntegrityError", exc_info=True)
112 errortxt = inst.pgerror.replace('«','"').replace('»','"')
113 if '"public".' in errortxt:
114 context = errortxt.split('"public".')[1]
115 model_name = table = context.split('"')[1]
117 last_quote_end = errortxt.rfind('"')
118 last_quote_begin = errortxt.rfind('"', 0, last_quote_end)
119 model_name = table = errortxt[last_quote_begin+1:last_quote_end].strip()
120 model = table.replace("_",".")
121 model_obj = osv_pool.get(model)
123 model_name = model_obj._description or model_obj._name
124 msg += _('\n\n[object with reference: %s - %s]') % (model_name, model)
127 raise openerp.osv.orm.except_orm(_('Integrity Error'), msg)
129 raise openerp.osv.orm.except_orm(_('Integrity Error'), inst[0])
131 _logger.exception("Uncaught exception")
136 def execute_cr(cr, uid, obj, method, *args, **kw):
137 object = openerp.pooler.get_pool(cr.dbname).get(obj)
139 raise except_orm('Object Error', 'Object %s doesn\'t exist' % str(obj))
140 return getattr(object, method)(cr, uid, *args, **kw)
142 def execute_kw(db, uid, obj, method, args, kw=None):
143 return execute(db, uid, obj, method, *args, **kw or {})
146 def execute(db, uid, obj, method, *args, **kw):
147 threading.currentThread().dbname = db
148 cr = openerp.pooler.get_db(db).cursor()
151 if method.startswith('_'):
152 raise except_orm('Access Denied', 'Private methods (such as %s) cannot be called remotely.' % (method,))
153 res = execute_cr(cr, uid, obj, method, *args, **kw)
155 _logger.warning('The method %s of the object %s can not return `None` !', method, obj)
164 def exec_workflow_cr(cr, uid, obj, signal, *args):
165 object = openerp.pooler.get_pool(cr.dbname).get(obj)
167 raise except_orm('Object Error', 'Object %s doesn\'t exist' % str(obj))
169 return object._workflow_signal(cr, uid, [res_id], signal)[res_id]
172 def exec_workflow(db, uid, obj, signal, *args):
173 cr = openerp.pooler.get_db(db).cursor()
176 res = exec_workflow_cr(cr, uid, obj, signal, *args)
185 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: