0001"""Kid Import Hooks.
0002
0003When installed, these hooks allow importing .kid files as if they were
0004Python modules.
0005
0006Notes:
0007
0008There's some unpleasant incompatibility between ZODB's import trickery and the
0009import hooks here. Bottom line: if you're using ZODB, import it *before*
0010installing the import hooks.
0011
0012This module is based heavily on code from the Quixote ptl_import module by MEMS
0013Exchange -- thanks guys.
0014"""
0015
0016__revision__ = "$Rev: 252 $"
0017__date__ = "$Date: 2006-01-15 14:55:12 -0500 (Sun, 15 Jan 2006) $"
0018__author__ = "Ryan Tomayko (rtomayko@gmail.com)"
0019__copyright__ = "Copyright 2004-2005, Ryan Tomayko"
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040import os
0041import sys
0042import time
0043import imp, ihooks, new
0044import __builtin__
0045
0046import kid.compiler
0047KID_EXT = kid.compiler.KID_EXT
0048
0049assert sys.hexversion >= 0x20000b1, "need Python 2.0b1 or later"
0050
0051_installed = False
0052def install(suffixes=None):
0053 global _installed
0054 if not _installed:
0055 hooks = KIDHooks(suffixes=suffixes)
0056 loader = KIDLoader(hooks)
0057 if cimport is not None:
0058 importer = cModuleImporter(loader)
0059 else:
0060 importer = ihooks.ModuleImporter(loader)
0061 ihooks.install(importer)
0062 _installed = True
0063
0064def uninstall():
0065 global _installed
0066 _installed = False
0067 ihooks.uninstall()
0068
0069def import_template(name, filename, force=0):
0070 if not force and name and sys.modules.has_key(name):
0071 return sys.modules[name]
0072 template = kid.compiler.KidFile(filename)
0073 code = template.compile(dump_source=os.environ.get('KID_OUTPUT_PY'))
0074 module = _create_module(code, name, filename)
0075 return module
0076
0077def get_template_name(name, filename):
0078 if name:
0079 return name
0080 else:
0081 return 'kid.util.template_' + hex(hash(filename) + 0x80000000)
0082
0083def _create_module(code, name, filename, store=1):
0084 name = get_template_name(name, filename)
0085 mod = new.module(name)
0086 mod.__file__ = filename
0087 mod.__ctime__ = time.time()
0088 exec code in mod.__dict__
0089 if store:
0090 sys.modules[name] = mod
0091 return mod
0092
0093
0094KID_FILE = object()
0095
0096class KIDHooks(ihooks.Hooks):
0097
0098 def __init__(self, verbose=ihooks.VERBOSE, suffixes=None):
0099 ihooks.Hooks.__init__(self, verbose)
0100 self.suffixes = suffixes or []
0101
0102 def get_suffixes(self):
0103 return [(KID_EXT, 'r', KID_FILE)] + [(suffix, 'r', KID_FILE) for suffix in self.suffixes] + imp.get_suffixes()
0106
0107class KIDLoader(ihooks.ModuleLoader):
0108
0109 def load_module(self, name, stuff):
0110 file, filename, info = stuff
0111 (suff, mode, type) = info
0112 if type is KID_FILE:
0113 return import_template(name, filename, force=1)
0114 else:
0115 return ihooks.ModuleLoader.load_module(self, name, stuff)
0116
0117try:
0118 import cimport
0119except ImportError:
0120 cimport = None
0121
0122class cModuleImporter(ihooks.ModuleImporter):
0123 def __init__(self, loader=None):
0124 self.loader = loader or ihooks.ModuleLoader()
0125 cimport.set_loader(self.find_import_module)
0126
0127 def find_import_module(self, fullname, subname, path):
0128 stuff = self.loader.find_module(subname, path)
0129 if not stuff:
0130 return None
0131 return self.loader.load_module(fullname, stuff)
0132
0133 def install(self):
0134 self.save_import_module = __builtin__.__import__
0135 self.save_reload = __builtin__.reload
0136 if not hasattr(__builtin__, 'unload'):
0137 __builtin__.unload = None
0138 self.save_unload = __builtin__.unload
0139 __builtin__.__import__ = cimport.import_module
0140 __builtin__.reload = cimport.reload_module
0141 __builtin__.unload = self.unload