[REV] revert of previous improvement
authorniv-openerp <nicolas.vanhoren@openerp.com>
Wed, 5 Jun 2013 09:29:26 +0000 (11:29 +0200)
committerniv-openerp <nicolas.vanhoren@openerp.com>
Wed, 5 Jun 2013 09:29:26 +0000 (11:29 +0200)
bzr revid: nicolas.vanhoren@openerp.com-20130605092926-dhoumh76dwtl211t

addons/web/controllers/main.py
addons/web/http.py
addons/web/tests/test_dataset.py
addons/web/tests/test_menu.py

index b7071ef..78aa856 100644 (file)
@@ -36,8 +36,6 @@ from openerp.tools.translate import _
 from .. import http
 openerpweb = http
 
-from openerp.addons.web.http import request as req
-
 #----------------------------------------------------------
 # OpenERP Web helpers
 #----------------------------------------------------------
@@ -86,7 +84,7 @@ def rjsmin(script):
     ).strip()
     return result
 
-def db_list():
+def db_list(req):
     proxy = req.session.proxy("db")
     dbs = proxy.list()
     h = req.httprequest.environ['HTTP_HOST'].split(':')[0]
@@ -95,7 +93,7 @@ def db_list():
     dbs = [i for i in dbs if re.match(r, i)]
     return dbs
 
-def db_monodb_redirect():
+def db_monodb_redirect(req):
     db = False
     redirect = False
 
@@ -105,7 +103,7 @@ def db_monodb_redirect():
         return (db_url, False)
 
     try:
-        dbs = db_list()
+        dbs = db_list(req)
     except Exception:
         # ignore access denied
         dbs = []
@@ -126,11 +124,11 @@ def db_monodb_redirect():
         redirect = req.httprequest.path + '?' + urllib.urlencode(query)
     return (db, redirect)
 
-def db_monodb():
+def db_monodb(req):
     # if only one db exists, return it else return False
-    return db_monodb_redirect()[0]
+    return db_monodb_redirect(req)[0]
 
-def redirect_with_hash(url, code=303):
+def redirect_with_hash(req, url, code=303):
     if req.httprequest.user_agent.browser == 'msie':
         try:
             version = float(req.httprequest.user_agent.version)
@@ -184,7 +182,7 @@ def module_topological_sort(modules):
         visit(n)
     return L
 
-def module_installed():
+def module_installed(req):
     # Candidates module the current heuristic is the /static dir
     loadable = openerpweb.addons_manifest.keys()
     modules = {}
@@ -226,14 +224,14 @@ def module_installed_bypass_session(dbname):
     sorted_modules = module_topological_sort(modules)
     return sorted_modules
 
-def module_boot(db=None):
+def module_boot(req, db=None):
     server_wide_modules = openerp.conf.server_wide_modules or ['web']
     serverside = []
     dbside = []
     for i in server_wide_modules:
         if i in openerpweb.addons_manifest:
             serverside.append(i)
-    monodb = db or db_monodb()
+    monodb = db or db_monodb(req)
     if monodb:
         dbside = module_installed_bypass_session(monodb)
         dbside = [i for i in dbside if i not in serverside]
@@ -310,9 +308,9 @@ def fs2web(path):
     """convert FS path into web path"""
     return '/'.join(path.split(os.path.sep))
 
-def manifest_glob(extension, addons=None, db=None):
+def manifest_glob(req, extension, addons=None, db=None):
     if addons is None:
-        addons = module_boot(db=db)
+        addons = module_boot(req, db=db)
     else:
         addons = addons.split(',')
     r = []
@@ -328,7 +326,7 @@ def manifest_glob(extension, addons=None, db=None):
                 r.append((path, fs2web(path[len(addons_path):])))
     return r
 
-def manifest_list(extension, mods=None, db=None):
+def manifest_list(req, extension, mods=None, db=None):
     """ list ressources to load specifying either:
     mods: a comma separated string listing modules
     db: a database name (return all installed modules in that database)
@@ -340,7 +338,7 @@ def manifest_list(extension, mods=None, db=None):
         elif db:
             path += '?' + urllib.urlencode({'db': db})
         return [path]
-    files = manifest_glob(extension, addons=mods, db=db)
+    files = manifest_glob(req, extension, addons=mods, db=db)
     return [wp for _fp, wp in files]
 
 def get_last_modified(files):
@@ -357,13 +355,15 @@ def get_last_modified(files):
                    for f in files)
     return datetime.datetime(1970, 1, 1)
 
-def make_conditional(response, last_modified=None, etag=None):
+def make_conditional(req, response, last_modified=None, etag=None):
     """ Makes the provided response conditional based upon the request,
     and mandates revalidation from clients
 
     Uses Werkzeug's own :meth:`ETagResponseMixin.make_conditional`, after
     setting ``last_modified`` and ``etag`` correctly on the response object
 
+    :param req: OpenERP request
+    :type req: web.common.http.WebRequest
     :param response: Werkzeug response
     :type response: werkzeug.wrappers.Response
     :param datetime.datetime last_modified: last modification date of the response content
@@ -379,7 +379,7 @@ def make_conditional(response, last_modified=None, etag=None):
         response.set_etag(etag)
     return response.make_conditional(req.httprequest)
 
-def login_and_redirect(db, login, key, redirect_url='/'):
+def login_and_redirect(req, db, login, key, redirect_url='/'):
     wsgienv = req.httprequest.environ
     env = dict(
         base_location=req.httprequest.url_root.rstrip('/'),
@@ -387,23 +387,23 @@ def login_and_redirect(db, login, key, redirect_url='/'):
         REMOTE_ADDR=wsgienv['REMOTE_ADDR'],
     )
     req.session.authenticate(db, login, key, env)
