4 import dateutil.relativedelta
13 _logger = logging.getLogger(__name__)
15 #----------------------------------------------------------
16 # OpenERPSession RPC openerp backend access
17 #----------------------------------------------------------
18 class AuthenticationError(Exception):
21 class SessionExpiredException(Exception):
24 class Service(object):
25 def __init__(self, session, service_name):
26 self.session = session
27 self.service_name = service_name
29 def __getattr__(self, method):
30 def proxy_method(*args):
31 result = self.session.send(self.service_name, method, *args)
36 def __init__(self, session, model):
37 self.session = session
39 self.proxy = self.session.proxy('object')
41 def __getattr__(self, method):
42 def proxy(*args, **kw):
43 result = self.proxy.execute_kw(self.session._db, self.session._uid, self.session._password, self.model, method, args, kw)
46 if isinstance(result, list) and len(result) > 0 and "id" in result[0]:
50 result = [index[x] for x in args[0] if x in index]
54 def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, context=None):
55 record_ids = self.search(domain or [], offset, limit or False, order or False, context or {})
56 if not record_ids: return []
57 records = self.read(record_ids, fields or [], context or {})
60 class OpenERPSession(object):
62 An OpenERP RPC session, a given user can own multiple such sessions
65 .. attribute:: context
67 The session context, a ``dict``. Can be reloaded by calling
68 :meth:`openerpweb.openerpweb.OpenERPSession.get_context`
70 .. attribute:: domains_store
72 A ``dict`` matching domain keys to evaluable (but non-literal) domains.
74 Used to store references to non-literal domains which need to be
75 round-tripped to the client browser.
78 self._creation_time = time.time()
82 self._password = False
85 self.jsonp_requests = {} # FIXME use a LRU
87 def send(self, service_name, method, *args):
88 code_string = u"warning -- %s\n\n%s"
90 return openerp.netsvc.dispatch_rpc(service_name, method, args)
91 except openerp.osv.osv.except_osv, e:
92 raise xmlrpclib.Fault(code_string % (e.name, e.value), '')
93 except openerp.exceptions.Warning, e:
94 raise xmlrpclib.Fault(code_string % ("Warning", e), '')
95 except openerp.exceptions.AccessError, e:
96 raise xmlrpclib.Fault(code_string % ("AccessError", e), '')
97 except openerp.exceptions.AccessDenied, e:
98 raise xmlrpclib.Fault('AccessDenied', openerp.tools.ustr(e))
99 except openerp.exceptions.DeferredException, e:
100 formatted_info = "".join(traceback.format_exception(*e.traceback))
101 raise xmlrpclib.Fault(openerp.tools.ustr(e), formatted_info)
103 formatted_info = "".join(traceback.format_exception(*(sys.exc_info())))
104 raise xmlrpclib.Fault(openerp.tools.ustr(e), formatted_info)
106 def proxy(self, service):
107 return Service(self, service)
109 def bind(self, db, uid, login, password):
113 self._password = password
115 def authenticate(self, db, login, password, env=None):
116 uid = self.proxy('common').authenticate(db, login, password, env)
117 self.bind(db, uid, login, password)
119 if uid: self.get_context()
122 def assert_valid(self, force=False):
124 Ensures this session is valid (logged into the openerp server)
126 if self._uid and not force:
128 # TODO use authenticate instead of login
129 uid = self.proxy("common").login(self._db, self._login, self._password)
131 raise AuthenticationError("Authentication failure")
133 def ensure_valid(self):
136 self.assert_valid(True)
140 def execute(self, model, func, *l, **d):
142 model = self.model(model)
143 r = getattr(model, func)(*l, **d)
146 def exec_workflow(self, model, id, signal):
148 r = self.proxy('object').exec_workflow(self._db, self._uid, self._password, model, signal, id)
151 def model(self, model):
152 """ Get an RPC proxy for the object ``model``, bound to this session.
154 :param model: an OpenERP model name
156 :rtype: a model object
158 if self._db == False:
159 raise SessionExpiredException("Session expired")
161 return Model(self, model)
163 def get_context(self):
164 """ Re-initializes the current user's session context (based on
165 his preferences) by calling res.users.get_context() with the old
168 :returns: the new context
170 assert self._uid, "The user needs to be logged-in to initialize his context"
171 self.context = self.model('res.users').context_get() or {}
172 self.context['uid'] = self._uid
173 self._fix_lang(self.context)
176 def _fix_lang(self, context):
177 """ OpenERP provides languages which may not make sense and/or may not
178 be understood by the web client's libraries.
182 :param dict context: context to fix
184 lang = context['lang']
186 # inane OpenERP locale
190 # lang to lang_REGION (datejs only handles lang_REGION, no bare langs)
191 if lang in babel.core.LOCALE_ALIASES:
192 lang = babel.core.LOCALE_ALIASES[lang]
194 context['lang'] = lang or 'en_US'