[albatross-users] page module import magic
Andrew McNamara
andrewm at object-craft.com.au
Mon Jan 12 23:07:05 EST 2004
Is this getting too ugly? Much of the messiness comes from supporting
hierarchies of page modules (app.login.help, etc) - dummy parent modules
have to be created. I've written a bunch of tests, and it looks like
the modification works well, but maybe we should only support a flat page
module namespace?
Index: app.py
===================================================================
RCS file: /usr/local/cvsroot/object-craft/albatross/albatross/app.py,v
retrieving revision 1.87
diff -u -r1.87 app.py
--- app.py 9 Jan 2004 12:38:27 -0000 1.87
+++ app.py 12 Jan 2004 12:02:26 -0000
@@ -7,7 +7,6 @@
import os
import sys
-import stat
import imp
import urlparse
@@ -374,10 +373,13 @@
'''Caching module loader
'''
+ mod_holder_name = '__alpage__'
+
def __init__(self, base_dir, start_page):
self.__base_dir = base_dir
self.__start_page = start_page
- self.__cache = {}
+ if not sys.modules.has_key(self.mod_holder_name):
+ self.create_module_holder(self.mod_holder_name)
def module_path(self):
return self.__base_dir
@@ -393,35 +395,49 @@
ctx.set_page(name)
self.load_page_module(ctx, name)
+ def is_page_module(self, name):
+ return name.startswith(self.mod_holder_name)
+
+ def create_module_holder(self, name):
+ sys.modules[name] = module = imp.new_module(name)
+ return module
+
+ def get_module_holder(self, name):
+ path = name.split('.')[:-1]
+ parent_name = '.'.join(path)
+ try:
+ return sys.modules[parent_name]
+ except KeyError:
+ parent_parent = self.get_module_holder(parent_name)
+ module = self.create_module_holder(parent_name)
+ setattr(parent_parent, path[-1], module)
+ return module
+
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:
- dirname, name = os.path.split(path)
- file, filepath, desc = imp.find_module(name, [dirname])
- 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()
+ if not name.startswith(self.mod_holder_name):
+ name = self.mod_holder_name + '.' + name
+ try:
+ page = sys.modules[name]
+ except KeyError:
+ modpath = os.path.join(self.__base_dir, *name.split('.')[1:])
+ modpath, modname = os.path.split(os.path.normpath(modpath))
+ try:
+ f, filepath, desc = imp.find_module(modname, [modpath])
+ except ImportError, e:
+ raise ApplicationError('%s (in %s)' % (e, modpath))
+ try:
+ page = imp.load_module(name, f, filepath, desc)
+ finally:
+ if f:
+ f.close()
if not (hasattr(page, 'page_enter') or
hasattr(page, 'page_leave') or
hasattr(page, 'page_process') or
hasattr(page, 'page_display')):
raise ApplicationError('module "%s" does not define one of page_enter, page_leave, page_process or page_display' % (name))
- page.__mtime__ = os.stat(page.__file__)[stat.ST_MTIME]
- self.__cache[path] = page
+ setattr(self.get_module_holder(name), modname, page)
ctx.page = page
+ return ctx.page
def page_enter(self, ctx, args):
if hasattr(ctx.page, 'page_enter'):
@@ -451,8 +467,8 @@
self.__start_page = start_page
self.__page_objects = {}
- def module_path(self):
- pass
+ def is_page_module(self, name):
+ return False
def start_page(self):
return self.__start_page
Index: context.py
===================================================================
RCS file: /usr/local/cvsroot/object-craft/albatross/albatross/context.py,v
retrieving revision 1.93
diff -u -r1.93 context.py
--- context.py 21 Sep 2003 04:40:31 -0000 1.93
+++ context.py 12 Jan 2004 12:02:28 -0000
@@ -10,6 +10,7 @@
import stat
import re
import cPickle
+import __builtin__
try:
import zlib
@@ -564,9 +565,13 @@
self.clear_locals()
def decode_session(self, text):
- module_path = self.app.module_path()
- if module_path:
- sys.path.insert(0, module_path)
+ def imp_hook(name, globals, locals, fromlist):
+ if self.app.is_page_module(name):
+ return self.app.load_page_module(self, name)
+ else:
+ return real_imp(name, globals, locals, fromlist)
+
+ real_imp, __builtin__.__import__ = __builtin__.__import__, imp_hook
try:
try:
vars = cPickle.loads(text)
@@ -577,8 +582,7 @@
for name in vars.keys():
self.__vars[name] = 1
finally:
- if module_path:
- sys.path.remove(module_path)
+ __builtin__.__import__ = real_imp
def encode_session(self):
vars = {}
--
Andrew McNamara, Senior Developer, Object Craft
http://www.object-craft.com.au/
More information about the Albatross-users
mailing list