1. Olemis Lang
  2. bloodhound_hggit

Commits

Jure Žitnik  committed e8093ba Draft

#441, web bootstap handler, patch t441_r1468583_trac_bootstrap_handler.diff applied (from Olemis)

git-svn-id: https://svn.apache.org/repos/asf/bloodhound/trunk@146919813f79535-47bb-0310-9956-ffa450edef68

  • Participants
  • Parent commits 4bee3bb
  • Branches default

Comments (0)

Files changed (2)

File trac/trac/hooks.py

View file
 import imp
 import inspect
 
-from config import Configuration
-from util.concurrency import threading
+from trac.config import Configuration
+from trac.env import open_environment
+from trac.util.concurrency import threading
+from trac.web.api import RequestDone
+from trac.web.href import Href
+from trac.web.main import RequestWithSession
+
 
 __all__ = ['environment_factory', 'install_global_hooks']
 
 class EnvironmentFactoryBase(object):
     def open_environment(self, environ, env_path, global_env, use_cache=False):
-        return None
+        raise NotImplementedError("Must override method 'open_environment'")
 
 class RequestFactoryBase(object):
     def create_request(self, env, environ, start_response):
-        return None
+        raise NotImplementedError("Must override method 'create_request'")
 
 def _get_plugins_dir(env_path):
     return os.path.normcase(os.path.realpath(os.path.join(env_path, 'plugins')))
 def request_factory(env):
     hook_path = env.config.get('trac', 'request_factory', default=None)
     return _get_hook_class(env.path, hook_path, RequestFactoryBase) if hook_path else None
