mso@oz.net wrote: > [Trimmed down the Cc list to those I know will be interested.] > > Ian Bicking wrote: > >>>I looked briefly at the source and saw it's not a simple straightforward >>>task. >>> - wsgikit.cgiserver seems to be the only adapter, akin to >>>quixote.servers.cgi_server . Nothing fast enough for production use >>>unless you believe in FastCGI (which I don't). >> >>It's the only one really included, just because it doesn't have a Real >>Home. wsgi-server can handle the WSGIUtils server, a "console" server >>(which dumps one page to stdout), a CGI-generating "server" (creates a >>CGI script), and used to support Twisted. But Twisted web 2 got native >>WSGI support, and I haven't tracked it down since then. I would like to >>include all other interesting servers (at least stubs for them), but I >>don't think it's hard, and if it isn't hard I feel okay putting it off ;) > > > I guess the first thing that's needed is a HOWTO explaining all these > alternatives, where to get them and install them, and which ones work with > which. Andrew wrote something up yesterday which might help: http://svn.w4py.org/WSGIKit/trunk/docs/servers.txt > I downloaded TwistedSumo-2005-03-22 and grepped for wsgi but there wasn't > anything. I saw a note from you on twisted-web with a reply saying it's > in twisted.web2 . Is that a separate package? I'm not sure, I haven't had a chance to track it down. WSGIKit includes twisted_wsgi, but I hear there are bugs in it (it blocks the server, I think). >>> - The Session middleware may be usable. It saves to files akin to >>>DirMapping. >> >>It's actually not that good, but I expect to integrate this session >>middleware soon: http://www.saddi.com/software/py-lib/#Session > > > Actually, our Session object is used like an instance rather than a > dictionary, and it has .user/.get_user()/.set_user(), so we'd have to > support those somehow. And people are used to subclassing Session (and > Request) to provide extra attributes or for inter-method communication. Webware's session is a wrapper that just uses the dictionary as a backing store, you wouldn't necessarily expose the dictionary itself. The crudest way to do this would just be to put the Quixote Session object in the dictionary somewhere. >>Ideally I'd like to see one fairly general object publisher (/URL >>parser) included in WSGIKit, where Quixote applications would either >>subclass that publisher or pass in some configuration variables to get >>it to act like Quixote's publisher. > > > Quixote (Qx) applications tend to have one class per directory rather than > per servlet. The classes can be made autonomous and relocatable, which > means they can fit into larger units (Qx or non-Qx). Parsing below the > directory URL is not needed because each directory has a > ._q_traverse(list_of_following_components) => string|htmltext > method that handles it. The default implementation looks for a method > named after the next component and calls *its* ._q_traverse of there are > further components, or if there are no further components it just calls > the method and returns the result. But you can override ._q_traverse > completely if you want to do something different. My thought with configuring the object publisher would be to configure (or subclass) a generic publisher so that it looked for things like _q_traverse. E.g., if you wanted to use one publisher for Quixote and CherryPy, the actual distinguishing details are more names and slight semantic differences than differences that require two entirely separate code bases. At least, I would expect that to be the case, I don't know for sure. >>Do Quixote objects that are published inherit from a single class? If >>not, then the publisher probably has to wrap the published object just >>before passing off control to that object, and the wrapper would create >>the request and response objects and make sure they get flushed properly >>and whatnot. > > > Directories usually inherit from Directory, although they may be any > object with a compatible ._q_traverse method/function. Hmm... the benefit of inheriting from a single class is the class could be extended to add WSGIKit compatibility, and all the apps would automatically get that functionality. Otherwise you have to create a wrapper, and the publisher is more likely to need to know exactly how to detect Quixote objects and wrap them appropriately. > The level above is the > Publisher.process_request(request) => response > method. The URL parsing is simple: > '/'.split(url) > The Publisher also delegates the session handling and performs error > handling. PublishError(public_msg, private_msg) results in the public > message to the user and both messages in the log. Any other exceptions > call cgitb, with variations for security. We're currently in debate about > how much of the Publisher would be left if all the middleware components > were factored out. Maybe it would only split the URL and call the > traversal metnod. Another problem is decoupling the Session from the > Publisher, since the Session currently depends on it. Not ideal if you > think the Publisher might disappear. How does the session depend on the Publisher? That doesn't seem like a natural dependency, so it should be removable. The error handling, IMHO, is best handled externally. My one biggest motivation has been the desire to keep error handling consistent in web and non-web environments, but there's all sorts of other good reasons as well. It seems like Publisher is a natural candidate for being split up into several pieces of nested middleware. I've avoided splitting the URL in the URL traversal code I've written, because it adds derivative data that might get out of sync. Instead I just pull one chunk off PATH_INFO and put it on SCRIPT_NAME. It seems repetetive, but I think it keeps the possible side effects down. > We may have to decide how far to support custom Publisher/Session/Request > subclasses, or maybe have two WSGI implementations: a monolithic one for > highly customized sites, and a middleware'd one for generic sites. That might indeed be necessary, though if you can identify a public (with respect to subclassing) API that the classes provide that subclasses use, you should be able to support subclasses so long as they stick to that and don't recreate the API without subclassing. > One thing I don't understand is, WSGI seems to require both parts to be in > the same process, since you can't pickle an open file object. I thought > WSGI would replace SCGI, but with that limitation it can't. It would have > to operate on the application side of it. It makes the WSGI adapter seem > very small and perhaps not worth the trouble, since you're essentially > just repackaging the environment dictionary twice and not getting at the > real problem, which is the darn mod_* to Python interface, and mod_* > modules that break when you need them or suddenly won't compile. What can > WSGI middleware do that SCGI middleware couldn't do? They are different in scope. WSGI is single-process, though of course it can translated to and from SCGI or even HTTP fairly easily. If there's four pieces of WSGI middleware that you are using, that means at least four functional calls, but only one dictionary. That's reasonably efficient. You can't have four serialization/deserializations and network transfers efficiently. Also the WSGI dictionary can (and in WSGIKit definitely *does*) have non-string objects which SCGI can't support (even with pickling, e.g., callbacks). I think they are just totally different things, really -- bothed based heavily on CGI, but serving different purposes. -- Ian Bicking / ianb@colorstudy.com / http://blog.ianbicking.org