-    return set_cookie_and_redirect(redirect_url)
+    return set_cookie_and_redirect(req, redirect_url)
 
-def set_cookie_and_redirect(redirect_url):
+def set_cookie_and_redirect(req, redirect_url):
     redirect = werkzeug.utils.redirect(redirect_url, 303)
     redirect.autocorrect_location_header = False
     cookie_val = urllib2.quote(simplejson.dumps(req.session_id))
     redirect.set_cookie('instance0|session_id', cookie_val)
     return redirect
 
-def load_actions_from_ir_values(key, key2, models, meta):
+def load_actions_from_ir_values(req, key, key2, models, meta):
     Values = req.session.model('ir.values')
     actions = Values.get(key, key2, models, meta, req.context)
 
-    return [(id, name, clean_action(action))
+    return [(id, name, clean_action(req, action))
             for id, name, action in actions]
 
-def clean_action(action):
+def clean_action(req, action):
     action.setdefault('flags', {})
     action_type = action.setdefault('type', 'ir.actions.act_window_close')
     if action_type == 'ir.actions.act_window':
@@ -521,7 +521,7 @@ def xml2json_from_elementtree(el, preserve_whitespaces=False):
     res["children"] = kids
     return res
 
-def content_disposition(filename):
+def content_disposition(filename, req):
     filename = filename.encode('utf8')
     escaped = urllib2.quote(filename)
     browser = req.httprequest.user_agent.browser
@@ -568,28 +568,28 @@ class Home(openerpweb.Controller):
     _cp_path = '/'
 
     @openerpweb.httprequest
-    def index(self, s_action=None, db=None, **kw):
-        db, redir = db_monodb_redirect()
+    def index(self, req, s_action=None, db=None, **kw):
+        db, redir = db_monodb_redirect(req)
         if redir:
-            return redirect_with_hash(redir)
+            return redirect_with_hash(req, redir)
 
-        js = "\n        ".join('<script type="text/javascript" src="%s"></script>' % i for i in manifest_list('js', db=db))
-        css = "\n        ".join('<link rel="stylesheet" href="%s">' % i for i in manifest_list('css', db=db))
+        js = "\n        ".join('<script type="text/javascript" src="%s"></script>' % i for i in manifest_list(req, 'js', db=db))
+        css = "\n        ".join('<link rel="stylesheet" href="%s">' % i for i in manifest_list(req, 'css', db=db))
 
         r = html_template % {
             'js': js,
             'css': css,
-            'modules': simplejson.dumps(module_boot(db=db)),
+            'modules': simplejson.dumps(module_boot(req, db=db)),
             'init': 'var wc = new s.web.WebClient();wc.appendTo($(document.body));'
         }
         return r
 
     @openerpweb.httprequest
-    def login(self, db, login, key):
-        return login_and_redirect(db, login, key)
+    def login(self, req, db, login, key):
+        return login_and_redirect(req, db, login, key)
 
     @openerpweb.jsonrequest
-    def jsonrpc(self, service, method, args):
+    def jsonrpc(self, req, service, method, args):
         """ Method used by client APIs to contact OpenERP. """
         return getattr(req.session.proxy(service), method)(*args)
 
@@ -597,20 +597,20 @@ class WebClient(openerpweb.Controller):
     _cp_path = "/web/webclient"
 
     @openerpweb.jsonrequest
-    def csslist(self, mods=None):
-        return manifest_list('css', mods=mods)
+    def csslist(self, req, mods=None):
+        return manifest_list(req, 'css', mods=mods)
 
     @openerpweb.jsonrequest
-    def jslist(self, mods=None):
-        return manifest_list('js', mods=mods)
+    def jslist(self, req, mods=None):
+        return manifest_list(req, 'js', mods=mods)
 
     @openerpweb.jsonrequest
-    def qweblist(self, mods=None):
-        return manifest_list('qweb', mods=mods)
+    def qweblist(self, req, mods=None):
+        return manifest_list(req, 'qweb', mods=mods)
 
     @openerpweb.httprequest
-    def css(self, mods=None, db=None):
-        files = list(manifest_glob('css', addons=mods, db=db))
+    def css(self, req, mods=None, db=None):
+        files = list(manifest_glob(req, 'css', addons=mods, db=db))
         last_modified = get_last_modified(f[0] for f in files)
         if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
             return werkzeug.wrappers.Response(status=304)
@@ -656,12 +656,12 @@ class WebClient(openerpweb.Controller):
         content = '\n'.join(matches)
 
         return make_conditional(
-            req.make_response(content, [('Content-Type', 'text/css')]),
+            req, req.make_response(content, [('Content-Type', 'text/css')]),
             last_modified, checksum)
 
     @openerpweb.httprequest
-    def js(self, mods=None, db=None):
-        files = [f[0] for f in manifest_glob('js', addons=mods, db=db)]
+    def js(self, req, mods=None, db=None):
+        files = [f[0] for f in manifest_glob(req, 'js', addons=mods, db=db)]
         last_modified = get_last_modified(files)
         if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
             return werkzeug.wrappers.Response(status=304)
@@ -669,12 +669,12 @@ class WebClient(openerpweb.Controller):
         content, checksum = concat_js(files)
 
         return make_conditional(
-            req.make_response(content, [('Content-Type', 'application/javascript')]),
+            req, req.make_response(content, [('Content-Type', 'application/javascript')]),
             last_modified, checksum)
 
     @openerpweb.httprequest
-    def qweb(self, mods=None, db=None):
-        files = [f[0] for f in manifest_glob('qweb', addons=mods, db=db)]
+    def qweb(self, req, mods=None, db=None):
+        files = [f[0] for f in manifest_glob(req, 'qweb', addons=mods, db=db)]
         last_modified = get_last_modified(files)
         if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
             return werkzeug.wrappers.Response(status=304)
@@ -682,11 +682,11 @@ class WebClient(openerpweb.Controller):
         content, checksum = concat_xml(files)
 
         return make_conditional(
-            req.make_response(content, [('Content-Type', 'text/xml')]),
+            req, req.make_response(content, [('Content-Type', 'text/xml')]),
             last_modified, checksum)
 
     @openerpweb.jsonrequest
-    def bootstrap_translations(self, mods):
+    def bootstrap_translations(self, req, mods):
         """ Load local translations from *.po files, as a temporary solution
             until we have established a valid session. This is meant only
             for translating the login page and db management chrome, using
@@ -709,7 +709,7 @@ class WebClient(openerpweb.Controller):
                 "lang_parameters": None}
 
     @openerpweb.jsonrequest
-    def translations(self, mods, lang):
+    def translations(self, req, mods, lang):
         res_lang = req.session.model('res.lang')
         ids = res_lang.search([("code", "=", lang)])
         lang_params = None
@@ -734,19 +734,20 @@ class WebClient(openerpweb.Controller):
                 "lang_parameters": lang_params}
 
     @openerpweb.jsonrequest
-    def version_info(self):
+    def version_info(self, req):
         return openerp.service.common.exp_version()
 
 class Proxy(openerpweb.Controller):
     _cp_path = '/web/proxy'
 
     @openerpweb.jsonrequest
-    def load(self, path):
+    def load(self, req, path):
         """ Proxies an HTTP request through a JSON request.
 
         It is strongly recommended to not request binary files through this,
         as the result will be a binary data blob as well.
 
+        :param req: OpenERP request
         :param path: actual request path
         :return: file content
         """
@@ -759,11 +760,11 @@ class Database(openerpweb.Controller):
     _cp_path = "/web/database"
 
     @openerpweb.jsonrequest
-    def get_list(self):
-        return db_list()
+    def get_list(self, req):
+        return db_list(req)
 
     @openerpweb.jsonrequest
-    def create(self, fields):
+    def create(self, req, fields):
         params = dict(map(operator.itemgetter('name', 'value'), fields))
         return req.session.proxy("db").create_database(
             params['super_admin_pwd'],
@@ -773,7 +774,7 @@ class Database(openerpweb.Controller):
             params['create_admin_pwd'])
 
     @openerpweb.jsonrequest
-    def duplicate(self, fields):
+    def duplicate(self, req, fields):
         params = dict(map(operator.itemgetter('name', 'value'), fields))
         return req.session.proxy("db").duplicate_database(
             params['super_admin_pwd'],
@@ -781,7 +782,7 @@ class Database(openerpweb.Controller):
             params['db_name'])
 
     @openerpweb.jsonrequest
-    def duplicate(self, fields):
+    def duplicate(self, req, fields):
         params = dict(map(operator.itemgetter('name', 'value'), fields))
         duplicate_attrs = (
             params['super_admin_pwd'],
@@ -792,7 +793,7 @@ class Database(openerpweb.Controller):
         return req.session.proxy("db").duplicate_database(*duplicate_attrs)
 
     @openerpweb.jsonrequest
-    def drop(self, fields):
+    def drop(self, req, fields):
         password, db = operator.itemgetter(
             'drop_pwd', 'drop_db')(
                 dict(map(operator.itemgetter('name', 'value'), fields)))
@@ -805,7 +806,7 @@ class Database(openerpweb.Controller):
             return {'error': _('Could not drop database !'), 'title': _('Drop Database')}
 
     @openerpweb.httprequest
-    def backup(self, backup_db, backup_pwd, token):
+    def backup(self, req, backup_db, backup_pwd, token):
         try:
             db_dump = base64.b64decode(
                 req.session.proxy("db").dump(backup_pwd, backup_db))
@@ -816,14 +817,14 @@ class Database(openerpweb.Controller):
             }
             return req.make_response(db_dump,
                [('Content-Type', 'application/octet-stream; charset=binary'),
-               ('Content-Disposition', content_disposition(filename))],
+               ('Content-Disposition', content_disposition(filename, req))],
                {'fileToken': int(token)}
             )
         except Exception, e:
             return simplejson.dumps([[],[{'error': openerp.tools.ustr(e), 'title': _('Backup Database')}]])
 
     @openerpweb.httprequest
-    def restore(self, db_file, restore_pwd, new_db):
+    def restore(self, req, db_file, restore_pwd, new_db):
         try:
             data = base64.b64encode(db_file.read())
             req.session.proxy("db").restore(restore_pwd, new_db, data)
@@ -832,7 +833,7 @@ class Database(openerpweb.Controller):
             raise Exception("AccessDenied")
 
     @openerpweb.jsonrequest
-    def change_password(self, fields):
+    def change_password(self, req, fields):
         old_password, new_password = operator.itemgetter(
             'old_pwd', 'new_pwd')(
                 dict(map(operator.itemgetter('name', 'value'), fields)))
@@ -846,7 +847,7 @@ class Database(openerpweb.Controller):
 class Session(openerpweb.Controller):
     _cp_path = "/web/session"
 
-    def session_info(self):
+    def session_info(self, req):
         req.session.ensure_valid()
         return {
             "session_id": req.session_id,
@@ -857,11 +858,11 @@ class Session(openerpweb.Controller):
         }
 
     @openerpweb.jsonrequest
-    def get_session_info(self):
-        return self.session_info()
+    def get_session_info(self, req):
+        return self.session_info(req)
 
     @openerpweb.jsonrequest
-    def authenticate(self, db, login, password, base_location=None):
+    def authenticate(self, req, db, login, password, base_location=None):
         wsgienv = req.httprequest.environ
         env = dict(
             base_location=base_location,
@@ -870,10 +871,10 @@ class Session(openerpweb.Controller):
         )
         req.session.authenticate(db, login, password, env)
 
-        return self.session_info()
+        return self.session_info(req)
 
     @openerpweb.jsonrequest
-    def change_password (self, fields):
+    def change_password (self,req,fields):
         old_password, new_password,confirm_password = operator.itemgetter('old_pwd', 'new_password','confirm_pwd')(
                 dict(map(operator.itemgetter('name', 'value'), fields)))
         if not (old_password.strip() and new_password.strip() and confirm_password.strip()):
@@ -889,24 +890,24 @@ class Session(openerpweb.Controller):
         return {'error': _('Error, password not changed !'), 'title': _('Change Password')}
 
     @openerpweb.jsonrequest
-    def sc_list(self):
+    def sc_list(self, req):
         return req.session.model('ir.ui.view_sc').get_sc(
             req.session._uid, "ir.ui.menu", req.context)
 
     @openerpweb.jsonrequest
-    def get_lang_list(self):
+    def get_lang_list(self, req):
         try:
             return req.session.proxy("db").list_lang() or []
         except Exception, e:
             return {"error": e, "title": _("Languages")}
 
     @openerpweb.jsonrequest
-    def modules(self):
+    def modules(self, req):
         # return all installed modules. Web client is smart enough to not load a module twice
-        return module_installed()
+        return module_installed(req)
 
     @openerpweb.jsonrequest
-    def save_session_action(self, the_action):
+    def save_session_action(self, req, the_action):
         """
         This method store an action object in the session object and returns an integer
         identifying that action. The method get_session_action() can be used to get
@@ -930,7 +931,7 @@ class Session(openerpweb.Controller):
         return key
 
     @openerpweb.jsonrequest
-    def get_session_action(self, key):
+    def get_session_action(self, req, key):
         """
         Gets back a previously saved action. This method can return None if the action
         was saved since too much time (this case should be handled in a smart way).
@@ -946,21 +947,23 @@ class Session(openerpweb.Controller):
         return saved_actions["actions"].get(key)
 
     @openerpweb.jsonrequest
-    def check(self):
+    def check(self, req):
         req.session.assert_valid()
         return None
 
     @openerpweb.jsonrequest
-    def destroy(self):
+    def destroy(self, req):
         req.session._suicide = True
 
 class Menu(openerpweb.Controller):
     _cp_path = "/web/menu"
 
     @openerpweb.jsonrequest
-    def get_user_roots(self):
+    def get_user_roots(self, req):
         """ Return all root menu ids visible for the session user.
 
+        :param req: A request object, with an OpenERP session attribute
+        :type req: < session -> OpenERPSession >
         :return: the root menu ids
         :rtype: list(int)
         """
@@ -980,16 +983,18 @@ class Menu(openerpweb.Controller):
         return Menus.search(menu_domain, 0, False, False, req.context)
 
     @openerpweb.jsonrequest
-    def load(self):
+    def load(self, req):
         """ Loads all menu items (all applications and their sub-menus).
 
+        :param req: A request object, with an OpenERP session attribute
+        :type req: < session -> OpenERPSession >
         :return: the menu root
         :rtype: dict('children': menu_nodes)
         """
         Menus = req.session.model('ir.ui.menu')
 
         fields = ['name', 'sequence', 'parent_id', 'action']
-        menu_root_ids = self.get_user_roots()
+        menu_root_ids = self.get_user_roots(req)
         menu_roots = Menus.read(menu_root_ids, fields, req.context) if menu_root_ids else []
         menu_root = {
             'id': False,
@@ -1031,7 +1036,7 @@ class Menu(openerpweb.Controller):
         return menu_root
 
     @openerpweb.jsonrequest
-    def load_needaction(self, menu_ids):
+    def load_needaction(self, req, menu_ids):
         """ Loads needaction counters for specific menu ids.
 
             :return: needaction data
@@ -1040,9 +1045,9 @@ class Menu(openerpweb.Controller):
         return req.session.model('ir.ui.menu').get_needaction_data(menu_ids, req.context)
 
     @openerpweb.jsonrequest
-    def action(self, menu_id):
+    def action(self, req, menu_id):
         # still used by web_shortcut
-        actions = load_actions_from_ir_values('action', 'tree_but_open',
+        actions = load_actions_from_ir_values(req,'action', 'tree_but_open',
                                              [('ir.ui.menu', menu_id)], False)
         return {"action": actions}
 
@@ -1050,13 +1055,15 @@ class DataSet(openerpweb.Controller):
     _cp_path = "/web/dataset"
 
     @openerpweb.jsonrequest
-    def search_read(self, model, fields=False, offset=0, limit=False, domain=None, sort=None):
-        return self.do_search_read(model, fields, offset, limit, domain, sort)
-    def do_search_read(self, model, fields=False, offset=0, limit=False, domain=None
+    def search_read(self, req, model, fields=False, offset=0, limit=False, domain=None, sort=None):
+        return self.do_search_read(req, model, fields, offset, limit, domain, sort)
+    def do_search_read(self, req, model, fields=False, offset=0, limit=False, domain=None
                        , sort=None):
         """ Performs a search() followed by a read() (if needed) using the
         provided search criteria
 
+        :param req: a JSON-RPC request object
+        :type req: openerpweb.JsonRequest
         :param str model: the name of the model to search on
         :param fields: a list of the fields to return in the result records
         :type fields: [str]
@@ -1092,7 +1099,7 @@ class DataSet(openerpweb.Controller):
         }
 
     @openerpweb.jsonrequest
-    def load(self, model, id, fields):
+    def load(self, req, model, id, fields):
         m = req.session.model(model)
         value = {}
         r = m.read([id], False, req.context)
@@ -1100,10 +1107,10 @@ class DataSet(openerpweb.Controller):
             value = r[0]
         return {'value': value}
 
-    def call_common(self, model, method, args, domain_id=None, context_id=None):
-        return self._call_kw(model, method, args, {})
+    def call_common(self, req, model, method, args, domain_id=None, context_id=None):
+        return self._call_kw(req, model, method, args, {})
 
-    def _call_kw(self, model, method, args, kwargs):
+    def _call_kw(self, req, model, method, args, kwargs):
         # Temporary implements future display_name special field for model#read()
         if method == 'read' and kwargs.get('context', {}).get('future_display_name'):
             if 'display_name' in args[1]:
@@ -1118,26 +1125,26 @@ class DataSet(openerpweb.Controller):
         return getattr(req.session.model(model), method)(*args, **kwargs)
 
     @openerpweb.jsonrequest
-    def call(self, model, method, args, domain_id=None, context_id=None):
-        return self._call_kw(model, method, args, {})
+    def call(self, req, model, method, args, domain_id=None, context_id=None):
+        return self._call_kw(req, model, method, args, {})
 
     @openerpweb.jsonrequest
-    def call_kw(self, model, method, args, kwargs):
-        return self._call_kw(model, method, args, kwargs)
+    def call_kw(self, req, model, method, args, kwargs):
+        return self._call_kw(req, model, method, args, kwargs)
 
     @openerpweb.jsonrequest
-    def call_button(self, model, method, args, domain_id=None, context_id=None):
-        action = self._call_kw(model, method, args, {})
+    def call_button(self, req, model, method, args, domain_id=None, context_id=None):
+        action = self._call_kw(req, model, method, args, {})
         if isinstance(action, dict) and action.get('type') != '':
-            return clean_action(action)
+            return clean_action(req, action)
         return False
 
     @openerpweb.jsonrequest
-    def exec_workflow(self, model, id, signal):
+    def exec_workflow(self, req, model, id, signal):
         return req.session.exec_workflow(model, id, signal)
 
     @openerpweb.jsonrequest
-    def resequence(self, model, ids, field='sequence', offset=0):
+    def resequence(self, req, model, ids, field='sequence', offset=0):
         """ Re-sequences a number of records in the model, by their ids
 
         The re-sequencing starts at the first model of ``ids``, the sequence
@@ -1163,7 +1170,7 @@ class View(openerpweb.Controller):
     _cp_path = "/web/view"
 
     @openerpweb.jsonrequest
-    def add_custom(self, view_id, arch):
+    def add_custom(self, req, view_id, arch):
         CustomView = req.session.model('ir.ui.view.custom')
         CustomView.create({
             'user_id': req.session._uid,
@@ -1173,7 +1180,7 @@ class View(openerpweb.Controller):
         return {'result': True}
 
     @openerpweb.jsonrequest
-    def undo_custom(self, view_id, reset=False):
+    def undo_custom(self, req, view_id, reset=False):
         CustomView = req.session.model('ir.ui.view.custom')
         vcustom = CustomView.search([('user_id', '=', req.session._uid), ('ref_id' ,'=', view_id)],
                                     0, False, False, req.context)
@@ -1189,16 +1196,16 @@ class TreeView(View):
     _cp_path = "/web/treeview"
 
     @openerpweb.jsonrequest
-    def action(self, model, id):
+    def action(self, req, model, id):
         return load_actions_from_ir_values(
-            'action', 'tree_but_open',[(model, id)],
+            req,'action', 'tree_but_open',[(model, id)],
             False)
 
 class Binary(openerpweb.Controller):
     _cp_path = "/web/binary"
 
     @openerpweb.httprequest
-    def image(self, model, id, field, **kw):
+    def image(self, req, model, id, field, **kw):
         last_update = '__last_update'
         Model = req.session.model(model)
         headers = [('Content-Type', 'image/png')]
@@ -1238,7 +1245,7 @@ class Binary(openerpweb.Controller):
             image_data = base64.b64decode(image_base64)
 
         except Exception:
-            image_data = self.placeholder()
+            image_data = self.placeholder(req)
         headers.append(('ETag', retag))
         headers.append(('Content-Length', len(image_data)))
         try:
@@ -1248,18 +1255,20 @@ class Binary(openerpweb.Controller):
             pass
         return req.make_response(image_data, headers)
 
-    def placeholder(self, image='placeholder.png'):
+    def placeholder(self, req, image='placeholder.png'):
         addons_path = openerpweb.addons_manifest['web']['addons_path']
         return open(os.path.join(addons_path, 'web', 'static', 'src', 'img', image), 'rb').read()
 
     @openerpweb.httprequest
-    def saveas(self, model, field, id=None, filename_field=None, **kw):
+    def saveas(self, req, model, field, id=None, filename_field=None, **kw):
         """ Download link for files stored as binary fields.
 
         If the ``id`` parameter is omitted, fetches the default value for the
         binary field (via ``default_get``), otherwise fetches the field for
         that precise record.
 
+        :param req: OpenERP request
+        :type req: :class:`web.common.http.HttpRequest`
         :param str model: name of the model to fetch the binary from
         :param str field: binary field
         :param str id: id of the record from which to fetch the binary
@@ -1283,10 +1292,10 @@ class Binary(openerpweb.Controller):
                 filename = res.get(filename_field, '') or filename
             return req.make_response(filecontent,
                 [('Content-Type', 'application/octet-stream'),
-                 ('Content-Disposition', content_disposition(filename))])
+                 ('Content-Disposition', content_disposition(filename, req))])
 
     @openerpweb.httprequest
-    def saveas_ajax(self, data, token):
+    def saveas_ajax(self, req, data, token):
         jdata = simplejson.loads(data)
         model = jdata['model']
         field = jdata['field']
@@ -1315,11 +1324,11 @@ class Binary(openerpweb.Controller):
                 filename = res.get(filename_field, '') or filename
             return req.make_response(filecontent,
                 headers=[('Content-Type', 'application/octet-stream'),
-                        ('Content-Disposition', content_disposition(filename))],
+                        ('Content-Disposition', content_disposition(filename, req))],
                 cookies={'fileToken': int(token)})
 
     @openerpweb.httprequest
-    def upload(self, callback, ufile):
+    def upload(self, req, callback, ufile):
         # TODO: might be useful to have a configuration flag for max-length file uploads
         out = """<script language="javascript" type="text/javascript">
                     var win = window.top.window;
@@ -1334,7 +1343,7 @@ class Binary(openerpweb.Controller):
         return out % (simplejson.dumps(callback), simplejson.dumps(args))
 
     @openerpweb.httprequest
-    def upload_attachment(self, callback, model, id, ufile):
+    def upload_attachment(self, req, callback, model, id, ufile):
         Model = req.session.model('ir.attachment')
         out = """<script language="javascript" type="text/javascript">
                     var win = window.top.window;
@@ -1357,20 +1366,20 @@ class Binary(openerpweb.Controller):
         return out % (simplejson.dumps(callback), simplejson.dumps(args))
 
     @openerpweb.httprequest
-    def company_logo(self, dbname=None):
+    def company_logo(self, req, dbname=None):
         # TODO add etag, refactor to use /image code for etag
         uid = None
         if req.session._db:
             dbname = req.session._db
             uid = req.session._uid
         elif dbname is None:
-            dbname = db_monodb()
+            dbname = db_monodb(req)
 
         if not uid:
             uid = openerp.SUPERUSER_ID
 
         if not dbname:
-            image_data = self.placeholder('logo.png')
+            image_data = self.placeholder(req, 'logo.png')
         else:
             try:
                 # create an empty registry
@@ -1386,9 +1395,9 @@ class Binary(openerpweb.Controller):
                     if row and row[0]:
                         image_data = str(row[0]).decode('base64')
                     else:
-                        image_data = self.placeholder('nologo.png')
+                        image_data = self.placeholder(req, 'nologo.png')
             except Exception:
-                image_data = self.placeholder('logo.png')
+                image_data = self.placeholder(req, 'logo.png')
 
         headers = [
             ('Content-Type', 'image/png'),
@@ -1400,7 +1409,7 @@ class Action(openerpweb.Controller):
     _cp_path = "/web/action"
 
     @openerpweb.jsonrequest
-    def load(self, action_id, do_not_eval=False):
+    def load(self, req, action_id, do_not_eval=False):
         Actions = req.session.model('ir.actions.actions')
         value = False
         try:
@@ -1422,15 +1431,15 @@ class Action(openerpweb.Controller):
             ctx.update(req.context)
             action = req.session.model(action_type).read([action_id], False, ctx)
             if action:
-                value = clean_action(action[0])
+                value = clean_action(req, action[0])
         return value
 
     @openerpweb.jsonrequest
-    def run(self, action_id):
+    def run(self, req, action_id):
         return_action = req.session.model('ir.actions.server').run(
             [action_id], req.context)
         if return_action:
-            return clean_action(return_action)
+            return clean_action(req, return_action)
         else:
             return False
 
@@ -1438,7 +1447,7 @@ class Export(openerpweb.Controller):
     _cp_path = "/web/export"
 
     @openerpweb.jsonrequest
-    def formats(self):
+    def formats(self, req):
         """ Returns all valid export formats
 
         :returns: for each export format, a pair of identifier and printable name
@@ -1451,20 +1460,20 @@ class Export(openerpweb.Controller):
             if hasattr(controller, 'fmt')
         ], key=operator.itemgetter("label"))
 
-    def fields_get(self, model):
+    def fields_get(self, req, model):
         Model = req.session.model(model)
         fields = Model.fields_get(False, req.context)
         return fields
 
     @openerpweb.jsonrequest
-    def get_fields(self, model, prefix='', parent_name= '',
+    def get_fields(self, req, model, prefix='', parent_name= '',
                    import_compat=True, parent_field_type=None,
                    exclude=None):
 
         if import_compat and parent_field_type == "many2one":
             fields = {}
         else:
-            fields = self.fields_get(model)
+            fields = self.fields_get(req, model)
 
         if import_compat:
             fields.pop('id', None)
@@ -1506,23 +1515,23 @@ class Export(openerpweb.Controller):
         return records
 
     @openerpweb.jsonrequest
-    def namelist(self, model, export_id):
+    def namelist(self,req,  model, export_id):
         # TODO: namelist really has no reason to be in Python (although itertools.groupby helps)
         export = req.session.model("ir.exports").read([export_id])[0]
         export_fields_list = req.session.model("ir.exports.line").read(
             export['export_fields'])
 
         fields_data = self.fields_info(
-            model, map(operator.itemgetter('name'), export_fields_list))
+            req, model, map(operator.itemgetter('name'), export_fields_list))
 
         return [
             {'name': field['name'], 'label': fields_data[field['name']]}
             for field in export_fields_list
         ]
 
-    def fields_info(self, model, export_fields):
+    def fields_info(self, req, model, export_fields):
         info = {}
-        fields = self.fields_get(model)
+        fields = self.fields_get(req, model)
         if ".id" in export_fields:
             fields['.id'] = fields.pop('id', {'string': 'ID'})
 
@@ -1561,7 +1570,7 @@ class Export(openerpweb.Controller):
             if length == 2:
                 # subfields is a seq of $base/*rest, and not loaded yet
                 info.update(self.graft_subfields(
-                    fields[base]['relation'], base, fields[base]['string'],
+                    req, fields[base]['relation'], base, fields[base]['string'],
                     subfields
                 ))
             else:
@@ -1569,11 +1578,11 @@ class Export(openerpweb.Controller):
 
         return info
 
-    def graft_subfields(self, model, prefix, prefix_string, fields):
+    def graft_subfields(self, req, model, prefix, prefix_string, fields):
         export_fields = [field.split('/', 1)[1] for field in fields]
         return (
             (prefix + '/' + k, prefix_string + '/' + v)
-            for k, v in self.fields_info(model, export_fields).iteritems())
+            for k, v in self.fields_info(req, model, export_fields).iteritems())
 
 class ExportFormat(object):
     @property
@@ -1599,7 +1608,7 @@ class ExportFormat(object):
         raise NotImplementedError()
 
     @openerpweb.httprequest
-    def index(self, data, token):
+    def index(self, req, data, token):
         model, fields, ids, domain, import_compat = \
             operator.itemgetter('model', 'fields', 'ids', 'domain',
                                 'import_compat')(
@@ -1619,7 +1628,7 @@ class ExportFormat(object):
 
         return req.make_response(self.from_data(columns_headers, import_data),
             headers=[('Content-Disposition',
-                            content_disposition(self.filename(model))),
+                            content_disposition(self.filename(model), req)),
                      ('Content-Type', self.content_type)],
             cookies={'fileToken': int(token)})
 
@@ -1710,7 +1719,7 @@ class Reports(openerpweb.Controller):
     }
 
     @openerpweb.httprequest
-    def index(self, action, token):
+    def index(self, req, action, token):
         action = simplejson.loads(action)
 
         report_srv = req.session.proxy("report")
@@ -1758,7 +1767,7 @@ class Reports(openerpweb.Controller):
 
         return req.make_response(report,
              headers=[
-                 ('Content-Disposition', content_disposition(file_name)),
+                 ('Content-Disposition', content_disposition(file_name, req)),
                  ('Content-Type', report_mimetype),
                  ('Content-Length', len(report))],
              cookies={'fileToken': int(token)})
index 5ada5d4..7e10ccc 100644 (file)
@@ -34,9 +34,6 @@ import openerp
 
 import session
 
-import inspect
-import functools
-
 _logger = logging.getLogger(__name__)
 
 #----------------------------------------------------------
@@ -200,10 +197,10 @@ class JsonRequest(WebRequest):
             else:
                 self.jsonrequest = simplejson.loads(request, object_hook=reject_nonliteral)
             self.init(self.jsonrequest.get("params", {}))
-            #if _logger.isEnabledFor(logging.DEBUG):
-            #    _logger.debug("--> %s.%s\n%s", method.im_class.__name__, method.__name__, pprint.pformat(self.jsonrequest))
+            if _logger.isEnabledFor(logging.DEBUG):
+                _logger.debug("--> %s.%s\n%s", method.im_class.__name__, method.__name__, pprint.pformat(self.jsonrequest))
             response['id'] = self.jsonrequest.get('id')
-            response["result"] = method(**self.params)
+            response["result"] = method(self, **self.params)
         except session.AuthenticationError, e:
             se = serialize_exception(e)
             error = {
@@ -295,9 +292,9 @@ class HttpRequest(WebRequest):
                 akw[key] = value
             else:
                 akw[key] = type(value)
-        #_logger.debug("%s --> %s.%s %r", self.httprequest.method, method.im_class.__name__, method.__name__, akw)
+        _logger.debug("%s --> %s.%s %r", self.httprequest.method, method.im_class.__name__, method.__name__, akw)
         try:
-            r = method(**self.params)
+            r = method(self, **self.params)
         except Exception, e:
             _logger.exception("An exception occured during an http request")
             se = serialize_exception(e)
@@ -353,31 +350,6 @@ def httprequest(f):
     return f
 
 #----------------------------------------------------------
-# Local storage of requests
-#----------------------------------------------------------
-_thlocal = threading.local()
-
-class RequestProxy(object):
-    def __getattr__(self, name):
-        return getattr(_thlocal.stack[-1], name)
-    def __setattr__(self, name, val):
-        return setattr(_thlocal.stack[-1], name, val)
-    def __delattr__(self, name):
-        return delattr(_thlocal.stack[-1], name)
-    @classmethod
-    def set_request(cls, request):
-        class with_obj:
-            def __enter__(self):
-                if getattr(_thlocal, "stack", None) is None:
-                    _thlocal.stack = []
-                _thlocal.stack.append(request)
-            def __exit__(self, *args):
-                _thlocal.stack.pop()
-        return with_obj()
-
-request = RequestProxy()
-
-#----------------------------------------------------------
 # Controller registration with a metaclass
 #----------------------------------------------------------
 addons_module = {}
@@ -391,19 +363,6 @@ controllers_path = {}
 class ControllerType(type):
     def __init__(cls, name, bases, attrs):
         super(ControllerType, cls).__init__(name, bases, attrs)
-
-        # create wrappers for old-style methods with req as first argument
-        cls._methods_wrapper = {}
-        for k, v in attrs.items():
-            if inspect.isfunction(v):
-                spec = inspect.getargspec(v)
-                first_arg = spec.args[1] if len(spec.args) >= 2 else None
-                if first_arg in ["req", "request"]:
-                    def build_new(nv):
-                        return lambda self, *args, **kwargs: nv(self, request, *args, **kwargs)
-                    cls._methods_wrapper[k] = build_new(v)
-
-        # store the controller in the controllers list
         name_class = ("%s.%s" % (cls.__module__, cls.__name__), cls)
         controllers_class.append(name_class)
         path = attrs.get('_cp_path')
@@ -421,12 +380,6 @@ class Controller(object):
 
         return object.__new__(cls)
 
-    def get_wrapped_method(self, name):
-        if name in self.__class__._methods_wrapper:
-            return functools.partial(self.__class__._methods_wrapper[name], self)
-        else:
-            return getattr(self, name)
-
 #----------------------------------------------------------
 # Session context manager
 #----------------------------------------------------------
@@ -655,21 +608,12 @@ class Root(object):
                     method = getattr(c, method_name, None)
                     if method:
                         exposed = getattr(method, 'exposed', False)
-                        method = c.get_wrapped_method(method_name)
                         if exposed == 'json':
                             _logger.debug("Dispatch json to %s %s %s", ps, c, method_name)
-                            def fct(request):
-                                req = JsonRequest(request)
-                                with RequestProxy.set_request(req):
-                                    return req.dispatch(method)
-                            return fct
+                            return lambda request: JsonRequest(request).dispatch(method)
                         elif exposed == 'http':
                             _logger.debug("Dispatch http to %s %s %s", ps, c, method_name)
-                            def fct(request):
-                                req = HttpRequest(request)
-                                with RequestProxy.set_request(req):
-                                    return req.dispatch(method)
-                            return fct
+                            return lambda request: HttpRequest(request).dispatch(method)
                     if method_name != "index":
                         method_name = "index"
                         continue
index 72cd99a..a6faf9e 100644 (file)
@@ -2,36 +2,30 @@
 import mock
 import unittest2
 import openerp.addons.web.controllers.main
-from openerp.addons.web.http import request as req
-from openerp.addons.web.http import RequestProxy
 
 class TestDataSetController(unittest2.TestCase):
     def setUp(self):
         self.dataset = openerp.addons.web.controllers.main.DataSet()
-        self.tmp_req = RequestProxy.set_request(mock.Mock())
-        self.tmp_req.__enter__()
-        self.read = req.session.model().read
-        self.search = req.session.model().search
-
-    def tearDown(self):
-        self.tmp_req.__exit__()
+        self.request = mock.Mock()
+        self.read = self.request.session.model().read
+        self.search = self.request.session.model().search
 
     def test_empty_find(self):
         self.search.return_value = []
         self.read.return_value = []
 
         self.assertEqual(
-            self.dataset.do_search_read('fake.model'),
+            self.dataset.do_search_read(self.request, 'fake.model'),
             {'records': [], 'length': 0})
         self.read.assert_called_once_with(
-            [], False, req.context)
+            [], False, self.request.context)
 
     def test_regular_find(self):
         self.search.return_value = [1, 2, 3]
 
-        self.dataset.do_search_read('fake.model')
+        self.dataset.do_search_read(self.request, 'fake.model')
         self.read.assert_called_once_with(
-            [1, 2, 3], False, req.context)
+            [1, 2, 3], False,self.request.context)
 
     def test_ids_shortcut(self):
         self.search.return_value = [1, 2, 3]
