diff --git a/openerp/http.py b/openerp/http.py index 5876cdc6a9a..8c73b33c8a0 100644 --- a/openerp/http.py +++ b/openerp/http.py @@ -36,6 +36,7 @@ import werkzeug.wsgi import openerp from openerp.service import security, model as service_model +from openerp.tools.func import lazy_property _logger = logging.getLogger(__name__) @@ -1077,22 +1078,28 @@ class Root(object): path = openerp.tools.config.session_dir _logger.debug('HTTP sessions stored in: %s', path) self.session_store = werkzeug.contrib.sessions.FilesystemSessionStore(path, session_class=OpenERPSession) + self._loaded = False - # TODO should we move this to ir.http so that only configured modules are served ? - _logger.info("HTTP Configuring static files") - self.load_addons() - + @lazy_property + def nodb_routing_map(self): _logger.info("Generating nondb routing") - self.nodb_routing_map = routing_map([''] + openerp.conf.server_wide_modules, True) + return routing_map([''] + openerp.conf.server_wide_modules, True) def __call__(self, environ, start_response): """ Handle a WSGI request """ + if not self._loaded: + self.load_addons() + self._loaded = True return self.dispatch(environ, start_response) def load_addons(self): """ Load all addons from addons patch containg static files and controllers and configure them. """ + # TODO should we move this to ir.http so that only configured modules are served ? + _logger.info("HTTP Configuring static files") + + self.__dict__.pop('dispatch', None) statics = {} for addons_path in openerp.modules.module.ad_paths: @@ -1284,11 +1291,8 @@ class CommonController(Controller): """ Method used by client APIs to contact OpenERP. """ return dispatch_rpc(service, method, args) -root = None - -def wsgi_postload(): - global root - root = Root() - openerp.service.wsgi_server.register_wsgi_handler(root) +# register main wsgi handler +root = Root() +openerp.service.wsgi_server.register_wsgi_handler(root) # vim:et:ts=4:sw=4: diff --git a/openerp/tools/func.py b/openerp/tools/func.py index ca8bba6bd49..89cdf9fb622 100644 --- a/openerp/tools/func.py +++ b/openerp/tools/func.py @@ -3,7 +3,7 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). -# Copyright (C) 2010 OpenERP s.a. (). +# Copyright (C) 2010, 2014 OpenERP s.a. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -20,11 +20,39 @@ # ############################################################################## -__all__ = ['synchronized'] +__all__ = ['synchronized', 'lazy_property'] from functools import wraps from inspect import getsourcefile + +class lazy_property(object): + """ Decorator for a lazy property of an object, i.e., an object attribute + that is determined by the result of a method call evaluated once. To + reevaluate the property, simply delete the attribute on the object, and + get it again. + """ + def __init__(self, fget): + self.fget = fget + self.name = fget.__name__ + + def __get__(self, obj, cls): + if obj is None: + return self + value = self.fget(obj) + setattr(obj, self.name, value) + return value + + @staticmethod + def reset_all(obj): + """ Reset all lazy properties on the instance `obj`. """ + cls = type(obj) + obj_dict = obj.__dict__ + for name in obj_dict.keys(): + if isinstance(getattr(cls, name, None), lazy_property): + obj_dict.pop(name) + + def synchronized(lock_attr='_lock'): def decorator(func): @wraps(func)