/lib/galaxy/webapps/community/buildapp.py
https://bitbucket.org/cistrome/cistrome-harvard/ · Python · 200 lines · 145 code · 11 blank · 44 comment · 26 complexity · 13880a16e1a90771fb2e772cfca652d7 MD5 · raw file
- """
- Provides factory methods to assemble the Galaxy web application
- """
- import logging, atexit, os, os.path, sys, config
- from inspect import isclass
- from paste.request import parse_formvars
- from paste.util import import_string
- from paste import httpexceptions
- from paste.deploy.converters import asbool
- import pkg_resources
- import galaxy.webapps.community.model
- import galaxy.webapps.community.model.mapping
- import galaxy.web.framework
- from galaxy.webapps.community.framework.middleware import hg
- log = logging.getLogger( __name__ )
- def add_ui_controllers( webapp, app ):
- """
- Search for controllers in the 'galaxy.webapps.controllers' module and add
- them to the webapp.
- """
- from galaxy.web.base.controller import BaseUIController
- from galaxy.web.base.controller import ControllerUnavailable
- import galaxy.webapps.community.controllers
- controller_dir = galaxy.webapps.community.controllers.__path__[0]
- for fname in os.listdir( controller_dir ):
- if not fname.startswith( "_" ) and fname.endswith( ".py" ):
- name = fname[:-3]
- module_name = "galaxy.webapps.community.controllers." + name
- module = __import__( module_name )
- for comp in module_name.split( "." )[1:]:
- module = getattr( module, comp )
- # Look for a controller inside the modules
- for key in dir( module ):
- T = getattr( module, key )
- if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ):
- webapp.add_ui_controller( name, T( app ) )
- import galaxy.web.controllers
- controller_dir = galaxy.web.controllers.__path__[0]
- for fname in os.listdir( controller_dir ):
- # TODO: fix this if we decide to use, we don't need to inspect all controllers...
- if fname.startswith( 'user' ) and fname.endswith( ".py" ):
- name = fname[:-3]
- module_name = "galaxy.web.controllers." + name
- module = __import__( module_name )
- for comp in module_name.split( "." )[1:]:
- module = getattr( module, comp )
- # Look for a controller inside the modules
- for key in dir( module ):
- T = getattr( module, key )
- if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ):
- webapp.add_ui_controller( name, T( app ) )
- def app_factory( global_conf, **kwargs ):
- """Return a wsgi application serving the root object"""
- # Create the Galaxy tool shed application unless passed in
- if 'app' in kwargs:
- app = kwargs.pop( 'app' )
- else:
- try:
- from galaxy.webapps.community.app import UniverseApplication
- app = UniverseApplication( global_conf=global_conf, **kwargs )
- except:
- import traceback, sys
- traceback.print_exc()
- sys.exit( 1 )
- atexit.register( app.shutdown )
- # Create the universe WSGI application
- webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxycommunitysession' )
- add_ui_controllers( webapp, app )
- webapp.add_route( '/:controller/:action', action='index' )
- webapp.add_route( '/:action', controller='repository', action='index' )
- webapp.add_route( '/repos/*path_info', controller='hg', action='handle_request', path_info='/' )
- webapp.finalize_config()
- # Wrap the webapp in some useful middleware
- if kwargs.get( 'middleware', True ):
- webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
- if kwargs.get( 'static_enabled', True ):
- webapp = wrap_in_static( webapp, global_conf, **kwargs )
- # Close any pooled database connections before forking
- try:
- galaxy.webapps.community.model.mapping.metadata.engine.connection_provider._pool.dispose()
- except:
- pass
- # Return
- return webapp
- def wrap_in_middleware( app, global_conf, **local_conf ):
- """Based on the configuration wrap `app` in a set of common and useful middleware."""
- # Merge the global and local configurations
- conf = global_conf.copy()
- conf.update( local_conf )
- debug = asbool( conf.get( 'debug', False ) )
- # First put into place httpexceptions, which must be most closely
- # wrapped around the application (it can interact poorly with
- # other middleware):
- app = httpexceptions.make_middleware( app, conf )
- log.debug( "Enabling 'httpexceptions' middleware" )
- # The recursive middleware allows for including requests in other
- # requests or forwarding of requests, all on the server side.
- if asbool(conf.get('use_recursive', True)):
- from paste import recursive
- app = recursive.RecursiveMiddleware( app, conf )
- log.debug( "Enabling 'recursive' middleware" )
- # Various debug middleware that can only be turned on if the debug
- # flag is set, either because they are insecure or greatly hurt
- # performance
- if debug:
- # Middleware to check for WSGI compliance
- if asbool( conf.get( 'use_lint', True ) ):
- from paste import lint
- app = lint.make_middleware( app, conf )
- log.debug( "Enabling 'lint' middleware" )
- # Middleware to run the python profiler on each request
- if asbool( conf.get( 'use_profile', False ) ):
- import profile
- app = profile.ProfileMiddleware( app, conf )
- log.debug( "Enabling 'profile' middleware" )
- # Middleware that intercepts print statements and shows them on the
- # returned page
- if asbool( conf.get( 'use_printdebug', True ) ):
- from paste.debug import prints
- app = prints.PrintDebugMiddleware( app, conf )
- log.debug( "Enabling 'print debug' middleware" )
- if debug and asbool( conf.get( 'use_interactive', False ) ):
- # Interactive exception debugging, scary dangerous if publicly
- # accessible, if not enabled we'll use the regular error printing
- # middleware.
- pkg_resources.require( "WebError" )
- from weberror import evalexception
- app = evalexception.EvalException( app, conf,
- templating_formatters=build_template_error_formatters() )
- log.debug( "Enabling 'eval exceptions' middleware" )
- else:
- # Not in interactive debug mode, just use the regular error middleware
- from paste.exceptions import errormiddleware
- app = errormiddleware.ErrorMiddleware( app, conf )
- log.debug( "Enabling 'error' middleware" )
- # Transaction logging (apache access.log style)
- if asbool( conf.get( 'use_translogger', True ) ):
- from paste.translogger import TransLogger
- app = TransLogger( app )
- log.debug( "Enabling 'trans logger' middleware" )
- # Config middleware just stores the paste config along with the request,
- # not sure we need this but useful
- from paste.deploy.config import ConfigMiddleware
- app = ConfigMiddleware( app, conf )
- log.debug( "Enabling 'config' middleware" )
- # X-Forwarded-Host handling
- from galaxy.web.framework.middleware.xforwardedhost import XForwardedHostMiddleware
- app = XForwardedHostMiddleware( app )
- log.debug( "Enabling 'x-forwarded-host' middleware" )
- app = hg.Hg( app, conf )
- log.debug( "Enabling hg middleware" )
- return app
-
- def wrap_in_static( app, global_conf, **local_conf ):
- from paste.urlmap import URLMap
- from galaxy.web.framework.middleware.static import CacheableStaticURLParser as Static
- urlmap = URLMap()
- # Merge the global and local configurations
- conf = global_conf.copy()
- conf.update(local_conf)
- # Get cache time in seconds
- cache_time = conf.get( "static_cache_time", None )
- if cache_time is not None:
- cache_time = int( cache_time )
- # Send to dynamic app by default
- urlmap["/"] = app
- # Define static mappings from config
- urlmap["/static"] = Static( conf.get( "static_dir" ), cache_time )
- urlmap["/images"] = Static( conf.get( "static_images_dir" ), cache_time )
- urlmap["/static/scripts"] = Static( conf.get( "static_scripts_dir" ), cache_time )
- urlmap["/static/style"] = Static( conf.get( "static_style_dir" ), cache_time )
- urlmap["/favicon.ico"] = Static( conf.get( "static_favicon_dir" ), cache_time )
- # URL mapper becomes the root webapp
- return urlmap
-
- def build_template_error_formatters():
- """
- Build a list of template error formatters for WebError. When an error
- occurs, WebError pass the exception to each function in this list until
- one returns a value, which will be displayed on the error page.
- """
- formatters = []
- # Formatter for mako
- import mako.exceptions
- def mako_html_data( exc_value ):
- if isinstance( exc_value, ( mako.exceptions.CompileException, mako.exceptions.SyntaxException ) ):
- return mako.exceptions.html_error_template().render( full=False, css=False )
- if isinstance( exc_value, AttributeError ) and exc_value.args[0].startswith( "'Undefined' object has no attribute" ):
- return mako.exceptions.html_error_template().render( full=False, css=False )
- formatters.append( mako_html_data )
- return formatters