[Web-SIG] Entry points and import maps (was Re: Scarecrow deployment config
Chris McDonough
chrism at plope.com
Mon Jul 25 02:35:08 CEST 2005
Sorry, I think I may have lost track of where we were going wrt the
deployment spec. Specifically, I don't know how we got to using eggs
(which I'd really like to, BTW, they're awesome conceptually!) from
where we were in the discussion about configuring a WSGI pipeline. What
is a "feature"? What is an "import map"? "Entry point"? Should I just
get more familiar with eggs to understand what's being discussed here or
did I miss a few posts?
On Sun, 2005-07-24 at 12:49 -0400, Phillip J. Eby wrote:
> [cc:ed to distutils-sig because much of the below is about a new egg
> feature; follow-ups about the web stuff should stay on web-sig]
>
> At 04:04 AM 7/24/2005 -0500, Ian Bicking wrote:
> >So maybe here's a deployment spec we can start with. It looks like:
> >
> > [feature1]
> > someapplication.somemodule.some_function
> >
> > [feature2]
> > someapplication.somemodule.some_function2
> >
> >You can't get dumber than that! There should also be a "no-feature"
> >section; maybe one without a section identifier, or some special section
> >identifier.
> >
> >It goes in the .egg-info directory. This way elsewhere you can say:
> >
> > application = SomeApplication[feature1]
>
> I like this a lot, although for a different purpose than the format Chris
> and I were talking about. I see this fitting into that format as maybe:
>
> [feature1 from SomeApplication]
> # configuration here
>
>
> >And it's quite unambiguous. Note that there is *no* "configuration" in
> >the egg-info file, because you can't put any configuration related to a
> >deployment in an .egg-info directory, because it's not specific to any
> >deployment. Obviously we still need a way to get configuration in
> >there, but lets say that's a different matter.
>
> Easily fixed via what I've been thinking of as the "deployment descriptor";
> I would call your proposal here the "import map". Basically, an import map
> describes a mapping from some sort of feature name to qualified names in
> the code.
>
> I have an extension that I would make, though. Instead of using sections
> for features, I would use name/value pairs inside of sections named for the
> kind of import map. E.g.:
>
> [wsgi.app_factories]
> feature1 = somemodule:somefunction
> feature2 = another.module:SomeClass
> ...
>
> [mime.parsers]
> application/atom+xml = something:atom_parser
> ...
>
> In other words, feature maps could be a generic mechanism offered by
> setuptools, with a 'Distribution.load_entry_point(kind,name)' API to
> retrieve the desired object. That way, we don't end up reinventing this
> idea for dozens of frameworks or pluggable applications that just need a
> way to find a few simple entry points into the code.
>
> In addition to specifying the entry point, each entry in the import map
> could optionally list the "extras" that are required if that entry point is
> used.
> It could also issue a 'require()' for the corresponding feature if it has
> any additional requirements listed in the extras_require dictionary.
>
> So, I'm thinking that this would be implemented with an entry_points.txt
> file in .egg-info, but supplied in setup.py like this:
>
> setup(
> ...
> entry_points = {
> "wsgi.app_factories": dict(
> feature1 = "somemodule:somefunction",
> feature2 = "another.module:SomeClass [extra1,extra2]",
> ),
> "mime.parsers": {
> "application/atom+xml": "something:atom_parser [feedparser]"
> }
> },
> extras_require = dict(
> feedparser = [...],
> extra1 = [...],
> extra2 = [...],
> )
> )
>
> Anyway, this would make the most common use case for eggs-as-plugins very
> easy: an application or framework would simply define entry points, and
> plugin projects would declare the ones they offer in their setup script.
>
> I think this is a fantastic idea and I'm about to leap into implementing
> it. :)
>
>
> >This puts complex middleware construction into the function that is
> >referenced. This function might be, in turn, an import from a
> >framework. Or it might be some complex setup specific to the
> >application. Whatever.
> >
> >The API would look like:
> >
> > wsgiapp = wsgiref.get_egg_application('SomeApplication[feature1]')
> >
> >Which ultimately resolves to:
> >
> > wsgiapp = some_function()
> >
> >get_egg_application could also take a pkg_resources.Distribution object.
>
> Yeah, I'm thinking that this could be implemented as something like:
>
> import pkg_resources
>
> def get_wsgi_app(project_name, app_name, *args, **kw):
> dist = pkg_resources.require(project_name)[0]
> return dist.load_entry_point('wsgi.app_factories',
> app_name)(*args,**kw)
>
> with all the heavy lifting happening in the pkg_resources.Distribution
> class, along with maybe a new EntryPoint class (to handle parsing entry
> point specifiers and to do the loading of them.
>
>
> >Open issues? Yep, there's a bunch. This requires the rest of the
> >configuration to be done quite lazily.
>
> Not sure I follow you; the deployment descriptor could contain all the
> configuration; see the Web-SIG post I made just previous to this one.
>
>
> > But I can fit this into source
> >control; it is about *all* I can fit into source control (I can't have
> >any filenames, I can't have any installation-specific pipelines, I can't
> >have any other apps), but it is also enough that the deployment-specific
> >parts can avoid many complexities of pipelining and factories and all
> >that -- presumably the factory functions handle that.
>
> +1.
>
>
> > I don't think
> >this is useful without the other pieces (both in front of this
> >configuration file and behind it) but maybe we can think about what
> >those other pieces could look like. I'm particularly open to
> >suggestions that some_function() take some arguments, but I don't know
> >what arguments.
>
> At this point, I think this "entry points" concept weighs in favor of
> having the deployment descriptor configuration values be Python
> expressions, meaning that a WSGI application factory would accept keyword
> arguments that can be whatever you like in order to configure it.
>
> However, after more thought, I think that the "next application" argument
> should be a keyword argument too, like 'wsgi_next' or some such. This
> would allow a factory to have required arguments in its signature, e.g.:
>
> def some_factory(required_arg_x, required_arg_y, optional_arg="foo",
> ....):
> ...
>
> The problem with my original idea to have the "next app" be a positional
> argument is that it would prevent non-middleware applications from having
> any required arguments.
>
> Anyway, I think we're now very close to being able to define a useful
> deployment descriptor format for establishing pipelines and setting
> options, that leaves open the possibility to do some very sophisticated
> things.
>
> Hm. Interesting thought... we could have a function to read a deployment
> descriptor (from a string, stream, or filename) and then return the WSGI
> application object. You could then wrap this in a simple WSGI app that
> does filesystem-based URL routing to serve up *.wsgi files from a
> directory. This would let you bootstrap a deployment capability into
> existing WSGI servers, without them having to add their own support for
> it! Web servers and frameworks that have some kind of file extension
> mapping mechanism could do this directly, of course. I can envision
> putting *.wsgi files in my web directories and then configuring Apache to
> run them using either mod_python or FastCGI or even as a CGI, just by
> tweaking local .htaccess files. However, once you have Apache tweaked the
> way you want, .wsgi files can be just dropped in and edited.
>
> Of course, there are still some open design issues, like caching of .wsgi
> files (e.g. should the file be checked for changes on each hit? I guess
> that could be a setting under "WSGI options", and would only work if the
> descriptor parser was given an actual filename to load from.)
>
> _______________________________________________
> Web-SIG mailing list
> Web-SIG at python.org
> Web SIG: http://www.python.org/sigs/web-sig
> Unsubscribe: http://mail.python.org/mailman/options/web-sig/chrism%40plope.com
>
More information about the Web-SIG
mailing list