@@ -42,6 +36,6 @@ class TestDataSetController(unittest2.TestCase):
         ]
 
         self.assertEqual(
-            self.dataset.do_search_read('fake.model', ['id']),
+            self.dataset.do_search_read(self.request, 'fake.model', ['id']),
             {'records': [{'id': 1}, {'id': 2}, {'id': 3}], 'length': 3})
         self.assertFalse(self.read.called)
index 7360354..9ad9eea 100644 (file)
@@ -2,8 +2,6 @@
 import collections
 import mock
 import unittest2
-from openerp.addons.web.http import request as req
-from openerp.addons.web.http import RequestProxy
 
 from ..controllers import main
 
@@ -15,13 +13,12 @@ class Placeholder(object):
 class LoadTest(unittest2.TestCase):
     def setUp(self):
         self.menu = main.Menu()
-        self.tmp_req = RequestProxy.set_request(mock.Mock())
-        self.tmp_req.__enter__()
+        self.request = mock.Mock()
 
         # Have self.request.session.model() return a different mock object for
         # each model (but always the same mock for a given model name)
         models = collections.defaultdict(mock.Mock)
-        model = req.session.model.side_effect = \
+        model = self.request.session.model.side_effect = \
             lambda model_name: models[model_name]
 
         self.MockMenus = model('ir.ui.menu')
