[albatross-users] page module problem

Dave Cole djc at object-craft.com.au
Sun Aug 10 21:17:24 EST 2003


> I'm using a random app but I suspect the problem would occur with
> non-random apps too.
> 
> If I store my page modules in a directory structure and two
> directories have a python module with the same name, something like
> this ...
> 
>     ./modules/one/list.py
>     ./modules/two/list.py
> 
> then **both** modules get imported with a name of 'list' (as seen in
> sys.modules.keys()). This happens because the directory structure is
> not considered a package structure, just somewhere to store modules.
> 
> I'm trying to find a solution to this limitation but, so far, I'm
> not happy with the fix. I'm currently abusing the imp module in a
> truly horrible way by passing an application generated name to
> load_module() to stop the name clash. It goes something like this:
> 
>     dirname, filename = os.path.split(path)
>     file, filepath, desc = imp.find_module(filename, [dirname])
>     mod_name = '_albatross_page_%s' % name.replace('/', '_')
>     page = imp.load_module(mod_name, file, filepath, desc)
> 
> Well, I did warn you it was horrible ;-).
> 
> Another possibility is to use the execfile() builtin to (sort of)
> load the module into a blank namespace. This seems cleaner since it
> does not create a module but I'm concerned it might break things in
> ways I don't yet understand. It would probably also mean changing
> the way in which the page modules are cached.
> 
> If anyone has more experience with this sort of thing I would be
> grateful for any ideas/help.

It might make more sense to require that applications use a proper
Python directory structure for page modules.  All that means is you
need to have an __init__.py in each page module directory.  Once this
has been done then the relevant code in the PageModuleMixin
load_page_module() method could be changed to this:

    def load_page_module(self, ctx, name):
        if self.__base_dir == '.':
            path = name
        else:
            path = os.path.join(self.__base_dir, name)
        page = self.__cache.get(path)
        if page:
            mtime = os.stat(page.__file__)[stat.ST_MTIME]
            if mtime > page.__mtime__:
                reload(page)
                page.__mtime__ = mtime
        if not page:
            #
            # Name must be a fully qualified page module relative to
            # the base module directory.  RandomPageModule must change
            # 'one/list' to 'one.list' so we can import here.
            #
            file, filepath, desc = imp.find_module(name, [self.__base_dir])
            page = sys.modules.get(name)
            if not page or not page.__file__.startswith(filepath):
                try:
                    page = imp.load_module(name, file, filepath, desc)
                finally:
                    if file:
                        file.close()

So all we do is delete the one line that causes the page module to be
imported from the directory in which it lives.  Then we cause the
import to be from the module base directory.

Seems a bit silly that it does not already do this.

- Dave

-- 
http://www.object-craft.com.au




More information about the Albatross-users mailing list