Changeset 4986

Show
Ignore:
Timestamp:
07/16/08 18:32:20 (1 month ago)
Author:
mramm
Message:

Updating the config object in tg to have methods for setting up default middleware stack and a load_environment function.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/tg/config.py

    r4876 r4986  
    11"""Simple AppSetup helper class""" 
     2import os 
     3from pylons.i18n import ugettext 
     4from genshi.filters import Translator 
     5from tg import defaults 
     6 
    27from pylons import config 
     8from beaker.middleware import SessionMiddleware, CacheMiddleware 
     9from paste.cascade import Cascade 
     10from paste.registry import RegistryManager 
     11from paste.urlparser import StaticURLParser 
     12from paste.deploy.converters import asbool 
     13from pylons import config 
     14from pylons.middleware import ErrorHandler, StaticJavascripts, \ 
     15    StatusCodeRedirect 
     16from pylons.wsgiapp import PylonsApp 
     17from routes import Mapper 
     18from routes.middleware import RoutesMiddleware 
     19 
     20from tw.api import make_middleware as tw_middleware 
    321 
    422class Bunch(dict): 
     
    2846    that is NESSISARY for proper application function.   
    2947    Deployment specific configuration information should go in  
    30     the config files (eg: development.ini or production.ini."  
     48    the config files (eg: development.ini or production.ini)"  
    3149    """ 
    3250     
     
    3452        self.stand_alone = True 
    3553        self.default_renderer = 'genshi' 
    36         self.auth_backend = None  
    37      
    38     pass 
     54        self.auth_backend = None 
     55        self.serve_static = True 
     56     
     57    def setup_paths(self): 
     58        root = os.path.dirname(os.path.abspath( 
     59                self.package.__file__)) 
     60        self.paths = dict(root=root, 
     61                     controllers=os.path.join(root, 'controllers'), 
     62                     static_files=os.path.join(root, 'public'), 
     63                     templates=[os.path.join(root, 'templates')]) 
     64                      
     65    def init_config(self, global_conf, app_conf): 
     66        # Initialize config with the basic options 
     67        config.init_app(global_conf, app_conf,  
     68                        package=self.package.__name__, 
     69                        paths=self.paths) 
     70                         
     71    def setup_routes(self): 
     72        # This setups up a set of default route that enables a standard 
     73        # TG2 style object dispatch.   Fell free to overide it with 
     74        # custom routes.   
     75        map = Mapper(directory=config['pylons.paths']['controllers'], 
     76                    always_scan=config['debug']) 
     77 
     78        # Setup a default route for the error controller: 
     79        map.connect('error/:action/:id', controller='error') 
     80 
     81        ## Replace the next line with your overides.   Overides should generally come 
     82        ## bevore the default route defined below 
     83        # map.connect('overide/url/here', controller='mycontrller', action='send_stuff') 
     84 
     85        # This route connects your root controller, it should be after 
     86        # more specific routes since the wildcard will pick up everything... 
     87        map.connect('*url', controller='root', action='routes_placeholder') 
     88         
     89        config['routes.map'] = map 
     90     
     91    def setup_helpers_and_globals(self): 
     92        config['pylons.app_globals'] = self.package.lib.app_globals.Globals() 
     93        config['pylons.h'] = self.package.lib.helpers 
     94     
     95    def setup_sa_auth_backend(): 
     96        defaults = {'user_class':self.model.User,  
     97                              'group_class':self.model.Group,  
     98                              'permission_class':self.model.Permission, 
     99                              'users_table':'tg_user', 
     100                              'groups_table':'tg_group', 
     101                              'permissions_table':'tg_permission', 
     102                              'password_encryption_method':'sha1', 
     103                              'form_plugin': None 
     104                      } 
     105        if config['sa_auth']: 
     106            config['sa_auth'] = defaults.update(config['sa_auth']) 
     107        if not config['sa_auth']: 
     108            config['sa_auth'] = defaults 
     109     
     110    def setup_mako_renderer(self): 
     111        # Create the Mako TemplateLookup, with the default auto-escaping 
     112        from mako.lookup import TemplateLookup 
     113        from tg.render import render_mako 
     114 
     115        config['pylons.app_globals'].mako_lookup = TemplateLookup( 
     116            directories=self.paths['templates'], 
     117            module_directory=os.path.join(app_conf['cache_dir'], 'templates'), 
     118            input_encoding='utf-8', output_encoding='utf-8', 
     119            imports=['from webhelpers.html import escape'], 
     120            default_filters=['escape']) 
     121        config['pylons.app_globals'].renderer_functions = render_mako 
     122         
     123    def setup_genshi_renderer(self): 
     124        # Create the Genshi TemplateLoader 
     125        from genshi.template import TemplateLoader 
     126        from tg.render import render_genshi 
     127 
     128        def template_loaded(template): 
     129            "Plug-in our i18n function to Genshi." 
     130            genshi.template.filters.insert(0, Translator(ugettext)) 
     131 
     132        config['pylons.app_globals'].genshi_loader = TemplateLoader( 
     133            self.paths['templates'], auto_reload=True) 
     134 
     135        config['pylons.app_globals'].renderer_functions = render_genshi 
     136     
     137    def setup_jinja_renderer(self): 
     138        # Create the Jinja Environment 
     139        from jinja import ChoiceLoader, Environment, FileSystemLoader 
     140        from tg.render import render_jinja 
     141 
     142        config['pylons.app_globals'].jinja_env = Environment(loader=ChoiceLoader( 
     143                [FileSystemLoader(path) for path in self.paths['templates']])) 
     144        # Jinja's unable to request c's attributes without strict_c 
     145        config['pylons.strict_c'] = True 
     146 
     147        config['pylons.app_globals'].renderer_functionsloa = render_jinja 
     148     
     149    def setup_default_renderer(self): 
     150        #This is specific to buffet, will not be needed later 
     151        config['buffet.template_engines'].pop() 
     152        template_location = '%s.templates' %self.package.__name__ 
     153        config.add_template_engine(self.default_renderer,  
     154                                   template_location,  {}) 
     155     
     156    def setup_sqlalchemy(self): 
     157        # Setup SQLAlchemy database engine 
     158        from sqlalchemy import engine_from_config 
     159        engine = engine_from_config(config, 'sqlalchemy.') 
     160        config['pylons.app_globals'].sa_engine = engine 
     161        # Pass the engine to initmodel, to be able to introspect tables 
     162        self.package.model.init_model(engine) 
     163        self.package.model.DBSession.configure(bind=engine) 
     164        self.package.model.metadata.bind = engine 
     165         
     166    def make_load_environment(self): 
     167        """Returns a load_environment function  
     168         
     169        The returned load_environment function can be called to configure the  
     170        TurboGears runtime environment for this particular application.  You  
     171        can do this dynamically with multiple nested TG applications if  
     172        nessisary.""" 
     173         
     174        def load_environment(global_conf, app_conf): 
     175            """Configure the Pylons environment via the ``pylons.config`` 
     176            object 
     177            """ 
     178 
     179            self.setup_paths() 
     180            self.init_config(global_conf, app_conf) 
     181            self.setup_routes() 
     182            self.setup_helpers_and_globals() 
     183            if self.auth_backend == "sqlalchemy":  
     184                self.setup_sa_auth_backend 
     185 
     186            if 'mako' in self.renderers: 
     187                self.setup_mako_renderer() 
     188 
     189            if 'genshi' in self.renderers: 
     190                self.setup_genshi_renderer() 
     191             
     192            if 'jinja' in self.renderers: 
     193                self.setup_jinja_renderer() 
     194 
     195            self.setup_default_renderer() 
     196             
     197            if self.use_sqlalchemy: 
     198                self.setup_sqlalchemy() 
     199 
     200        return load_environment 
     201 
     202 
     203    def add_error_middleware(self, global_conf, app): 
     204        # Handle Python exceptions 
     205        app = ErrorHandler(app, global_conf, **config['pylons.errorware']) 
     206 
     207        # Display error documents for 401, 403, 404 status codes (and 
     208        # 500 when debug is disabled) 
     209        if asbool(config['debug']): 
     210            app = StatusCodeRedirect(app) 
     211        else: 
     212            app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) 
     213        return app 
     214 
     215    def add_auth_middleware(self, app): 
     216        # configure identity Middleware 
     217        from tg.ext.repoze.who.middleware import make_who_middleware 
     218 
     219        auth = self.sa_auth 
     220 
     221        app = make_who_middleware(app, config, auth.user,  
     222                                  auth.user_criterion,  
     223                                  auth.user_id_column,  
     224                                  auth.dbsession, 
     225                                  ) 
     226        return app 
     227     
     228    def add_core_middleware(self, app):     
     229        app = RoutesMiddleware(app, config['routes.map']) 
     230        app = SessionMiddleware(app, config) 
     231        app = CacheMiddleware(app, config) 
     232        return app 
     233     
     234    def add_tosca_middleware(self, app): 
     235        app = tw_middleware(app, { 
     236            'toscawidgets.framework.default_view':  
     237            self.default_renderer, 
     238            'toscawidgets.middleware.inject_resources': True, 
     239            }) 
     240        return app 
     241     
     242    def add_static_file_middleware(self, app): 
     243        javascripts_app = StaticJavascripts() 
     244        static_app = StaticURLParser(config['pylons.paths']['static_files']) 
     245        app = Cascade([static_app, javascripts_app, app]) 
     246        return app 
     247 
     248    def setup_tg_wsgi_app(self, load_environment): 
     249        """Create a base TG app, with all the standard middleware 
     250 
     251        ``load_environment`` 
     252            A required callable, which sets up the basic application 
     253            evironment. 
     254        ``setup_vars`` 
     255            A dictionary any special values nessisary for setting up 
     256            the base wsgi app. 
     257        """                   
     258 
     259        def make_base_app(global_conf, wrap_app=None, full_stack=True, **app_conf): 
     260            """Create a tg WSGI application and return it 
     261 
     262            ``global_conf`` 
     263                The inherited configuration for this application. Normally from 
     264                the [DEFAULT] section of the Paste ini file. 
     265 
     266            ``full_stack`` 
     267                Whether or not this application provides a full WSGI stack (by 
     268                default, meaning it handles its own exceptions and errors). 
     269                Disable full_stack when this application is "managed" by 
     270                another WSGI middleware. 
     271 
     272            ``app_conf`` 
     273                The application's local configuration. Normally specified in the 
     274                [app:<name>] section of the Paste ini file (where <name> 
     275                defaults to main). 
     276            """ 
     277            # Configure the Pylons environment 
     278            load_environment(global_conf, app_conf) 
     279            app = PylonsApp() 
     280            if wrap_app:  
     281                wrap_app(app) 
     282            app = self.add_core_middleware(app) 
     283            app = self.add_tosca_middleware(app) 
     284 
     285            if self.auth_backend == "sqlalchemy": 
     286                app = self.add_auth_middleware(app) 
     287 
     288            if asbool(full_stack): 
     289                # This should nevery be true for internal nested apps 
     290                app = self.add_error_middleware(global_conf, app) 
     291 
     292            # Establish the Registry for this application 
     293            app = RegistryManager(app) 
     294 
     295            # Static files (If running in production, and Apache or another  
     296            # web server is serving static files)  
     297            if self.serve_static:  
     298                app = self.add_static_file_middleware(app) 
     299            return app 
     300 
     301        return make_base_app 
  • trunk/tg/defaults.py

    r4453 r4986  
    1010def make_default_route_map(): 
    1111    """Create, configure and return the routes Mapper""" 
     12     
     13    import warnings 
     14    warnings.warn("tg.defaults is depricated overide setup_routes on base_config object instead") 
     15     
    1216    map = Mapper(directory=config['pylons.paths']['controllers'], 
    1317                always_scan=config['debug']) 
  • trunk/tg/environment.py

    r4918 r4986  
    66from tg import defaults 
    77 
     8import warnings 
     9 
    810 
    911def make_load_environment(base_config): 
     12    warnings.warn("tg.environment is depricated use make_load_environment on the base_config object instead") 
    1013 
    1114    def load_environment(global_conf, app_conf): 
     
    4346                                  'permissions_table':'tg_permission', 
    4447                                  'password_encryption_method':'sha1', 
     48                                  'form_plugin': None 
    4549                          } 
    4650     
  • trunk/tg/middleware.py

    r4899 r4986  
    2323        the base wsgi app. 
    2424    """                   
     25     
     26    warnings.warn("tg.middleware is depricated use make_load_environment on the base_config object instead") 
    2527     
    2628    def make_base_app(global_conf, wrap_app=None, full_stack=True, **app_conf):