@@ -31,7 +28,7 @@ class LoadTest(unittest2.TestCase):
         }]
 
     def tearDown(self):
-        self.tmp_req.__exit__()
+        del self.request
         del self.MockMenus
         del self.menu
 
@@ -39,11 +36,11 @@ class LoadTest(unittest2.TestCase):
         self.MockMenus.search.return_value = []
         self.MockMenus.read.return_value = []
 
-        root = self.menu.load()
+        root = self.menu.load(self.request)
 
         self.MockMenus.search.assert_called_with(
             [('parent_id','=', False)], 0, False, False,
-            req.context)
+            self.request.context)
 
         self.assertEqual(root['all_menu_ids'], [])
 
@@ -59,16 +56,16 @@ class LoadTest(unittest2.TestCase):
             {'id': 2, 'sequence': 3, 'parent_id': False},
         ]
 
-        root = self.menu.load()
+        root = self.menu.load(self.request)
 
         self.MockMenus.search.assert_called_with(
             [('id','child_of', [1, 2, 3])], 0, False, False,
-            req.context)
+            self.request.context)
 
         self.MockMenus.read.assert_called_with(
             [1, 2, 3], ['name', 'sequence', 'parent_id',
                         'action'],
-            req.context)
+            self.request.context)
 
         self.assertEqual(root['all_menu_ids'], [1, 2, 3])
 
@@ -98,11 +95,11 @@ class LoadTest(unittest2.TestCase):
                 {'id': 4, 'sequence': 2, 'parent_id': [2, '']},
             ])
 
-        root = self.menu.load()
+        root = self.menu.load(self.request)
 
         self.MockMenus.search.assert_called_with(
             [('id','child_of', [1])], 0, False, False,
-            req.context)
+            self.request.context)
 
         self.assertEqual(root['all_menu_ids'], [1, 2, 3, 4])