author | rgbecker |
Wed, 27 Mar 2002 13:34:43 +0000 | |
changeset 1561 | 1b10f25e76df |
parent 1545 | 966ccacc4c7d |
child 1575 | 7d2360bdfc4d |
permissions | -rw-r--r-- |
494 | 1 |
#copyright ReportLab Inc. 2000 |
2 |
#see license.txt for license details |
|
3 |
#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/lib/utils.py?cvsroot=reportlab |
|
1561 | 4 |
#$Header: /tmp/reportlab/reportlab/lib/utils.py,v 1.29 2002/03/27 13:34:43 rgbecker Exp $ |
5 |
__version__=''' $Id: utils.py,v 1.29 2002/03/27 13:34:43 rgbecker Exp $ ''' |
|
562 | 6 |
|
1375 | 7 |
import string, os, sys |
413 | 8 |
from types import * |
674 | 9 |
from reportlab.lib.logger import warnOnce |
413 | 10 |
SeqTypes = (ListType,TupleType) |
562 | 11 |
|
1143 | 12 |
def _checkImportError(errMsg): |
13 |
if string.lower(string.strip(str(errMsg)[0:16]))!='no module named': raise |
|
14 |
||
413 | 15 |
try: |
16 |
#raise ImportError |
|
519 | 17 |
### NOTE! FP_STR SHOULD PROBABLY ALWAYS DO A PYTHON STR() CONVERSION ON ARGS |
18 |
### IN CASE THEY ARE "LAZY OBJECTS". ACCELLERATOR DOESN'T DO THIS (YET) |
|
474 | 19 |
try: |
1143 | 20 |
from _rl_accel import fp_str # in case of builtin version |
674 | 21 |
except ImportError, errMsg: |
1143 | 22 |
_checkImportError(errMsg) |
23 |
from reportlab.lib._rl_accel import fp_str # specific |
|
674 | 24 |
except ImportError, errMsg: |
1153 | 25 |
#_checkImportError(errMsg) # this effectively requires _rl_accel... should not be required |
413 | 26 |
def fp_str(*a): |
27 |
if len(a)==1 and type(a[0]) in SeqTypes: a = a[0] |
|
28 |
s = [] |
|
29 |
for i in a: |
|
1537 | 30 |
s.append('%0.6f' % i) |
413 | 31 |
return string.join(s) |
448 | 32 |
|
981 | 33 |
#hack test for comma users |
34 |
if ',' in fp_str(0.25): |
|
35 |
_FP_STR = fp_str |
|
36 |
def fp_str(*a): |
|
37 |
return string.replace(apply(_FP_STR,a),',','.') |
|
38 |
||
1538 | 39 |
def recursiveImport(modulename, baseDir=None, noCWD=0): |
1389
6e5ba87ce34e
added function recursiveImport('package1.package2.module') in r/lib/utils
andy_robinson
parents:
1387
diff
changeset
|
40 |
"""Dynamically imports possible packagized module, or raises ImportError""" |
6e5ba87ce34e
added function recursiveImport('package1.package2.module') in r/lib/utils
andy_robinson
parents:
1387
diff
changeset
|
41 |
import imp |
6e5ba87ce34e
added function recursiveImport('package1.package2.module') in r/lib/utils
andy_robinson
parents:
1387
diff
changeset
|
42 |
parts = string.split(modulename, '.') |
6e5ba87ce34e
added function recursiveImport('package1.package2.module') in r/lib/utils
andy_robinson
parents:
1387
diff
changeset
|
43 |
part = parts[0] |
1489
b4a6f11b5192
Added path functionality to Andy's recursive import thing
rgbecker
parents:
1470
diff
changeset
|
44 |
path = list(baseDir and (type(baseDir) not in SeqTypes and [baseDir] or filter(None,baseDir)) or None) |
1538 | 45 |
if not noCWD and '.' not in path: path.insert(0,'.') |
1396
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
46 |
|
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
47 |
#make import errors a bit more informative |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
48 |
try: |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
49 |
(file, pathname, description) = imp.find_module(part, path) |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
50 |
childModule = parentModule = imp.load_module(part, file, pathname, description) |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
51 |
for name in parts[1:]: |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
52 |
(file, pathname, description) = imp.find_module(name, parentModule.__path__) |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
53 |
childModule = imp.load_module(name, file, pathname, description) |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
54 |
setattr(parentModule, name, childModule) |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
55 |
parentModule = childModule |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
56 |
except ImportError: |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
57 |
msg = "cannot import '%s' while attempting recursive import of '%s'" % (part, modulename) |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
58 |
if baseDir: |
1489
b4a6f11b5192
Added path functionality to Andy's recursive import thing
rgbecker
parents:
1470
diff
changeset
|
59 |
msg = msg + " under paths '%s'" % `path` |
1396
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
60 |
raise ImportError, msg |
40d1361f08b7
Enhanced the error message from recursiveImport
andy_robinson
parents:
1389
diff
changeset
|
61 |
|
1389
6e5ba87ce34e
added function recursiveImport('package1.package2.module') in r/lib/utils
andy_robinson
parents:
1387
diff
changeset
|
62 |
return childModule |
6e5ba87ce34e
added function recursiveImport('package1.package2.module') in r/lib/utils
andy_robinson
parents:
1387
diff
changeset
|
63 |
|
674 | 64 |
def import_zlib(): |
65 |
try: |
|
66 |
import zlib |
|
67 |
except ImportError, errMsg: |
|
1143 | 68 |
_checkImportError(errMsg) |
674 | 69 |
zlib = None |
1470 | 70 |
from reportlab.rl_config import ZLIB_WARNINGS |
962 | 71 |
if ZLIB_WARNINGS: warnOnce('zlib not available') |
674 | 72 |
return zlib |
73 |
||
760 | 74 |
try: |
761 | 75 |
from PIL import Image |
760 | 76 |
except ImportError, errMsg: |
1143 | 77 |
_checkImportError(errMsg) |
998 | 78 |
from reportlab.rl_config import PIL_WARNINGS |
674 | 79 |
try: |
761 | 80 |
import Image |
962 | 81 |
if PIL_WARNINGS: warnOnce('Python Imaging Library not available as package; upgrade your installation!') |
674 | 82 |
except ImportError, errMsg: |
1143 | 83 |
_checkImportError(errMsg) |
760 | 84 |
Image = None |
962 | 85 |
if PIL_WARNINGS: warnOnce('Python Imaging Library not available') |
760 | 86 |
PIL_Image = Image |
87 |
del Image |
|
674 | 88 |
|
1375 | 89 |
class ArgvDictValue: |
90 |
'''A type to allow clients of getArgvDict to specify a conversion function''' |
|
91 |
def __init__(self,value,func): |
|
92 |
self.value = value |
|
93 |
self.func = func |
|
94 |
||
95 |
def getArgvDict(**kw): |
|
96 |
''' Builds a dictionary from its keyword arguments with overrides from sys.argv. |
|
97 |
Attempts to be smart about conversions, but the value can be an instance |
|
98 |
of ArgDictValue to allow specifying a conversion function. |
|
99 |
''' |
|
1387 | 100 |
def handleValue(v,av,func): |
101 |
if func: |
|
102 |
v = func(av) |
|
103 |
else: |
|
104 |
t = type(v) |
|
105 |
if t is StringType: |
|
106 |
v = av |
|
107 |
elif t is FloatType: |
|
108 |
v = float(av) |
|
109 |
elif t is IntType: |
|
110 |
v = int(av) |
|
111 |
elif t is ListType: |
|
112 |
v = list(eval(av)) |
|
113 |
elif t is TupleType: |
|
114 |
v = tuple(eval(av)) |
|
115 |
else: |
|
116 |
raise TypeError, "Can't convert string '%s' to %s" % (av,str(t)) |
|
117 |
return v |
|
118 |
||
1375 | 119 |
A = sys.argv[1:] |
1387 | 120 |
R = {} |
1375 | 121 |
for k, v in kw.items(): |
122 |
if isinstance(v,ArgvDictValue): |
|
123 |
v, func = v.value, v.func |
|
124 |
else: |
|
125 |
func = None |
|
1387 | 126 |
handled = 0 |
1375 | 127 |
ke = k+'=' |
128 |
for a in A: |
|
129 |
if string.find(a,ke)==0: |
|
130 |
av = a[len(ke):] |
|
131 |
A.remove(a) |
|
1387 | 132 |
R[k] = handleValue(v,av,func) |
133 |
handled = 1 |
|
1375 | 134 |
break |
1387 | 135 |
|
136 |
if not handled: R[k] = handleValue(v,v,func) |
|
137 |
||
138 |
return R |
|
1375 | 139 |
|
452 | 140 |
def getHyphenater(hDict=None): |
141 |
try: |
|
142 |
from reportlab.lib.pyHnj import Hyphen |
|
143 |
if hDict is None: hDict=os.path.join(os.path.dirname(__file__),'hyphen.mashed') |
|
144 |
return Hyphen(hDict) |
|
674 | 145 |
except ImportError, errMsg: |
677 | 146 |
if str(errMsg)!='No module named pyHnj': raise |
452 | 147 |
return None |
148 |
||
448 | 149 |
def _className(self): |
150 |
'''Return a shortened class name''' |
|
151 |
try: |
|
152 |
name = self.__class__.__name__ |
|
153 |
i=string.rfind(name,'.') |
|
154 |
if i>=0: return name[i+1:] |
|
155 |
return name |
|
156 |
except AttributeError: |
|
157 |
return str(self) |
|
1538 | 158 |
|
159 |
class DebugMemo: |
|
1543
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
160 |
'''Intended as a simple report back encapsulator |
1545 | 161 |
|
1543
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
162 |
Typical usages |
1545 | 163 |
1) To record error data |
164 |
dbg = DebugMemo(fn='dbgmemo.dbg',myVar=value) |
|
165 |
dbg.add(anotherPayload='aaaa',andagain='bbb') |
|
1543
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
166 |
dbg.dump() |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
167 |
|
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
168 |
2) To show the recorded info |
1545 | 169 |
dbg = DebugMemo(fn='dbgmemo.dbg',mode='r') |
170 |
dbg.load() |
|
171 |
dbg.show() |
|
1543
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
172 |
|
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
173 |
3) To re-use recorded information |
1545 | 174 |
dbg = DebugMemo(fn='dbgmemo.dbg',mode='r') |
175 |
dbg.load() |
|
176 |
myTestFunc(dbg.payload('myVar'),dbg.payload('andagain')) |
|
177 |
||
178 |
in addition to the payload variables the dump records many useful bits |
|
179 |
of information which are also printed in the show() method. |
|
1543
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
180 |
''' |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
181 |
def __init__(self,fn='rl_dbgmemo.dbg',mode='w',getScript=1,modules=(),**kw): |
1538 | 182 |
import time, socket |
183 |
self.fn = fn |
|
184 |
if mode!='w': return |
|
185 |
self.store = store = {} |
|
186 |
if sys.exc_info() != (None,None,None): |
|
187 |
import StringIO, traceback |
|
188 |
s = StringIO.StringIO() |
|
189 |
traceback.print_exc(None,s) |
|
190 |
store['__traceback'] = s.getvalue() |
|
191 |
cwd=os.getcwd() |
|
192 |
lcwd = os.listdir(cwd) |
|
1543
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
193 |
exed = os.path.abspath(os.path.dirname(sys.argv[0])) |
1538 | 194 |
store.update({ 'gmt': time.asctime(time.gmtime(time.time())), |
195 |
'platform': sys.platform, |
|
196 |
'version': sys.version, |
|
197 |
'executable': sys.executable, |
|
198 |
'prefix': sys.prefix, |
|
199 |
'path': sys.path, |
|
200 |
'argv': sys.argv, |
|
201 |
'cwd': cwd, |
|
202 |
'hostname': socket.gethostname(), |
|
1543
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
203 |
'lcwd': lcwd, |
1538 | 204 |
}) |
1543
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
205 |
if exed!=cwd: store.update({'exed': exed, |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
206 |
'lexed': os.listdir(exed), |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
207 |
}) |
1538 | 208 |
if hasattr(os,'uname'): |
209 |
store.update({ |
|
210 |
'uname': os.uname(), |
|
211 |
'ctermid': os.ctermid(), |
|
212 |
'getgid': os.getgid(), |
|
213 |
'getuid': os.getuid(), |
|
214 |
'getegid': os.getegid(), |
|
215 |
'geteuid': os.geteuid(), |
|
216 |
'getlogin': os.getlogin(), |
|
217 |
'getgroups': os.getgroups(), |
|
218 |
'getpgrp': os.getpgrp(), |
|
219 |
'getpid': os.getpid(), |
|
220 |
'getppid': os.getppid(), |
|
221 |
}) |
|
222 |
if getScript: |
|
223 |
fn = os.path.abspath(sys.argv[0]) |
|
224 |
if os.path.isfile(fn): |
|
225 |
store['__script'] = open(fn,'r').read() |
|
226 |
module_versions = {} |
|
227 |
for n,m in sys.modules.items(): |
|
228 |
if n=='reportlab' or n=='rlextra' or n[:10]=='reportlab.' or n[:8]=='rlextra.': |
|
229 |
v = getattr(m,'__version__',None) |
|
230 |
if v: module_versions[n] = v |
|
231 |
store['__module_versions'] = module_versions |
|
232 |
self.store['__payload'] = {} |
|
233 |
self._add(kw) |
|
234 |
||
235 |
def _add(self,D): |
|
236 |
payload = self.store['__payload'] |
|
237 |
for k, v in D.items(): |
|
238 |
payload[k] = v |
|
239 |
||
240 |
def add(self,**kw): |
|
241 |
self._add(kw) |
|
242 |
||
243 |
def dump(self): |
|
244 |
import pickle |
|
245 |
pickle.dump(self.store,open(self.fn,'wb')) |
|
246 |
||
247 |
def load(self): |
|
248 |
import pickle |
|
249 |
self.store = pickle.load(open(self.fn,'rb')) |
|
250 |
||
251 |
def _show_module_versions(self,k,v): |
|
252 |
print k[2:] |
|
253 |
K = v.keys() |
|
254 |
K.sort() |
|
255 |
for k in K: |
|
256 |
vk = v[k] |
|
257 |
try: |
|
258 |
m = recursiveImport(k,sys.path[:],1) |
|
259 |
d = getattr(m,'__version__',None)==vk and 'SAME' or 'DIFFERENT' |
|
260 |
except: |
|
261 |
m = None |
|
262 |
d = '??????unknown??????' |
|
263 |
print ' %s = %s (%s)' % (k,vk,d) |
|
264 |
||
265 |
def _banner(self,k,what): |
|
266 |
print '###################%s %s##################' % (what,k[2:]) |
|
267 |
||
268 |
def _start(self,k): |
|
269 |
self._banner(k,'Start ') |
|
270 |
||
271 |
def _finish(self,k): |
|
272 |
self._banner(k,'Finish ') |
|
273 |
||
274 |
def _show_lines(self,k,v): |
|
275 |
self._start(k) |
|
276 |
print v |
|
277 |
self._finish(k) |
|
278 |
||
279 |
def _show_payload(self,k,v): |
|
280 |
if v: |
|
281 |
import pprint |
|
282 |
self._start(k) |
|
283 |
pprint.pprint(v) |
|
284 |
self._finish(k) |
|
285 |
||
286 |
specials = {'__module_versions': _show_module_versions, |
|
287 |
'__payload': _show_payload, |
|
288 |
'__traceback': _show_lines, |
|
289 |
'__script': _show_lines, |
|
290 |
} |
|
291 |
def show(self): |
|
1543
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
292 |
K = self.store.keys() |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
293 |
K.sort() |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
294 |
for k in K: |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
295 |
if k not in self.specials.keys(): print '%-15s = %s' % (k,self.store[k]) |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
296 |
for k in K: |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
297 |
if k in self.specials.keys(): apply(self.specials[k],(self,k,self.store[k])) |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
298 |
|
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
299 |
def payload(self,name): |
3681c7d8898d
Slight formatting improvements & added payload method
rgbecker
parents:
1538
diff
changeset
|
300 |
return self.store['__payload'][name] |
1561 | 301 |
|
302 |
def __setitem__(self,name,value): |
|
303 |
self.store['__payload'][name] = value |
|
304 |
||
305 |
def __getitem__(self,name): |
|
306 |
return self.store['__payload'][name] |