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