Has anyone considered how to support multiple apps sharing the same
templates? This would make it easier to combine multiple apps and get the
same "look and feel". I have seen this requested several times on the TG
MLs.
Could we make the templates directory a configurable option in the config
file, which defaults to the standard templates directory? I haven't thought
the full implications of this through, but it seems like a (relatively)
simple option that might get us moving towards achieving this goal.
Any major problems with this strategy?
Kevin Horn
On 5/24/07, Alberto Valverde <[EMAIL PROTECTED]> wrote:
>
>
>
> On May 22, 2007, at 11:07 PM, Alberto Valverde wrote:
>
> >
> >
> > On May 21, 2007, at 10:53 PM, Ian Charnas wrote:
> >
> >>
> >> So are we still on for a TurboGears sprint this upcoming saturday?
> >> How do we do this? Do we all jump on IRC at a certain time and
> >> decide
> >> what to do?
> >
> > It'll be probably be good to open up a page in the docs.tg.org wiki
> > to make some planning...
> >
> > I'll be in to work on a new test infrastructure to eventually port
> > all failing controller tests to put TG back in the "green" zone. The
> > other big task needing work is poring the config module to CP3's new
> > config system . Some coordination between my work and the "config
> > team" is needed since a pre-requisite to my part is to have a TG app
> > nicely wrapped in a WSGI app (possibly with a paste.app_factory entry-
> > point implemented) since I'm planning to use paste fixture for the
> > testing.
> >
> > Some notes + brainstorming:
> >
> > CP3 uses the Application object to create the mentioned WSGI app
> > which receives the app's config as a constructor's parameter so we'll
> > have to agree on how we create initialize this object. Maybe
> > something like this:
> >
> > - add a new wsgiapp.py module inside quickstarted apps which
> > implements the paste.app_factory entrypoint to return a TG/CP3 app.
> > This module uses some helper functions inside TG's startup.py (or
> > even a TGWSGIApp Application subclass) to initialize and stack TG's
> > specific middleware (none ATM, expect EvalException, but we need to
> > leave room for future growth).
> >
> > - This entrypoint could be called by PasteScript's paster passing a
> > paste.deploy config file which would override config parameters
> > defined in well knownt app.cfg et al. tg-admin should grow a new
> > "serve" commad (which delegates to paster serve) which loads a TG app
> > with no paste.deploy config and mounts it at /. This new "serve "
> > commands deprecates good 'ol start-myapp.py (which can be left as a
> > backwards compatibility artifact which simply delegates to tg-admin
> > serve).
> >
> > A quick mental topological sort leaves tasks in this way:
> >
> > 1) wrap TG apps with CP3's Application object
> > 1.5) (at this point I can start migrating the testing framework)
> > 2) this Application object receives an app config dict so... adapt
> > current config.py so it can load TG' config and pass it to the
> > Application constructor. The "config" team could work on a rewrite of
> > the config module so it produces a properly formatted config dict to
> > feed to Appliaction)
> > 3) implement the paste.app_factory entry point which can receive a
> > *possible* paste.deploy config or a dummy one that points to app.cfg
> > and returns this WSGI app object. The possible paste.deploy config
> > should override values in app.cfg if present.
> > 4) implement the tg-admin "serve" command
> > 5) glue all this together so "tg-admin serve my.config" launches a TG
> > app and start-myapp delegates to this
> >
> > Sorry for my poor communication of this ideas.... I'm speaking from
> > memory and it has been months since other work has displaced this
> > task from the foreground of my badly multi-tasking brain ;)
>
>
> Yesterday I comitted some changes on the trunk implementing these
> ideas. Some comments:
>
> - turbogears.config is now a paste.config.DispatchingConfig which
> provides conetxtual config for each TG app mounted in the same
> process. It preserves the original inteface (update_config, update,
> get) plus, being a proxy to a dict, has now other useful methods like
> items, __getitem__, __setitem__, etc ("items" will be specially
> useful in view.load_engines to dump all available template engine
> options to each engines, no need to "cherry-pick" them one by one.
> It's structure is something like this:
> {"/": {config options for the current app, this key is accessible at
> cherrypy.request.config during a request},
> "tg_widgets": {tools.staticdir.on: True, tools.staticdir.dir:
> "some_dir"},
> ....}
>
> The preferred method of accessing app configuration is through
> turbogears.config which proxies to the dict that was merged with the
> apps config at the app factory. cherrypy will use each path's key
> when calclating which tools to apply depending on the path.
>
> - The WSGI app is built inside the users app at
> myapp.wsgiapp:WSGIApp.app_factory.
>
> This is the paste.app_factory entry point. Most work is done in the
> superclass (defined in turbogears.wsgi) but, being the final subclass
> available inside the users app it allows for easy customization, eg:
> * __call__ can be overriden to execute per-request actions, branch to
> other wsgi apps, etc... This function has the WSGI app signature
> (environ, start_response) so the full flexibility of WSGI is
> available at this point.
> * app_factory can be extended to further wrap the app in middleware
> between the resuting TG app (and all its middleware) and the server
>
> def app_factory(self, global_conf, root=None, full_stack=None,
> **app_conf):
> app = super(...).app_factory(....)
> app = MyMiddleWare(app, ...)
> .....
> return app
>
> Note that middleware stacked here will be outside TG's context
>
> * __init__ can be overriden to stack middleware below the TG app.
> This middleware will be inside the context of the TG app:
>
> def __init__(self, root=None):
> super(....).__init__(root)
> self.wsgiapp = MyMiddleware(self.wsgiapp, ....)
>
> Note that this middleware can also be declared in the CP3 config file
>
> - There are some architectural changes needed to allow for multiple
> apps per process:
>
> * We're making heavy use of module globals for customization
> (view.variable_providers, view.loadBases, scheduler, database.engine,
> etc...) This should be modified because these globals will be shared
> by all instances of TG apps used in the same process, extension
> authors should pay special attention to this...
> The solution I've comed up with is to provide a proxy at
> turbogears.globals which proxies to app.globals (a globals object
> bound to the WSGI app that wraps the root controller). This way all
> these globals will be in the context of the WSGI app that configured
> them during a request. I've implemented view.engines this way (so
> each app can have it's own kid.defaultoutput, etc...) but others
> still need to be ported/rewritten (database.engine, scheduler, etc)
>
> - Since the app_factory ep is implemented, paster can already be used
> to launch a TG app. I've made the changes needed to the quickstarted
> template so you can try it out like this:
>
> $ paster serve depoly_cfg.ini
>
> Which should have the same effect as calling start-myapp.py (I've
> rewritten start_turbogears so 1.0 startup scripts remain compatible).
> start-myapp.py should be deprecated so all apps are loaded using the
> paste.deploy API. Since the minimal deploy ini config file is so
> simple, "tg-admin serve" could emulate what it does when no
> deployment config is specified, so when you run "tg-admin serve"
> inside a projects egg it should start up the app automatically. If a
> deployment config is passed as a parameter, it should use that
> instead. Some cool things you can already do with this:
>
> [DEFAULT]
> [server:main]
> use= egg:PasteScript#cherrypy
> host = 0.0.0.0
> port = 8080
>
> [composite:main]
> use = egg:Paste#urlmap
> / = app1
> /app2 = app2
>
> [app:app1]
> use = egg:TestApp
> app_id = app1
> tg.config_file = %(here)s/dev.cfg
>
>
> [app:app2]
> use = egg:TestApp
> tg.config_file = %(here)s/dev.cfg
> app_id = app2
> kid.encoding = iso-8859-1
> kid.outputformat= xhtml
>
> This will mount the same TG app at / and /app2 but with different
> configuration settings (they could even use different dev.cfg and
> dev2.cfg) and serve it with CP3's wsgi server (swap it with Paste's
> if you feel inclined to for didactical purposes)
>
> Please note that multiple apps per process is still broken since we
> use so many module globals. I haven't tested it yet but, for example,
> I believe both apps would share the same db engine... this needs to
> be sorted out.
>
> Some low hanging fruit we need need to address:
>
> * rewrite view.load_engines so it all template plugin confg options
> can be used. Maybe even replace the whole view module and implement
> it as a class we can instantiate and bind to turbogears.globals so
> each app has it's own configured set of engines. This is implemented
> in TW as the EngineManager... maybe we can take ideas from there, or,
> better still, factor it out into an independent egg both TW and TG
> can share.
> * Move the scheduler to turbogears.globals, so each app has it's own
> scheduler
> * Ditto with database.engine
> * more I'm failing to recall....
>
> Some more complex stuff:
>
> * Move all module globals: view.variable_providers,
> turbogears.call_on_startup, etc so they're bound to each app. This
> will require a change to the extensions API to work properly,
> however, a proxy can be left at the original location for backwards
> compatibility. This allows for a smooth degradation: non conforming
> extension will still work in a single app per process scenario, but
> will break when multiple TG apps cohabitate the same process.... this
> will put some pressure on extension authors to upgrade them ;)
> * Write the new testutils using paste fixture to port all TG
> controller tests.
> * more I'm failing to recall....
>
> Well, gotta run now... comments welcomed :)
>
> Alberto
>
> PS: Looks like Saturday's sprint is going to be lots of fun! :)
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"TurboGears Trunk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/turbogears-trunk?hl=en
-~----------~----~----~----~------~----~------~--~---