Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | # This module is used by the Pmw package system. |
2 | # The PmwLoader class can be used to simulate a python module, | |
3 | # but also supports importing of submodules on demand. This technique | |
4 | # reduces startup time because Pmw submodules which are not used are | |
5 | # not loaded. | |
6 | # | |
7 | # The PmwLoader class also supports runtime selection of the Pmw | |
8 | # version(s) to use. | |
9 | ||
10 | import sys | |
11 | import os | |
12 | import string | |
13 | import types | |
14 | ||
15 | _PMW_DEF = 'Pmw.def' # Pmw definition file | |
16 | _BASEMODULE = 'Base' # Name of Base module | |
17 | ||
18 | class PmwLoader: | |
19 | ||
20 | def __init__(self, dirpath, instdirs, dirs): | |
21 | self._dirpath = dirpath | |
22 | self._instdirs = instdirs | |
23 | self._dirs = dirs | |
24 | self._initialised = 0 | |
25 | self._version = string.replace(instdirs[0][4:], '_', '.') | |
26 | self._alpha_versions = () | |
27 | ||
28 | #====================================================================== | |
29 | ||
30 | # Public methods. These methods will be seen as "module methods". | |
31 | ||
32 | def setversion(self, version): | |
33 | if self._version == version: | |
34 | return | |
35 | if self._initialised: | |
36 | raise ValueError, 'Cannot change Pmw version after initialisation' | |
37 | self._version = version | |
38 | ||
39 | def setalphaversions(self, *alpha_versions): | |
40 | if self._alpha_versions == alpha_versions: | |
41 | return | |
42 | if self._initialised: | |
43 | raise ValueError, \ | |
44 | 'Cannot change Pmw alpha versions after initialisation' | |
45 | self._alpha_versions = alpha_versions | |
46 | ||
47 | def version(self, alpha = 0): | |
48 | if alpha: | |
49 | return self._alpha_versions | |
50 | else: | |
51 | return self._version | |
52 | ||
53 | def installedversions(self, alpha = 0): | |
54 | rtn = [] | |
55 | if alpha: | |
56 | dirs = filter(lambda x: x[:5] == 'Alpha', self._dirs) | |
57 | dirs.sort() | |
58 | dirs.reverse() | |
59 | for dir in dirs: | |
60 | rtn.append(string.replace(dir[6:], '_', '.')) | |
61 | else: | |
62 | for dir in self._instdirs: | |
63 | rtn.append(string.replace(dir[4:], '_', '.')) | |
64 | return rtn | |
65 | ||
66 | #====================================================================== | |
67 | ||
68 | # Private methods | |
69 | ||
70 | def _getmodule(self,modpath): | |
71 | __import__(modpath) | |
72 | mod = sys.modules[modpath] | |
73 | return mod | |
74 | ||
75 | def _initialise(self): | |
76 | searchpath = [] | |
77 | ||
78 | for version in self._alpha_versions: | |
79 | alphadir = '_Pmw.Alpha_%s.lib' % string.replace(version, '.', '_') | |
80 | searchpath.append(alphadir) | |
81 | ||
82 | libdir = '_Pmw.Pmw_%s.lib' % string.replace(self._version, '.', '_') | |
83 | searchpath.append(libdir) | |
84 | ||
85 | # Create attributes for the PmwBase classes and functions. | |
86 | for path in searchpath: | |
87 | try: | |
88 | basemodule = self._getmodule(path + '.Pmw' + _BASEMODULE) | |
89 | break | |
90 | except ImportError, msg: | |
91 | if path == searchpath[-1]: | |
92 | # No PmwBase module found. | |
93 | raise ImportError, msg | |
94 | ||
95 | for k,v in basemodule.__dict__.items(): | |
96 | if k[0] is not '_' and type(v) != types.ModuleType: | |
97 | self.__dict__[k] = v | |
98 | ||
99 | # Set the Pmw definitions from the Pmw.def file. | |
100 | dict = { | |
101 | '_widgets' : {}, | |
102 | '_extraWidgets' : {}, | |
103 | '_functions' : {}, | |
104 | '_modules' : {}, | |
105 | } | |
106 | for name in dict.keys(): | |
107 | self.__dict__[name] = {} | |
108 | searchpath.reverse() | |
109 | for path in searchpath: | |
110 | pathbit = apply(os.path.join, tuple(string.split(path[5:], '.'))) | |
111 | lpath = os.path.join(self._dirpath, pathbit) | |
112 | d = {} | |
113 | execfile(os.path.join(lpath,_PMW_DEF), d) | |
114 | for k,v in d.items(): | |
115 | if dict.has_key(k): | |
116 | if type(v) == types.TupleType: | |
117 | for item in v: | |
118 | modpath = path + '.Pmw' + item | |
119 | dict[k][item] = modpath | |
120 | elif type(v) == types.DictionaryType: | |
121 | for k1, v1 in v.items(): | |
122 | modpath = path + '.Pmw' + v1 | |
123 | dict[k][k1] = modpath | |
124 | self.__dict__.update(dict) | |
125 | self._widgets_keys = self._widgets.keys() | |
126 | self._extraWidgets_keys = self._extraWidgets.keys() | |
127 | self._functions_keys = self._functions.keys() | |
128 | self._modules_keys = self._modules.keys() | |
129 | ||
130 | self._initialised = 1 | |
131 | ||
132 | def __getattr__(self, name): | |
133 | if not self._initialised: | |
134 | self._initialise() | |
135 | # Beware: _initialise may have defined 'name' | |
136 | if name in self.__dict__.keys(): | |
137 | return self.__dict__[name] | |
138 | ||
139 | # The requested attribute is not yet set. Look it up in the | |
140 | # tables set by Pmw.def, import the appropriate module and | |
141 | # set the attribute so that it will be found next time. | |
142 | ||
143 | if name in self._widgets_keys: | |
144 | # The attribute is a widget name. | |
145 | mod = self._getmodule(self._widgets[name]) | |
146 | cls = getattr(mod,name) | |
147 | self.__dict__[name] = cls | |
148 | return cls | |
149 | ||
150 | if name in self._functions_keys: | |
151 | # The attribute is a function from one of the modules. | |
152 | modname = self._functions[name] | |
153 | mod = self._getmodule(modname) | |
154 | func = getattr(mod, name) | |
155 | self.__dict__[name] = func | |
156 | return func | |
157 | ||
158 | if name in self._modules_keys: | |
159 | # The attribute is a module | |
160 | mod = self._getmodule(self._modules[name]) | |
161 | self.__dict__[name] = mod | |
162 | return mod | |
163 | ||
164 | if name in self._extraWidgets_keys: | |
165 | # XXX I should import them all, once I've started. | |
166 | # The attribute is a widget name in a module of another name | |
167 | modname = self._extraWidgets[name] | |
168 | mod = self._getmodule(modname) | |
169 | cls = getattr(mod, name) | |
170 | self.__dict__[name] = cls | |
171 | return cls | |
172 | ||
173 | # The attribute is not known by Pmw, report an error. | |
174 | raise AttributeError, name |