#!/usr/bin/env python
"""
Provides some import hooks to allow Cheetah's .tmpl files to be imported
directly like Python .py modules.
To use these:
import Cheetah.ImportHooks
Cheetah.ImportHooks.install()
"""
import sys
import os.path
import types
import __builtin__
import imp
from threading import RLock
import string
import traceback
import types
from Cheetah import ImportManager
from Cheetah.ImportManager import DirOwner
from Cheetah.Compiler import Compiler
from Cheetah.convertTmplPathToModuleName import convertTmplPathToModuleName
_installed = False
##################################################
## HELPER FUNCS
_cacheDir = []
def setCacheDir(cacheDir):
global _cacheDir
_cacheDir.append(cacheDir)
##################################################
## CLASSES
class CheetahDirOwner(DirOwner):
_lock = RLock()
_acquireLock = _lock.acquire
_releaseLock = _lock.release
templateFileExtensions = ('.tmpl',)
def getmod(self, name):
self._acquireLock()
try:
mod = DirOwner.getmod(self, name)
if mod:
return mod
for ext in self.templateFileExtensions:
tmplPath = os.path.join(self.path, name + ext)
if os.path.exists(tmplPath):
try:
return self._compile(name, tmplPath)
except:
# @@TR: log the error
exc_txt = traceback.format_exc()
exc_txt =' '+(' \n'.join(exc_txt.splitlines()))
raise ImportError(
'Error while compiling Cheetah module'
' %(name)s, original traceback follows:\n%(exc_txt)s'%locals())
##
return None
finally:
self._releaseLock()
def _compile(self, name, tmplPath):
## @@ consider adding an ImportError raiser here
code = str(Compiler(file=tmplPath, moduleName=name,
mainClassName=name))
if _cacheDir:
__file__ = os.path.join(_cacheDir[0],
convertTmplPathToModuleName(tmplPath)) + '.py'
try:
open(__file__, 'w').write(code)
except OSError:
## @@ TR: need to add some error code here
traceback.print_exc(file=sys.stderr)
__file__ = tmplPath
else:
__file__ = tmplPath
co = compile(code+'\n', __file__, 'exec')
mod = types.ModuleType(name)
mod.__file__ = co.co_filename
if _cacheDir:
mod.__orig_file__ = tmplPath # @@TR: this is used in the WebKit
# filemonitoring code
mod.__co__ = co
return mod
##################################################
## FUNCTIONS
def install(templateFileExtensions=('.tmpl',)):
"""Install the Cheetah Import Hooks"""
global _installed
if not _installed:
CheetahDirOwner.templateFileExtensions = templateFileExtensions
import __builtin__
if isinstance(__builtin__.__import__, types.BuiltinFunctionType):
global __oldimport__
__oldimport__ = __builtin__.__import__
ImportManager._globalOwnerTypes.insert(0, CheetahDirOwner)
#ImportManager._globalOwnerTypes.append(CheetahDirOwner)
global _manager
_manager=ImportManager.ImportManager()
_manager.setThreaded()
_manager.install()
def uninstall():
"""Uninstall the Cheetah Import Hooks"""
global _installed
if not _installed:
import __builtin__
if isinstance(__builtin__.__import__, types.MethodType):
__builtin__.__import__ = __oldimport__
global _manager
del _manager
if __name__ == '__main__':
install()
|