PageRenderTime 67ms CodeModel.GetById 23ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 1ms

/lib/galaxy/webapps/reports/buildapp.py

https://bitbucket.org/cistrome/cistrome-harvard/
Python | 178 lines | 148 code | 11 blank | 19 comment | 6 complexity | 3bb6782032952e7f29a921e8f2f5767c MD5 | raw file
  1"""
  2Provides factory methods to assemble the Galaxy web application
  3"""
  4
  5import logging, atexit
  6import os, os.path, sys
  7
  8from inspect import isclass
  9
 10from paste.request import parse_formvars
 11from paste.util import import_string
 12from paste import httpexceptions
 13
 14import pkg_resources
 15
 16from galaxy.util import asbool
 17
 18import config
 19import galaxy.model
 20import galaxy.model.mapping
 21import galaxy.web.framework
 22
 23log = logging.getLogger( __name__ )
 24
 25class ReportsWebApplication( galaxy.web.framework.WebApplication ):
 26    pass
 27
 28def add_ui_controllers( webapp, app ):
 29    """
 30    Search for controllers in the 'galaxy.webapps.controllers' module and add
 31    them to the webapp.
 32    """
 33    from galaxy.web.base.controller import BaseUIController
 34    from galaxy.web.base.controller import ControllerUnavailable
 35    import galaxy.webapps.reports.controllers
 36    controller_dir = galaxy.webapps.reports.controllers.__path__[0]
 37    for fname in os.listdir( controller_dir ):
 38        if not fname.startswith( "_" ) and fname.endswith( ".py" ):
 39            name = fname[:-3]
 40            module_name = "galaxy.webapps.reports.controllers." + name
 41            module = __import__( module_name )
 42            for comp in module_name.split( "." )[1:]:
 43                module = getattr( module, comp )
 44            # Look for a controller inside the modules
 45            for key in dir( module ):
 46                T = getattr( module, key )
 47                if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ):
 48                    webapp.add_ui_controller( name, T( app ) )
 49
 50def app_factory( global_conf, **kwargs ):
 51    """Return a wsgi application serving the root object"""
 52    # Create the Galaxy application unless passed in
 53    if 'app' in kwargs:
 54        app = kwargs.pop( 'app' )
 55    else:
 56        from galaxy.webapps.reports.app import UniverseApplication
 57        app = UniverseApplication( global_conf = global_conf, **kwargs )
 58    atexit.register( app.shutdown )
 59    # Create the universe WSGI application
 60    webapp = ReportsWebApplication( app, session_cookie='galaxyreportssession', name="reports" )
 61    add_ui_controllers( webapp, app )
 62    # These two routes handle our simple needs at the moment
 63    webapp.add_route( '/:controller/:action', controller="root", action='index' )
 64    webapp.add_route( '/:action', controller='root', action='index' )
 65    webapp.finalize_config()
 66    # Wrap the webapp in some useful middleware
 67    if kwargs.get( 'middleware', True ):
 68        webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
 69    if kwargs.get( 'static_enabled', True ):
 70        webapp = wrap_in_static( webapp, global_conf, **kwargs )
 71    # Close any pooled database connections before forking
 72    try:
 73        galaxy.model.mapping.metadata.engine.connection_provider._pool.dispose()
 74    except:
 75        pass
 76    # Return
 77    return webapp
 78
 79def wrap_in_middleware( app, global_conf, **local_conf ):
 80    """Based on the configuration wrap `app` in a set of common and useful middleware."""
 81    # Merge the global and local configurations
 82    conf = global_conf.copy()
 83    conf.update(local_conf)
 84    debug = asbool( conf.get( 'debug', False ) )
 85    # First put into place httpexceptions, which must be most closely
 86    # wrapped around the application (it can interact poorly with
 87    # other middleware):
 88    app = httpexceptions.make_middleware( app, conf )
 89    log.debug( "Enabling 'httpexceptions' middleware" )
 90    # The recursive middleware allows for including requests in other
 91    # requests or forwarding of requests, all on the server side.
 92    if asbool(conf.get('use_recursive', True)):
 93        from paste import recursive
 94        app = recursive.RecursiveMiddleware( app, conf )
 95        log.debug( "Enabling 'recursive' middleware" )
 96    # Various debug middleware that can only be turned on if the debug
 97    # flag is set, either because they are insecure or greatly hurt
 98    # performance
 99    if debug:
100        # Middleware to check for WSGI compliance
101        if asbool( conf.get( 'use_lint', True ) ):
102            from paste import lint
103            app = lint.make_middleware( app, conf )
104            log.debug( "Enabling 'lint' middleware" )
105        # Middleware to run the python profiler on each request
106        if asbool( conf.get( 'use_profile', False ) ):
107            import profile
108            app = profile.ProfileMiddleware( app, conf )
109            log.debug( "Enabling 'profile' middleware" )
110        # Middleware that intercepts print statements and shows them on the
111        # returned page
112        if asbool( conf.get( 'use_printdebug', True ) ):
113            from paste.debug import prints
114            app = prints.PrintDebugMiddleware( app, conf )
115            log.debug( "Enabling 'print debug' middleware" )
116    if debug and asbool( conf.get( 'use_interactive', False ) ):
117        # Interactive exception debugging, scary dangerous if publicly
118        # accessible, if not enabled we'll use the regular error printing
119        # middleware.
120        pkg_resources.require( "WebError" )
121        from weberror import evalexception
122        app = evalexception.EvalException( app, conf,
123                                           templating_formatters=build_template_error_formatters() )
124        log.debug( "Enabling 'eval exceptions' middleware" )
125    else:
126        # Not in interactive debug mode, just use the regular error middleware
127        from paste.exceptions import errormiddleware
128        app = errormiddleware.ErrorMiddleware( app, conf )
129        log.debug( "Enabling 'error' middleware" )
130    # Transaction logging (apache access.log style)
131    if asbool( conf.get( 'use_translogger', True ) ):
132        from paste.translogger import TransLogger
133        app = TransLogger( app )
134        log.debug( "Enabling 'trans logger' middleware" )
135    # X-Forwarded-Host handling
136    from galaxy.web.framework.middleware.xforwardedhost import XForwardedHostMiddleware
137    app = XForwardedHostMiddleware( app )
138    log.debug( "Enabling 'x-forwarded-host' middleware" )
139    return app
140
141def wrap_in_static( app, global_conf, **local_conf ):
142    from paste.urlmap import URLMap
143    from galaxy.web.framework.middleware.static import CacheableStaticURLParser as Static
144    urlmap = URLMap()
145    # Merge the global and local configurations
146    conf = global_conf.copy()
147    conf.update(local_conf)
148    # Get cache time in seconds
149    cache_time = conf.get( "static_cache_time", None )
150    if cache_time is not None:
151        cache_time = int( cache_time )
152    # Send to dynamic app by default
153    urlmap["/"] = app
154    # Define static mappings from config
155    urlmap["/static"] = Static( conf.get( "static_dir" ), cache_time )
156    urlmap["/images"] = Static( conf.get( "static_images_dir" ), cache_time )
157    urlmap["/static/scripts"] = Static( conf.get( "static_scripts_dir" ), cache_time )
158    urlmap["/static/style"] = Static( conf.get( "static_style_dir" ), cache_time )
159    urlmap["/favicon.ico"] = Static( conf.get( "static_favicon_dir" ), cache_time )
160    # URL mapper becomes the root webapp
161    return urlmap
162
163def build_template_error_formatters():
164    """
165    Build a list of template error formatters for WebError. When an error
166    occurs, WebError pass the exception to each function in this list until
167    one returns a value, which will be displayed on the error page.
168    """
169    formatters = []
170    # Formatter for mako
171    import mako.exceptions
172    def mako_html_data( exc_value ):
173        if isinstance( exc_value, ( mako.exceptions.CompileException, mako.exceptions.SyntaxException ) ):
174            return mako.exceptions.html_error_template().render( full=False, css=False )
175        if isinstance( exc_value, AttributeError ) and exc_value.args[0].startswith( "'Undefined' object has no attribute" ):
176            return mako.exceptions.html_error_template().render( full=False, css=False )
177    formatters.append( mako_html_data )
178    return formatters