[10:00] <albertov> In order to make TG apps fully WSGI compliant some architectural changes need to take place. Fortunately Paste already provides most of the building blocks we need (StackedObjectProxy to handle module globals, wsgi wrappers that make environ look less daunting, error handling middleware, mechanisms for easy deployment using a config file, etc.. [10:00] <albertov> To see which bits of TG 1.0 need work on look at the module globals. At the moment I can think of a few: [10:00] <albertov> turbogears.database.{metadata,session}, turbogears.config, etc.. [10:01] <albertov> This is because as soon as you have two TG apps in the same process, those two apps will be looking at the same objects which is normally not what we want. Fortunately Paste already provides tools to handle this. [10:02] <albertov> To sum up, what we/I have in mind for TG 2.0 is: [10:02] <albertov> 1) Make heavier use of Paste (specially paste.deploy) to provide the pieces we need to make TG apps easily deployable in any scenario. [10:03] <albertov> What we haven't decided yet and is open for discussion (as everything) is if we shall keep our current config style (using ConfigObj) along paste.deploy's or stick to paste.deploy only... [10:03] <albertov> This has a side effect of moving away from the CherryPy engine which is what we're using currently for config, dispatching and filtering [10:04] <albertov> The reason is that, although CP 3 has made a great progess towards WSGI-friendlyness, it's not yet there IMO. [10:04] <albertov> For example, CP3 apps cannot be used as opaque WSGI apps (mainly because of it's use of globals like cherrypy.config, cherrypy.tree, cherrypy.engine, etc... which where not designed for a CP app to be a small part of a bigger app.. [10:04] <fumanchu> um [10:04] <fumanchu> http://www.cherrypy.org/wiki/WSGI [10:05] <dowski> a_wsgi_app = cherrypy.tree.mount(YourAppRoot()) [10:05] <dowski> if i'm not mistaken [10:06] <albertov> That last part is important, I'm not saying you cannot mount several WSGI apps in the same process, being CP or non CP, but you cannot wrap several CP apps in paste.deploy app_factories and mount them via URLMapper in a Paste http server [10:06] <albertov> please correct me if I'm wrong, at leats from my experiemnts I didn't see an obvious way to avoid clashes between CP's globals... [10:06] <eleftherios> albertov, from what I gather TG 2.0 will look like Pylons quite much. Is this the case? [10:07] <albertov> eleftherios: that was a secret! shhhhh ;) [10:07] <dowski> albertov: fumanchu probaly has better info on this, but each CP3 application has its own config [10:07] <fumanchu> albertov, that may have been true for CP 2 but shouldn't be true for CP 3 [10:07] <fumanchu> I'll try to make an example for you [10:07] * godoy mumbles: now I understand why albertov fell in love with pylons... [10:08] <grayrest> are we using other bits of paste? paste.remote and whatnot? [10:08] <tazzzzz> eleftherios: the wsgi app construction will be similar to pylons, but other parts of the stack will likely look different [10:08] <godoy> I'd try touching the least things... i.e., keep ConfigObj and if we need, ditch it in 2.1. [10:08] <eleftherios> tazzzzz, I see [10:08] <albertov> I'll need to investigate more then... However, I might not have made my point clear: a CP app being part of a bigger WSGI app (not necesarily served by CP) *alonside* other CP apps... [10:08] <fumanchu> ...is no problem [10:09] <fumanchu> cf the diagram at the bottom of http://www.cherrypy.org/wiki/WSGI [10:09] <albertov> fumanchu: really? how does it prevent smashing globals? [10:10] <albertov> however, what I'm saying regarding CP3 is not yet final.. much discussion needs to take place at the trunk ML. In fact, my firt experiement monkey-patched cp.config, etc... with StackedObjectProxies.... [10:10] <fumanchu> we should take this to the ML [10:11] <albertov> well, I'll continue with my pre-written talk now... ;) [10:11] <fumanchu> :) [10:11] <godoy> fumanchu: post it now, as a reminder on the discussion. we can't miss that point. (I know you won't forget it...) [10:12] <fumanchu> ok
More discussion to follow. I just spent a man-year of work making CP 3 do all this and more and be beautiful at the same time, and I'll be damned if I let TG devolve back to preferring the ugliness of bare WSGI and Paste.
Robert Brewer System Architect Amor Ministries fuman...@amor.org
fumanchu wrote: > More discussion to follow. I just spent a man-year of work making CP 3 > do all this and more and be beautiful at the same time, and I'll be > damned if I let TG devolve back to preferring the ugliness of bare WSGI > and Paste.
Mmm... strong words.
I don't think anyone is suggesting bare WSGI and Paste for TurboGears. This isn't how WSGI or Paste is intended to be used.
Comparisons are perhaps a little difficult here, because the layers don't match up quite right:
Paste CherryPy Pylons TurboGears
That is, CherryPy works on a higher level than Paste, in places closer to a "real" framework like Pylons; similarly, TurboGears works on a level that includes a lot more functionality than Pylons. Paste and CherryPy are not addressing equivalent sets of features. And many of the things that TG 2.0 is looking for are quite possibly better drawn from Pylons than Paste -- in that there's ideas in Paste that are (intentionally) only half-baked, and Pylons more fully exposes them in a way that could also make sense for TurboGears.
And further, Paste itself is factored into three distinct pieces, most of which CherryPy includes in its one package; TG is free to cherrypick (sorry, pun not intended) from Paste's offerings:
* Paste Deploy, the configuration system * Paste core, the WSGI tools * Paste Script, the app server (also a file layout generator and other stuff)
The app server in Paste Script is merely there because I needed something, I'm not going to argue that it's a wonderful app server; I think CherryPy's is largely in the same position. The file layout stuff and other tools in Paste Script don't have equivalents in CherryPy, so there's no comparison to be made there.
So there's Paste Deploy (the configuration system) and Paste core (a bunch of WSGI tools).
If TurboGears uses Paste core's WSGI tools or not, it really doesn't much matter to me. There's lots of useful pieces in there, and I'm happy to point them out, but you could copy and rename those and tweak them as you wish and it would be perfectly fine. There's nothing singular about the implementations in Paste. The argument there is really about a framework that uses WSGI internally, and one that does not. Not everything should be squeezed into WSGI -- certainly I've seen things that seem odd or wrong to me (e.g., wsgiform). It would probably be easier to debate specific places -- e.g., what is the advantage of CP's request object over a request object that purely wraps a WSGI environment (like paste.wsgiwrappers.WSGIRequest)? Or, what is the advantage of writing authentication using a CherryPy-specific technique over WSGI middleware?
Configuration is the other big issue. The core of Paste Deploy is really an interface, not a specific configuration file format. You could quite reasonably create another config file format, or load configs from a database or whatever, if you access the same interface that Paste Deploy accesses.
There's three interfaces that Paste Deploy defines:
All three of these return a WSGI application. "app" is the wrapped WSGI application. "loader" is an object that can load other apps by name (used for dispatchers that dispatch to multiple applications). global_conf is the "inherited" configuration -- configuration that wasn't specifically intended for this component, but which might provide useful advise. E.g., you might look for a "debug" global value. Looking for a global "document_root" value probably isn't very meaningful, so you are not forced to respect the values in global_conf, nor are they automatically folded together.
local_conf is restricted, in that the values can all be strings, and strings should be specially handled. Thus the string 'false' shouldn't be interpreted as true in a boolean context. It is up to the application to coerce the values as necessary; no validation of any kind is part of the interface, except for function signatures.
These three interfaces are how everything is set up in Paste Deploy. These application/middleware factories are really what defines a "Paste" application, I suppose -- that is, a configurable object that produces WSGI applications. You can define these interfaces for code without including any part of Paste. It is probably possible to provide these interfaces right now with CherryPy as the application factory (maybe using something like paste.registry to swap configs if that is indeed a problem).
It should be noted that configuration is not process-wide in Paste; it is local to the object returned by the factory. The same application can be instantiated twice with different configurations, and should respond properly. It doesn't *have* to of course -- though if it can't, it should probably raise an exception the second time it is invoked. If this really is required I'd consider the app/framework to have "middling" WSGI support, rather than "good" WSGI support (this has long been a problem with Django, for instance, which has lots of global process-wide configuration).
Personally I find Paste Deploy's actual configuration to be workable, but I can certainly imagine other ways to approach the problem. I believe the interfaces are sufficiently generic that it is possible to build other configuration systems or other ways to define a website layout. You can rely on the interfaces Paste Deploy uses to not change, and as you can see there's no direct bindings to the configuration file format.
I'm not sure how to compare this to CherryPy's configuration, as I don't really know what the most core or essential part of CherryPy's configuration is. Perhaps you could shed light on that.
fumanchu wrote: > More discussion to follow. I just spent a man-year of work making CP 3 > do all this and more and be beautiful at the same time, and I'll be > damned if I let TG devolve back to preferring the ugliness of bare > WSGI > and Paste.
First of all I'd like to say that CP3 does really looks beautiful and that it's wsgiserver is really good. Whatever TG 2.0 becomes it will surely use it's server by default.
As I've mentioned, the only problem I've seen when experimenting with it is how it handles module globals because of the way I'd like to build the WSGI stack for the application. I know that CherryPy can already build a tree composed of CP and wsgi apps, however, from what I've seen (I hope I'm wrong but I believe I'm not) it seems to me that CherryPy wants to be the only one building the stack.
What I mean with this is that by the way I've seen a CP app is mounted and the server started, the whole tree is built by CP mechanisms, mounted under a given prefix and served. This is what the quickstart function looks like:
def quickstart(root, script_name="", config=None): """Mount the given app, start the engine and builtin server, then block.""" if config: cherrypy.config.update(config) cherrypy.tree.mount(root, script_name, config) cherrypy.server.quickstart() cherrypy.engine.start()
CP and wsgi apps are mounted or grafted into a global cherrypy.tree, and then a global server and a global engine are started.
However, I'd like to use Paste Deploy for deployment of TG apps. This is for many reasons, most importantly:
* it looks like it's powerful enough for our needs (composing apps, applying filters, configuring a server (even CP), etc...) I know CP3 can already do this, but, read on...
* It's not tied to any particular framework. Pylons is using it and it looks like any wsgi compliant framework/app could use it too (just implement it's interface and provide entry points... could even be done by a user wanting to integrate a non "paste-enabled" wsgi app into it's workflow).
The last point I believe to be very important because I'd like to see other framework's apps easy to deploy along TG apps and the opposite way around too, TG apps being easy to deploy along other frameworks' apps.
I'd like to stress the fact that this deployment should be easy and as standardized as possible for the end user too (sysadmins, etc..), not only developers.
To achieve this it looks obvious to me that we (wsgi frameworks) shall agree on a "standard", framework-independent interface and paste deploy's is the only one I know of (is there any other?)
What I'm trying to achieve with this are self contained CP apps (with their own tree, config, etc...) which can be mounted by a paste.URLMap (or any other composite app factory) at *any* point in the tree.
However, I haven't found easy to isolate each CP app because of the mentioned use of globals. cherrypy.config is easy to monkey patch to be app specific. cherrypy.request and reponse too. I know they're already thread-local, but what if a CP app dispatches (in the same thread) to a wsgi app that turns out to be another CP app wrapped into an opaque WSGI app?, would they get app-specific cp globals? To put it in other words:
_tree = Tree() # mount stuff
# global tree cherrypy.tree.graft(_tree, '/foo') cherrypy.tree.graft(another_app, '/bar')
Would CP controllers under _tree see a different cp.config, cp.request, cp.response, etc... than those under cp.tree? This is why some sort of stacked, thread-local proxy is needed.
So it seems to me that if TG wants to use CP3's engine and use paste.deploy's interfaces some patching or monkey-patching is needed... I'm really not very comfortable with this sort of monkey- patching because we seem to be poking too many CP internals again. Experience with 1.0 has taught us that this leads to a hard time if we want to migrate to newer CP versions.
Another thing I'd like to see in TG is the use of middleware instead of CP3 tools and hooks. I've got nothing against them and I'm sure their design is sound and powerful. However, TG 2.0 want's to build on independent components which can be stolen, adapted or written from scratch and be reused in other frameworks/apps so it looks like WSGI middleware is a better alternative to CP's tools/hooks because the later can only be used in CP apps.
This brings us to a point that we should consider what CP3 provides us with. If we don't need config, deployment, tools and filters we're left with the server and it's dispatching mechanisms which is what most TG users are used to and love.
Taken all this into account I believe it's less risky to use CP3 server and emulate CP3's dispatching rather than heavily monkey- patching CP3's internals.
Alberto Valverde wrote: > fumanchu wrote: > > More discussion to follow. I just spent a man-year of work making CP 3 > > do all this and more and be beautiful at the same time, and I'll be > > damned if I let TG devolve back to preferring the ugliness of bare > > WSGI and Paste.
> As I've mentioned, the only problem I've seen when experimenting with > it is how it handles module globals because of the way I'd like to > build the WSGI stack for the application. I know that CherryPy can > already build a tree composed of CP and wsgi apps, however, from what > I've seen (I hope I'm wrong but I believe I'm not) it seems to me > that CherryPy wants to be the only one building the stack.
> What I mean with this is that by the way I've seen a CP app is > mounted and the server started, the whole tree is built by CP > mechanisms, mounted under a given prefix and served. This is what > the quickstart function looks like:
> def quickstart(root, script_name="", config=None): > """Mount the given app, start the engine and builtin server, > then block.""" > if config: > cherrypy.config.update(config) > cherrypy.tree.mount(root, script_name, config) > cherrypy.server.quickstart() > cherrypy.engine.start()
> CP and wsgi apps are mounted or grafted into a global cherrypy.tree, > and then a global server and a global engine are started.
This is merely the default, because most users, especially new ones, want to deploy a single application. Hence the name "quickstart". If you want to do more than that, then naturally you must take more manual control over the mounting and startup process, and CherryPy 3 gives you LOTS of control over that (which CP 2 did not).
> * It's not tied to any particular framework. Pylons is using it and > it looks like any wsgi compliant framework/app could use it too (just > implement it's interface and provide entry points... could even be > done by a user wanting to integrate a non "paste-enabled" wsgi app > into it's workflow).
Despite the rhetoric, frameworks are not evil per se; they provide a common interface to all components and are crucial for performing expensive operations _once_. WSGI does provide a lowest-common-denominator interface, but few people want to program to the WSGI interface all day long. So alternatives (like CherryPy, or paste.wsgiwrappers) are recommended to make working with WSGI more pleasant. But there's a vicious circle which accompanies the desire to "not have a framework":
1. You build your initial offering using middleware from project A. 2. The developers of project A find that parsing headers, params, and various calculated data is slow, so they cache behind the scenes in library Z. 3. The holy grail of WSGI middleware is that we should be able to steal code from lots of different projects, so you add another bit of WSGI middleware from project B. 4. The developers of project B find that parsing headers, params, and various calculated data is slow, so they cache behind the scenes in library Y. 5. As the number of libraries Z, Y, X... increases, the number of times the same data is parsed rises (increasing CPU time) and ALSO the number of places it is cached (increasing memory footprint). 6. Turbogears finds this state of affairs unacceptable, and decrees, "we will only support middleware built with library Z (or no library)". 7. Library Z therefore plays the role of a framework, no matter how much "proof by repeated assertion" that it is "not a framework" floats around in its marketing.
Why go through that entire loop when CherryPy is ready now to play the part of library Z?
> The last point I believe to be very important because I'd like to see > other framework's apps easy to deploy along TG apps and the opposite > way around too, TG apps being easy to deploy along other frameworks' > apps.
> I'd like to stress the fact that this deployment should be easy and > as standardized as possible for the end user too (sysadmins, etc..), > not only developers.
> To achieve this it looks obvious to me that we (wsgi frameworks) > shall agree on a "standard", framework-independent interface and > paste deploy's is the only one I know of (is there any other?)
That goal should be addressed on web-sig, I think. Choosing a current implementation (of any portion of a web stack) and expecting each web tool to declare it a "standard" has a pretty poor track record in the world of Python web apps. The WSGI standard, by contrast, was hashed out on web-sig for quite some time, taking input from all possible players in that space.
770 HTTP/1.1 500 Internal Server ErrorContent-Type: text/plain Content-Length: 35 Date: Fri, 05 Jan 2007 23:54:07 GMT Server: CherryPy/2.2.1
Unrecoverable error in the server.
> What I'm trying to achieve with this are self contained CP apps (with > their own tree, config, etc...) which can be mounted by a > paste.URLMap (or any other composite app factory) at *any* point in > the tree.
Then I haven't communicated the architecture of CherryPy properly. A "self-contained app" (CP or otherwise) shouldn't have a Tree. The CherryPy Tree class is WSGI middleware for app dispatch, much like paste.urlparser.URLResolver. And it can dispatch to CP apps or arbitrary WSGI apps equally well.
Tree dispatch is separate from the "handler dispatch" that occurs once we've finished with the WSGI stack and are inside a request object.
> However, I haven't found easy to isolate each CP app because of the > mentioned use of globals. cherrypy.config is easy to monkey patch to > be app specific. cherrypy.request and reponse too. I know they're > already thread-local, but what if a CP app dispatches (in the same > thread) to a wsgi app that turns out to be another CP app wrapped > into an opaque WSGI app?
First, I should clarify by repeating that CP _applications_ should not "dispatch to a wsgi app". A CP Tree instance might, because that's what it's made for. But a CP3 Application instance is just that: a WSGI application object and not middleware. There is a wsgiapp Tool in the distro, but frankly, I don't recommend it--there are much better ways to compose WSGI components. Most of CherryPy makes web application development easier, not middleware development. And this is IMO a proper focus, because the VAST majority of CP users (and TG users) are going to spend the VAST majority of their time writing web apps, not WSGI middleware.
> would they get app-specific cp globals? To > put it in other words:
> _tree = Tree() > # mount stuff
> # global tree > cherrypy.tree.graft(_tree, '/foo') > cherrypy.tree.graft(another_app, '/bar')
> Would CP controllers under _tree see a different cp.config, > cp.request, cp.response, etc... than those under cp.tree?
Yes, they would. The request and response objects are in a threadlocal; you get a different one for each request. You even get a different one when you InternalRedirect, now.
The config is in three parts: global config, app config, and a "request.config" which is "all the items in the first two that apply to the current request" in a single dict. The global config is truly global, but that's as it should be. Anything you don't want to put in all applications should go in each app's config. This is nothing more than proper separation.
> This is why some sort of stacked, thread-local proxy is needed.
I agree it needs to be thread-local, but it doesn't need to be "stacked" unless one *application* (not middleware) truly calls another *application*, which isn't AFAICT a use-case of the WSGI spec. In addition, CherryPy's expectation is that WSGI middleware should not use cherrypy globals, and no CherryPy middleware does.
> So it seems to me that if TG wants to use CP3's engine and use > paste.deploy's interfaces some patching or monkey-patching is > needed... I'm really not very comfortable with this sort of monkey- > patching because we seem to be poking too many CP internals again. > Experience with 1.0 has taught us that this leads to a hard time if > we want to migrate to newer CP versions.
I don't think you should use paste.deploy's interfaces. They're not a standard yet by any stretch of the imagination, and I've written extensively on why CherryPy's deployment interface is better at http://www.cherrypy.org/wiki/CherryPyAndPaste.
> TG 2.0 want's to build on independent components which can > be stolen, adapted or written from scratch and be reused in > other frameworks/apps so it looks like WSGI middleware is > a better alternative to CP's tools/hooks because the latter > can only be used in CP apps.
This is a non-sequitur. Nothing about CP keeps you from *using* WSGI components from anywhere, whether stolen, adapted or written from scratch. Please, beg, borrow and steal good code from these sources. But at the end of the day, middleware cannot implement all functionality (and I would argue little of the interesting functionality) for extending the request/response process. So you'll need some code to allow plugins inside the application itself, after all the WSGI layers have done their thing. CherryPy is ready, willing, and able to provide that extension system today. Why reinvent it?
Now, if you want to argue that CP Tools deny you the ability to share your code with others, that's a different tangent. But IMO that desire pales in comparison to the desire to have a useful, beautiful, fast web framework. Not to mention that the vast majority of Tools are short bits of code and could be ported to uglier middleware versions with a couple quick greps. I have no problem making those who want to steal MY code do that work; it's silly to make ME do it (and make my toolset ugly in the process in order to support
And I would be more than happy to make time at PyCon to sprint on a first draft of TG 2 using CP 3, even if you haven't decided whether you want to stick with CP or not yet. But let me know soon if you would find that beneficial.
Robert Brewer System Architect Amor Ministries fuman...@amor.org
fumanchu wrote: >> * It's not tied to any particular framework. Pylons is using it and >> it looks like any wsgi compliant framework/app could use it too (just >> implement it's interface and provide entry points... could even be >> done by a user wanting to integrate a non "paste-enabled" wsgi app >> into it's workflow).
> Despite the rhetoric, frameworks are not evil per se; they provide a > common interface to all components and are crucial for performing > expensive operations _once_. WSGI does provide a > lowest-common-denominator interface, but few people want to program to > the WSGI interface all day long. So alternatives (like CherryPy, or > paste.wsgiwrappers) are recommended to make working with WSGI more > pleasant.
paste.wsgiwrappers is a way of helping people use the WSGI interface; it isn't an alternative to that interface. It is very much constrained to what WSGI allows, and I've gone out of my way to keep it that way.
> But there's a vicious circle which accompanies the desire to > "not have a framework":
> 1. You build your initial offering using middleware from project A. > 2. The developers of project A find that parsing headers, params, and > various calculated data is slow, so they cache behind the scenes in > library Z.
Headers are already parsed. The query string must be parsed, and possibly the request body. I'm not sure what else really needs to be parsed.
> 3. The holy grail of WSGI middleware is that we should be able to > steal code from lots of different projects, so you add another bit of > WSGI middleware from project B. > 4. The developers of project B find that parsing headers, params, and > various calculated data is slow, so they cache behind the scenes in > library Y. > 5. As the number of libraries Z, Y, X... increases, the number of > times the same data is parsed rises (increasing CPU time) and ALSO the > number of places it is cached (increasing memory footprint).
This seems like you're looking for a problem that does not yet exist, and may never exist. So long as the results are semantically correct, the overhead (memory or CPU) that you are referring to is not that large, and dependent on the software stack.
> 6. Turbogears finds this state of affairs unacceptable, and decrees, > "we will only support middleware built with library Z (or no library)".
Performance concerns do not require any kind of restriction like that, they only lead people to advise certain combinations. As long as other combinations *work*, there's no reason to restrict people's choices. As long as everyone obeys WSGI (and doesn't try to pass information through non-WSGI channels) then they *will* work together.
> 7. Library Z therefore plays the role of a framework, no matter how > much "proof by repeated assertion" that it is "not a framework" floats > around in its marketing.
It's not a framework, just the basis of a well-performing stack that TurboGears uses and recommends.
> Why go through that entire loop when CherryPy is ready now to play the > part of library Z?
CherryPy is ready now to be a library for using WSGI?
>> The last point I believe to be very important because I'd like to see >> other framework's apps easy to deploy along TG apps and the opposite >> way around too, TG apps being easy to deploy along other frameworks' >> apps.
>> I'd like to stress the fact that this deployment should be easy and >> as standardized as possible for the end user too (sysadmins, etc..), >> not only developers.
>> To achieve this it looks obvious to me that we (wsgi frameworks) >> shall agree on a "standard", framework-independent interface and >> paste deploy's is the only one I know of (is there any other?)
> That goal should be addressed on web-sig, I think. Choosing a current > implementation (of any portion of a web stack) and expecting each web > tool to declare it a "standard" has a pretty poor track record in the > world of Python web apps. The WSGI standard, by contrast, was hashed > out on web-sig for quite some time, taking input from all possible > players in that space.
I brought up the possibility on Web-SIG of standardizing on something based on these interfaces, but no one seemed interested in it. Mostly Luke Arno was the most interested in stuff, and he prefers constructing stacks in Python so a standard interface didn't mean much to him.
>> However, I haven't found easy to isolate each CP app because of the >> mentioned use of globals. cherrypy.config is easy to monkey patch to >> be app specific. cherrypy.request and reponse too. I know they're >> already thread-local, but what if a CP app dispatches (in the same >> thread) to a wsgi app that turns out to be another CP app wrapped >> into an opaque WSGI app?
> First, I should clarify by repeating that CP _applications_ should not > "dispatch to a wsgi app". A CP Tree instance might, because that's what > it's made for. But a CP3 Application instance is just that: a WSGI > application object and not middleware. There is a wsgiapp Tool in the > distro, but frankly, I don't recommend it--there are much better ways > to compose WSGI components. Most of CherryPy makes web application > development easier, not middleware development. And this is IMO a > proper focus, because the VAST majority of CP users (and TG users) are > going to spend the VAST majority of their time writing web apps, not > WSGI middleware.
No ceilings! We (the larger programming community) is okay at reusing libraries and certain patterns, but so far not so good at reusing code that is more complex, in the case of web frameworks, code that has UI and multiple screens worth of interacting data.
Mounting a subapplication in your application allows you to create reusable code on this scale (which is hardly a large scale, but uncommonly large in current practice). This is the scale of reuse that TurboGears is struggling to achieve, and what can make TurboGears more than just Another Nice Framework.
>> This is why some sort of stacked, thread-local proxy is needed.
> I agree it needs to be thread-local, but it doesn't need to be > "stacked" unless one *application* (not middleware) truly calls another > *application*, which isn't AFAICT a use-case of the WSGI spec. In > addition, CherryPy's expectation is that WSGI middleware should not use > cherrypy globals, and no CherryPy middleware does.
It's definitely a use case for the WSGI spec. "Application" is just a role -- one side of the communication plays the part of server, the other of application. The labels only apply to that communication. Applications can forward requests to other applications. Much of the middleware I find myself writing is both middleware and application -- that is, some but not all requests get forwarded on to another application, or the dispatch is handled dynamically, or an application is instantiated based information in the request and then the request is forwarded to that short-lived application. All these patterns are useful.
>> So it seems to me that if TG wants to use CP3's engine and use >> paste.deploy's interfaces some patching or monkey-patching is >> needed... I'm really not very comfortable with this sort of monkey- >> patching because we seem to be poking too many CP internals again. >> Experience with 1.0 has taught us that this leads to a hard time if >> we want to migrate to newer CP versions.
> I don't think you should use paste.deploy's interfaces. They're not a > standard yet by any stretch of the imagination, and I've written > extensively on why CherryPy's deployment interface is better at > http://www.cherrypy.org/wiki/CherryPyAndPaste.
I think I'll have to write a full retort to that comparison, because there's just too much in there to go over it here.
As far as configuration, I'm not really clear on your argument. It doesn't look substantially different to me, except that the only way to configure dispatchers in CP (like Paste's URLMap or CP's Tree) is through ad hoc code.
>> TG 2.0 want's to build on independent components which can >> be stolen, adapted or written from scratch and be reused in >> other frameworks/apps so it looks like WSGI middleware is >> a better alternative to CP's tools/hooks because the latter >> can only be used in CP apps.
> This is a non-sequitur. Nothing about CP keeps you from *using* WSGI > components from anywhere, whether stolen, adapted or written from > scratch. Please, beg, borrow and steal good code from these sources. > But at the end of the day, middleware cannot implement all > functionality (and I would argue little of the interesting > functionality) for extending the request/response process. So you'll > need some code to allow plugins inside the application itself, after > all the WSGI layers have done their thing. CherryPy is ready, willing, > and able to provide that extension system today. Why reinvent it?
AFAICT TurboGears has its own heavy use of decorators for some plugins, normal library code of course, the toolbox and other extensions, and lots of other stuff. They know their way around plugins.
>> This brings us to a point that we should consider >> what CP3 provides us with. If we don't need config, >> deployment, tools and filters we're left with the >> server and it's dispatching mechanisms which is >> what most TG users are used to and love.
Ian Bicking wrote: > fumanchu wrote: > > Why go through that entire loop when CherryPy is ready now to play the > > part of library Z?
> CherryPy is ready now to be a library for using WSGI?
Yes. Although, more importantly, CherryPy is ready now to be a library for building web applications. Focusing on WSGI misses the forest for the trees.
> > First, I should clarify by repeating that CP _applications_ should not > > "dispatch to a wsgi app". A CP Tree instance might, because that's what > > it's made for. But a CP3 Application instance is just that: a WSGI > > application object and not middleware. There is a wsgiapp Tool in the > > distro, but frankly, I don't recommend it--there are much better ways > > to compose WSGI components. Most of CherryPy makes web application > > development easier, not middleware development. And this is IMO a > > proper focus, because the VAST majority of CP users (and TG users) are > > going to spend the VAST majority of their time writing web apps, not > > WSGI middleware.
> No ceilings! We (the larger programming community) is okay at reusing > libraries and certain patterns, but so far not so good at reusing code > that is more complex, in the case of web frameworks, code that has UI > and multiple screens worth of interacting data.
> Mounting a subapplication in your application allows you to create > reusable code on this scale (which is hardly a large scale, but > uncommonly large in current practice). This is the scale of reuse that > TurboGears is struggling to achieve, and what can make TurboGears more > than just Another Nice Framework.
Sure; and WSGI middleware is a good place to arrange this mounting, which is why CherryPy 3 not only allows, but actively encourages and makes easier the composition of a WSGI stack. CherryPy's Server class is just as good for managing someone else's HTTP server; CherryPy's Tree class is just as good for mounting other people's WSGI components, and you may even decide one of those "subapplications" should be a CherryPy Application.
> >> This is why some sort of stacked, thread-local proxy is needed.
> > I agree it needs to be thread-local, but it doesn't need to be > > "stacked" unless one *application* (not middleware) truly calls another > > *application*, which isn't AFAICT a use-case of the WSGI spec. In > > addition, CherryPy's expectation is that WSGI middleware should not use > > cherrypy globals, and no CherryPy middleware does.
> It's definitely a use case for the WSGI spec. "Application" is just a > role -- one side of the communication plays the part of server, the > other of application. The labels only apply to that communication. > Applications can forward requests to other applications. Much of the > middleware I find myself writing is both middleware and application --
Much? If you're using the term "application" as a "role" then I think you mean "ALL middleware I find myself writing is both middleware and application". The mixing of terminology is getting a bit thick. Let me restate my comment adopting another term from the spec: "pure" servers/gateways and applications/frameworks (as opposed to middleware, which plays both sides):
First, I should clarify by repeating that CP _applications_ should not "dispatch to a wsgi app". CP Application objects are always "pure" WSGI applications. A CP Tree instance might dispatch, because that's what it's made for; it's middleware. But a CP3 Application instance is just that: a "pure" WSGI application object and not middleware. There is a wsgiapp Tool in the distro, but frankly, I don't recommend it--there are much better ways to compose a WSGI stack. Most of CherryPy makes "pure" web application development easier, not middleware development. And this is IMO a proper focus, because the VAST majority of CP users (and TG users) are going to spend the VAST majority of their time writing code on the far side of a "pure" WSGI application interface, not WSGI middleware.
> This is why some sort of stacked, thread-local proxy is needed.
I agree it needs to be thread-local, but it doesn't need to be "stacked" unless one "pure" application (not middleware) truly calls another "pure" application, which isn't AFAICT a use-case of the WSGI spec. CherryPy's expectation is that WSGI middleware should not use cherrypy globals, and no CherryPy middleware does.
Ian Bicking also wrote: > that is, some but not all requests get forwarded on to another > application, or the dispatch is handled dynamically, or an application > is instantiated based information in the request and then the request is > forwarded to that short-lived application. All these patterns are useful.
No argument there; this is in fact the best use of middleware--dynamically choosing which WSGI call point to call next. This is the essence of a WSGI dispatcher, for example, which uses SCRIPT_NAME + PATH_INFO to make that choice.
Robert Brewer System Architect Amor Ministries fuman...@amor.org