+
+class BootstrapHandlerBase(object):
+    """Objects responsible for loading the target environment and
+    request objects used in subsequent dispatching. 
+    """
+    def open_environment(self, environ, start_response):
+        """Load and initialize target Trac environment involved in request
+        dispatching.
+
+        The following WSGI entries will also be present in `environ` dict:
+
+        ||= WSGI variable =||= Environment variable =||= Comment =||
+        || trac.env_path || TRAC_ENV || See wiki:TracModWSGI ||
+        || trac.env_parent_dir || TRAC_ENV_PARENT_DIR || See wiki:TracModWSGI||
+        || trac.env_index_template || TRAC_ENV_INDEX_TEMPLATE || See wiki:TracInterfaceCustomization ||
+        || trac.template_vars || TRAC_TEMPLATE_VARS || See wiki:TracInterfaceCustomization ||
+        || trac.locale ||  || Target locale ||
+        || trac.base_url || TRAC_BASE_URL || Trac base URL hint ||
+
+        This method may handle the request (e.g. render environment index page)
+        in case environment lookup yields void results. In that case it MUST 
+        invoke WSGI `write` callable returned by `start_response` and raise 
+        `trac.web.api.RequestDone` exception.
+
+        :param environ: WSGI environment dict
+        :param start_response: WSGI callback for starting the response
+        :throws RequestDone: if the request is fully processed while loading
+                             target environment e.g. environment index page
+        :throws EnvironmentError: if it is impossible to find a way to locate
+                                  target environment e.g. TRAC_ENV and 
+                                  TRAC_ENV_PARENT_DIR both missing
+        :throws Exception: any other exception will be processed by the caller 
+                           in order to send a generic error message back to
+                           the HTTP client
+        """
+        raise NotImplementedError("Must override method 'open_environment'")
+
+    def create_request(self, env, environ, start_response):
+        """Instantiate request object used in subsequent request dispatching
+        
+        :param env: target Trac environment returned by `open_environment`
+        :param environ: WSGI environment dict
+        :param start_response: WSGI callback for starting the response
+        """
+        raise NotImplementedError("Must override method 'create_request'")
+
+
+class DefaultBootstrapHandler(BootstrapHandlerBase):
+    """Default bootstrap handler
+    
+    - Load environment based on URL path.
+    - Instantiate RequestWithSession
+    
+    Notice: This class is a straightforward refactoring of factories
+    implementation.
+    """
+    global_env = None
+
+    def open_environment(self, environ, start_response):
+        env_path = environ.get('trac.env_path')
+        if not env_path:
+            env_parent_dir = environ.get('trac.env_parent_dir')
+            env_paths = environ.get('trac.env_paths')
+            if env_parent_dir or env_paths:
+                # The first component of the path is the base name of the
+                # environment
+                path_info = environ.get('PATH_INFO', '').lstrip('/').split('/')
+                env_name = path_info.pop(0)
+    
+                if not env_name:
+                    # No specific environment requested, so render an environment
+                    # index page
+                    send_project_index(environ, start_response, env_parent_dir,
+                                       env_paths)
+                    raise RequestDone
+    
+                errmsg = None
+    
+                # To make the matching patterns of request handlers work, we append
+                # the environment name to the `SCRIPT_NAME` variable, and keep only
+                # the remaining path in the `PATH_INFO` variable.
+                script_name = environ.get('SCRIPT_NAME', '')
+                try:
+                    script_name = unicode(script_name, 'utf-8')
+                    # (as Href expects unicode parameters)
+                    environ['SCRIPT_NAME'] = Href(script_name)(env_name)
+                    environ['PATH_INFO'] = '/' + '/'.join(path_info)
+    
+                    if env_parent_dir:
+                        env_path = os.path.join(env_parent_dir, env_name)
+                    else:
+                        env_path = get_environments(environ).get(env_name)
+    
+                    if not env_path or not os.path.isdir(env_path):
+                        errmsg = 'Environment not found'
+                except UnicodeDecodeError:
+                    errmsg = 'Invalid URL encoding (was %r)' % script_name
+    
+                if errmsg:
+                    write = start_response('404 Not Found',
+                                   [('Content-Type', 'text/plain'),
+                                    ('Content-Length', str(len(errmsg)))])
+                    write(errmsg)
+                    raise RequestDone
+    
+        if not env_path:
+            raise EnvironmentError('The environment options "TRAC_ENV" or '
+                                   '"TRAC_ENV_PARENT_DIR" or the mod_python '
+                                   'options "TracEnv" or "TracEnvParentDir" are '
+                                   'missing. Trac requires one of these options '
+                                   'to locate the Trac environment(s).')
+        run_once = environ['wsgi.run_once']
+    
+        env = None
+        self.global_env = global_env = None
+        try:
+            self.global_env = global_env = open_environment(env_path, use_cache=not run_once)
+            factory = environment_factory(global_env)
+            factory_env = factory().open_environment(environ, env_path, global_env, use_cache=not run_once) if factory \
+                            else None
+            env = factory_env if factory_env else global_env
+        except Exception:
+            raise
+        return env
+
+    def create_request(self, env, environ, start_response):
+        factory = None
+        try:
+            factory = request_factory(self.global_env)
+        except AttributeError:
+            pass
+        return factory().create_request(env, environ, start_response) if factory \
+                else RequestWithSession(environ, start_response)
+
+# Recursive imports
+from trac.web.main import send_project_index, get_environments

File trac/trac/web/main.py

View file
 
     locale.setlocale(locale.LC_ALL, environ['trac.locale'])
 
+    # FIXME: Load custom bootstrap handler
+    from trac.hooks import DefaultBootstrapHandler
+    bootstrap = DefaultBootstrapHandler()
+
     # Determine the environment
-    env_path = environ.get('trac.env_path')
-    if not env_path:
-        env_parent_dir = environ.get('trac.env_parent_dir')
-        env_paths = environ.get('trac.env_paths')
-        if env_parent_dir or env_paths:
-            # The first component of the path is the base name of the
-            # environment
-            path_info = environ.get('PATH_INFO', '').lstrip('/').split('/')
-            env_name = path_info.pop(0)
+    
+    env = env_error = None
+    try:
+        env = bootstrap.open_environment(environ, start_response)
+    except RequestDone:
+        return []
+    except EnvironmentError:
+        raise
+    except Exception, e:
+        env_error = e
+    else:
+        try:
+            if env.base_url_for_redirect:
+                environ['trac.base_url'] = env.base_url
+    
+            # Web front-end type and version information
+            if not hasattr(env, 'webfrontend'):
+                mod_wsgi_version = environ.get('mod_wsgi.version')
+                if mod_wsgi_version:
+                    mod_wsgi_version = (
+                            "%s (WSGIProcessGroup %s WSGIApplicationGroup %s)" %
+                            ('.'.join([str(x) for x in mod_wsgi_version]),
+                             environ.get('mod_wsgi.process_group'),
+                             environ.get('mod_wsgi.application_group') or
+                             '%{GLOBAL}'))
+                    environ.update({
+                        'trac.web.frontend': 'mod_wsgi',
+                        'trac.web.version': mod_wsgi_version})
+                env.webfrontend = environ.get('trac.web.frontend')
+                if env.webfrontend:
+                    env.systeminfo.append((env.webfrontend,
+                                           environ['trac.web.version']))
+        except Exception, e:
+            env_error = e
 
