[mod_python] Graham's New Importer

Graham Dumpleton grahamd at dscpl.com.au
Wed May 10 19:31:00 EDT 2006


Dan Eloff wrote ..
> >    from mod_python import apache
> >    __info__.path.extend(eval(apache.main_server.get_options().get
> > ('my_import_path','[]')))
> >
> 
> I like that, but I agree __info__.path is not ideal.
>
> ...
> 
> > By a module explicitly adding items to the embedded search path, it
> > would be
> > more predictable perhaps than blindly always using what the option
> > may be set
> > to, as by adding the code in you are making a conscious decision that
> > you want
> > it to work that way. You need not even use an option to obtain what
> > the path
> > should be set to, you could also use hard coded paths, or a path
> > determined by
> > taking a relative path and adding it to the dirname of the __file__
> > attribute of the
> > module.
> 
> Not ideal for me, since I would simply add this to the top of every
> single python file. But I can live with that because it does solve all
> the issues related to a global setting. All in all a pretty good
> solution.

Depending on how your modules are structured, it may not be quite
as bad as having to add it to every file. At least not the look up of
what path to use.

This is because what you may be able to do is use the fact that if
you supply an absolute or relative path to apache.import_module(),
that the "path" argument, rather than being a search path, becomes
the path which is encoded into the module as '__info__.path'.

Thus, if a top level entry point module were used, much like a
package root, and although there were various sub modules that
any methods were exposed through the top level module, you
could do something like:

    # toplevel.py

    from mod_python import apache
    __info__.path.extend(eval(apache.main_server.get_options().get('my_import_path','[]')))

    submodule_1 = apache.import_module('./submodule_1.py', path=__info__.path)
    submodule_2 = apache.import_module('./subdir_2/toplevel.py', path=__info__.path)

Thus, those submodules now don't need to set '__info__.path', as they
will inherit that from the top level module.

This may turn out to be messy or not useful as is as well. Overall, I
guess what we need to come up with is some example use cases where
search paths are required and perhaps work from that as to what is
a good interface for supporting it. At the moment, my impression is
that the common use case is in order to access some configuration
module in a central location. Can you describe again your use case?

One other issue that may come into play in this is that besides being
able to access 'apache.main_server.get_options()', that is, the main
server options, there is no way at global scope within a module to
access the options related to the request, or virtual host that the
module is being imported into.

There was a similar issue in respect of the mod_python config settings
for PythonDebug and PythonAutoReload when it came to the importer
itself. To get around this the importer uses new top level dispatch
functions to cache the appropriate configuration available so it is
available no matter where apache.import_module() is used. At the
moment this cached config isn't accessible through the 'apache' module
but is available as 'mod_python.importer.get_config()'.

If a module import is occurring do to PythonImport and you call that
function, you will get the 'apache.main_server.get_config()' object. If
the module import is occurring within the context of a request, the
function will return 'req.get_config()'. Thus the 'apache.import_module()'
function uses this to get the PythonDebug and PythonAutoReload
settings so that they don't have to be explicitly passed to the function
itself, thus avoiding some of the problems described in my issues list.

I guess the question in respect of user options, is whether there should
be some means getting the appropriate options object from global
scope in a module. Thus, something like:

    from mod_python import apache
    __info__.path.extend(eval(apache.get_options().get('my_import_path','[]')))

Where like with the config, if it is PythonImport, it returns the main
server options and if in context of a request, the request options.

The only problem with this is that you get back to unpredictable
behaviour if a module might be imported from different places where
the option set is different. That option set which is used first takes
precedence.

The issue is whether we want to protect people from doing stupid
things by not allowing it, or give them a loaded gun and let them
kill themselves if they want to. :-)

Note, in Vampire, it actually for the time that a module is being
imported exposes a variable '__req__' as global data within the module
so that either the config, options or anything else for that matter about
the request can be accessed. When I modified the Vampire importer for
use in mod_python though, I didn't carry across that feature as was
unsure about how wise it was providing it.

Sorry, I know this should be on the developer list. Maybe we should
look at bumping it over there. Dan are you on the developer list?

Graham



More information about the Mod_python mailing list