1 | # $Id: ImportHooks.py,v 1.27 2007/11/16 18:28:47 tavis_rudd Exp $ |
---|
2 | |
---|
3 | """Provides some import hooks to allow Cheetah's .tmpl files to be imported |
---|
4 | directly like Python .py modules. |
---|
5 | |
---|
6 | To use these: |
---|
7 | import Cheetah.ImportHooks |
---|
8 | Cheetah.ImportHooks.install() |
---|
9 | |
---|
10 | Meta-Data |
---|
11 | ================================================================================ |
---|
12 | Author: Tavis Rudd <tavis@damnsimple.com> |
---|
13 | License: This software is released for unlimited distribution under the |
---|
14 | terms of the MIT license. See the LICENSE file. |
---|
15 | Version: $Revision: 1.27 $ |
---|
16 | Start Date: 2001/03/30 |
---|
17 | Last Revision Date: $Date: 2007/11/16 18:28:47 $ |
---|
18 | """ |
---|
19 | __author__ = "Tavis Rudd <tavis@damnsimple.com>" |
---|
20 | __revision__ = "$Revision: 1.27 $"[11:-2] |
---|
21 | |
---|
22 | import sys |
---|
23 | import os.path |
---|
24 | import types |
---|
25 | import __builtin__ |
---|
26 | import new |
---|
27 | import imp |
---|
28 | from threading import RLock |
---|
29 | import string |
---|
30 | import traceback |
---|
31 | from Cheetah import ImportManager |
---|
32 | from Cheetah.ImportManager import DirOwner |
---|
33 | from Cheetah.Compiler import Compiler |
---|
34 | from Cheetah.convertTmplPathToModuleName import convertTmplPathToModuleName |
---|
35 | |
---|
36 | _installed = False |
---|
37 | |
---|
38 | ################################################## |
---|
39 | ## HELPER FUNCS |
---|
40 | |
---|
41 | _cacheDir = [] |
---|
42 | def setCacheDir(cacheDir): |
---|
43 | global _cacheDir |
---|
44 | _cacheDir.append(cacheDir) |
---|
45 | |
---|
46 | ################################################## |
---|
47 | ## CLASSES |
---|
48 | |
---|
49 | class CheetahDirOwner(DirOwner): |
---|
50 | _lock = RLock() |
---|
51 | _acquireLock = _lock.acquire |
---|
52 | _releaseLock = _lock.release |
---|
53 | |
---|
54 | templateFileExtensions = ('.tmpl',) |
---|
55 | |
---|
56 | def getmod(self, name): |
---|
57 | self._acquireLock() |
---|
58 | try: |
---|
59 | mod = DirOwner.getmod(self, name) |
---|
60 | if mod: |
---|
61 | return mod |
---|
62 | |
---|
63 | for ext in self.templateFileExtensions: |
---|
64 | tmplPath = os.path.join(self.path, name + ext) |
---|
65 | if os.path.exists(tmplPath): |
---|
66 | try: |
---|
67 | return self._compile(name, tmplPath) |
---|
68 | except: |
---|
69 | # @@TR: log the error |
---|
70 | exc_txt = traceback.format_exc() |
---|
71 | exc_txt =' '+(' \n'.join(exc_txt.splitlines())) |
---|
72 | raise ImportError( |
---|
73 | 'Error while compiling Cheetah module' |
---|
74 | ' %(name)s, original traceback follows:\n%(exc_txt)s'%locals()) |
---|
75 | ## |
---|
76 | return None |
---|
77 | |
---|
78 | finally: |
---|
79 | self._releaseLock() |
---|
80 | |
---|
81 | def _compile(self, name, tmplPath): |
---|
82 | ## @@ consider adding an ImportError raiser here |
---|
83 | code = str(Compiler(file=tmplPath, moduleName=name, |
---|
84 | mainClassName=name)) |
---|
85 | if _cacheDir: |
---|
86 | __file__ = os.path.join(_cacheDir[0], |
---|
87 | convertTmplPathToModuleName(tmplPath)) + '.py' |
---|
88 | try: |
---|
89 | open(__file__, 'w').write(code) |
---|
90 | except OSError: |
---|
91 | ## @@ TR: need to add some error code here |
---|
92 | traceback.print_exc(file=sys.stderr) |
---|
93 | __file__ = tmplPath |
---|
94 | else: |
---|
95 | __file__ = tmplPath |
---|
96 | co = compile(code+'\n', __file__, 'exec') |
---|
97 | |
---|
98 | mod = imp.new_module(name) |
---|
99 | mod.__file__ = co.co_filename |
---|
100 | if _cacheDir: |
---|
101 | mod.__orig_file__ = tmplPath # @@TR: this is used in the WebKit |
---|
102 | # filemonitoring code |
---|
103 | mod.__co__ = co |
---|
104 | return mod |
---|
105 | |
---|
106 | |
---|
107 | ################################################## |
---|
108 | ## FUNCTIONS |
---|
109 | |
---|
110 | def install(templateFileExtensions=('.tmpl',)): |
---|
111 | """Install the Cheetah Import Hooks""" |
---|
112 | |
---|
113 | global _installed |
---|
114 | if not _installed: |
---|
115 | CheetahDirOwner.templateFileExtensions = templateFileExtensions |
---|
116 | import __builtin__ |
---|
117 | if type(__builtin__.__import__) == types.BuiltinFunctionType: |
---|
118 | global __oldimport__ |
---|
119 | __oldimport__ = __builtin__.__import__ |
---|
120 | ImportManager._globalOwnerTypes.insert(0, CheetahDirOwner) |
---|
121 | #ImportManager._globalOwnerTypes.append(CheetahDirOwner) |
---|
122 | global _manager |
---|
123 | _manager=ImportManager.ImportManager() |
---|
124 | _manager.setThreaded() |
---|
125 | _manager.install() |
---|
126 | |
---|
127 | def uninstall(): |
---|
128 | """Uninstall the Cheetah Import Hooks""" |
---|
129 | global _installed |
---|
130 | if not _installed: |
---|
131 | import __builtin__ |
---|
132 | if type(__builtin__.__import__) == types.MethodType: |
---|
133 | __builtin__.__import__ = __oldimport__ |
---|
134 | global _manager |
---|
135 | del _manager |
---|
136 | |
---|
137 | if __name__ == '__main__': |
---|
138 | install() |
---|