-            if not env_name:
-                # No specific environment requested, so render an environment
-                # index page
-                send_project_index(environ, start_response, env_parent_dir,
-                                   env_paths)
-                return []
-
-            errmsg = None
-
-            # To make the matching patterns of request handlers work, we append
-            # the environment name to the `SCRIPT_NAME` variable, and keep only
-            # the remaining path in the `PATH_INFO` variable.
-            script_name = environ.get('SCRIPT_NAME', '')
-            try:
-                script_name = unicode(script_name, 'utf-8')
-                # (as Href expects unicode parameters)
-                environ['SCRIPT_NAME'] = Href(script_name)(env_name)
-                environ['PATH_INFO'] = '/' + '/'.join(path_info)
-
-                if env_parent_dir:
-                    env_path = os.path.join(env_parent_dir, env_name)
-                else:
-                    env_path = get_environments(environ).get(env_name)
-
-                if not env_path or not os.path.isdir(env_path):
-                    errmsg = 'Environment not found'
-            except UnicodeDecodeError:
-                errmsg = 'Invalid URL encoding (was %r)' % script_name
-
-            if errmsg:
-                start_response('404 Not Found',
-                               [('Content-Type', 'text/plain'),
-                                ('Content-Length', str(len(errmsg)))])
-                return [errmsg]
-
-    if not env_path:
-        raise EnvironmentError('The environment options "TRAC_ENV" or '
-                               '"TRAC_ENV_PARENT_DIR" or the mod_python '
-                               'options "TracEnv" or "TracEnvParentDir" are '
-                               'missing. Trac requires one of these options '
-                               'to locate the Trac environment(s).')
     run_once = environ['wsgi.run_once']
 
-    env = env_error = None
-    global_env = None
-    try:
-        from trac.hooks import environment_factory
-        global_env = open_environment(env_path, use_cache=not run_once)
-        factory = environment_factory(global_env)
-        factory_env = factory().open_environment(environ, env_path, global_env, use_cache=not run_once) if factory \
-                        else None
-        env = factory_env if factory_env else global_env
-        if env.base_url_for_redirect:
-            environ['trac.base_url'] = env.base_url
-
-        # Web front-end type and version information
-        if not hasattr(env, 'webfrontend'):
-            mod_wsgi_version = environ.get('mod_wsgi.version')
-            if mod_wsgi_version:
-                mod_wsgi_version = (
-                        "%s (WSGIProcessGroup %s WSGIApplicationGroup %s)" %
-                        ('.'.join([str(x) for x in mod_wsgi_version]),
-                         environ.get('mod_wsgi.process_group'),
-                         environ.get('mod_wsgi.application_group') or
-                         '%{GLOBAL}'))
-                environ.update({
-                    'trac.web.frontend': 'mod_wsgi',
-                    'trac.web.version': mod_wsgi_version})
-            env.webfrontend = environ.get('trac.web.frontend')
-            if env.webfrontend:
-                env.systeminfo.append((env.webfrontend,
-                                       environ['trac.web.version']))
-    except Exception, e:
-        env_error = e
-
-    from trac.hooks import request_factory
-    factory = None
-    try:
-        factory = request_factory(global_env)
-    except AttributeError:
-        pass
-    req = factory().create_request(env, environ, start_response) if factory \
-            else RequestWithSession(environ, start_response)
+    req = bootstrap.create_request(env, environ, start_response)
     translation.make_activable(lambda: req.locale, env.path if env else None)
     try:
         return _dispatch_request(req, env, env_error)