[Web-SIG] wsgiconfig design
Ian Bicking
ianb at colorstudy.com
Sat Jul 7 05:41:49 CEST 2007
Every so often I get in this cleanup/redux mood where I feel a need to
revisit things I've done before in an attempt to Do Them Right.
We've discussed Paste Deploy here before, and I'm thinking about Redoing
It Right. I thought I'd share some thoughts on the design:
I still am quite happy with the entry points from Paste Deploy, and plan
to keep them, except perhaps paste.composite_factory which I might
replace with another way of creating composites that takes a dictionary
as an argument (a dictionary of section names to WSGI applications). I
will probably rename them, but also support the old Paste Deploy names.
The composite entry point isn't too big a deal, because it's mostly
just Paste that implements those kinds of components -- normal people
just write applications and middleware that dispatches to a single
application.
There will be a few levels of pluggability. The first is the loader
itself, which will default to the wsgiconfig loader itself. This is
only applicable to file-based configuration. When you load up the
application from a file, it will search for a #! line that specifies a
loader, which is the name of a distribution or module. It will search
the distribution for some entry point (wsgiconfig.config_loader:main),
and that entry point is a callable like:
def config_loader(filename, options, object_type):
return wsgi_application
options is a flat dictionary of options that are passed in, which the
config loader can use at its discretion. A common way to use it would
be for variable substitution. This allows for things like "paster serve
config.ini var1=value var2=value", for ad hoc customization. It returns
a single application. (This does mean that a feature from Paste Deploy
is lost, where you could do "paster serve config.ini#section_name" to
load a specific application from several defined in a file -- but you
are less likely to get dead sections or confusing config file factorings).
object_type is the kind of object we want to get out. Here I'll only
specify 'wsgi.application'. 'wsgi.server' will probably also be
implemented, but that's all I plan for now. 'wsgi.appserver' or
something might be possible, for the process manager that runs an entire
application.
From there, you can do whatever. But importantly, wsgiconfig defines a
loader which I hope people will like.
Unlike Paste Deploy, section names will not be arbitrary. A section
name has a prefix and name. The prefix, as in Paste Deploy, says what
you are describing. The default prefix is "app:"; you can also give
"middleware:". Prefixes not recognized will be ignored. A possible
prefix might be "logging:" for logging, which if I don't implement it
will be initially ignored (but someone else could handle it). Similarly
the server as with Paste Deploy can be defined with "server:". For now
all we're concerned with is applications, middleware, and composites.
The applications and middleware are grouped together using the names.
That is, if you have an application "/" and a middleware "middleware:/",
then the middleware wraps that application. Middleware sections can
have trailing numbers to indicate ordering and keep section names
unique. Thus "middleware:/ 1", "middleware:/ 2", etc. Negative numbers
and floats are allowed. Anything but trailing numbers is considered
part of the name; thus names can have parameters or other structure.
All the applications in the server are put in a single dictionary, and
that is based to the composer. The composer by default is urlmap (which
also includes optional host-based dispatch). You can specify another
composer with a global option "composer = (specifier)"
The sections still have a "use" option, which indicates what implements
the option. It will take "egg:", and dotted module/object names, and
module names may have trailing entry point specifiers (if the object
doesn't implement the "preferred" interface for that kind of output).
You cannot use "config:" anymore, instead that will be handled by the
config file format.
The config files will use INITools, which is similar to ConfigParser but
a bit nicer. It will include improved string substitution, including
similar constructs to what zc.buildout has. While still keeping
applications firmly separated from the config files, I'm planning on
paying close attention to call signatures and exceptions to give good
error messages. E.g., if you raise something like TypeError("... got an
unexpected keyword argument 'X'") I'll figure out where the keyword
arguments came from and improve the text of that error message. Not
perfect, but should be passable, and better than what Paste Deploy does now.
That's pretty much it. I won't write any server stuff for now, except
maybe try to get "paster serve" to work with these files. I'll try to
include a simple framework for applications that want to have their own
command-line runners, so that if you have some neat little application
you can just tell people to install it and run "serve-applicationname"
or whatever you call your script.
Anyway, those are my thoughts. I'm going to give it a go this weekend.
--
Ian Bicking : ianb at colorstudy.com : http://blog.ianbicking.org
: Write code, do good : http://topp.openplans.org/careers
More information about the Web-SIG
mailing list