reportlab/lib/utils.py
author rgbecker
Sat, 13 Apr 2002 15:16:34 +0000
changeset 1580 50792f072538
parent 1575 7d2360bdfc4d
child 1584 33f2934aa2de
permissions -rw-r--r--
use generalised StringIO instance interface
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
494
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 474
diff changeset
     1
#copyright ReportLab Inc. 2000
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 474
diff changeset
     2
#see license.txt for license details
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 474
diff changeset
     3
#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/lib/utils.py?cvsroot=reportlab
1580
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
     4
#$Header: /tmp/reportlab/reportlab/lib/utils.py,v 1.31 2002/04/13 15:16:34 rgbecker Exp $
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
     5
__version__=''' $Id: utils.py,v 1.31 2002/04/13 15:16:34 rgbecker Exp $ '''
562
6c9408ec3302 Minor neglectable changes.
dinu_gherman
parents: 519
diff changeset
     6
1375
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
     7
import string, os, sys
413
6312e8296c9b Initial version
rgbecker
parents:
diff changeset
     8
from types import *
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
     9
from reportlab.lib.logger import warnOnce
413
6312e8296c9b Initial version
rgbecker
parents:
diff changeset
    10
SeqTypes = (ListType,TupleType)
562
6c9408ec3302 Minor neglectable changes.
dinu_gherman
parents: 519
diff changeset
    11
1143
46a5ec2d3d2c Better import error checking
rgbecker
parents: 998
diff changeset
    12
def _checkImportError(errMsg):
46a5ec2d3d2c Better import error checking
rgbecker
parents: 998
diff changeset
    13
	if string.lower(string.strip(str(errMsg)[0:16]))!='no module named': raise
46a5ec2d3d2c Better import error checking
rgbecker
parents: 998
diff changeset
    14
413
6312e8296c9b Initial version
rgbecker
parents:
diff changeset
    15
try:
6312e8296c9b Initial version
rgbecker
parents:
diff changeset
    16
	#raise ImportError
519
0452f833153c mods permitting late string conversions
aaron_watters
parents: 494
diff changeset
    17
	### NOTE!  FP_STR SHOULD PROBABLY ALWAYS DO A PYTHON STR() CONVERSION ON ARGS
0452f833153c mods permitting late string conversions
aaron_watters
parents: 494
diff changeset
    18
	### IN CASE THEY ARE "LAZY OBJECTS".  ACCELLERATOR DOESN'T DO THIS (YET)
474
5c5a9505fba1 Changes to make freezing easier
rgbecker
parents: 452
diff changeset
    19
	try:
1143
46a5ec2d3d2c Better import error checking
rgbecker
parents: 998
diff changeset
    20
		from _rl_accel import fp_str				# in case of builtin version
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    21
	except ImportError, errMsg:
1143
46a5ec2d3d2c Better import error checking
rgbecker
parents: 998
diff changeset
    22
		_checkImportError(errMsg)
46a5ec2d3d2c Better import error checking
rgbecker
parents: 998
diff changeset
    23
		from reportlab.lib._rl_accel import fp_str	# specific
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    24
except ImportError, errMsg:
1153
58081552b836 eliminated requirement for _rl_accel
aaron_watters
parents: 1143
diff changeset
    25
	#_checkImportError(errMsg) # this effectively requires _rl_accel... should not be required
413
6312e8296c9b Initial version
rgbecker
parents:
diff changeset
    26
	def fp_str(*a):
6312e8296c9b Initial version
rgbecker
parents:
diff changeset
    27
		if len(a)==1 and type(a[0]) in SeqTypes: a = a[0]
6312e8296c9b Initial version
rgbecker
parents:
diff changeset
    28
		s = []
6312e8296c9b Initial version
rgbecker
parents:
diff changeset
    29
		for i in a:
1537
799116e10b88 Small fp_str fixes
rgbecker
parents: 1489
diff changeset
    30
			s.append('%0.6f' % i)
413
6312e8296c9b Initial version
rgbecker
parents:
diff changeset
    31
		return string.join(s)
448
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
    32
981
b3dfa2ba427c Attempt to fix the locale mismatch problem
rgbecker
parents: 962
diff changeset
    33
#hack test for comma users
b3dfa2ba427c Attempt to fix the locale mismatch problem
rgbecker
parents: 962
diff changeset
    34
if ',' in fp_str(0.25):
b3dfa2ba427c Attempt to fix the locale mismatch problem
rgbecker
parents: 962
diff changeset
    35
	_FP_STR = fp_str
b3dfa2ba427c Attempt to fix the locale mismatch problem
rgbecker
parents: 962
diff changeset
    36
	def fp_str(*a):
b3dfa2ba427c Attempt to fix the locale mismatch problem
rgbecker
parents: 962
diff changeset
    37
		return string.replace(apply(_FP_STR,a),',','.')
b3dfa2ba427c Attempt to fix the locale mismatch problem
rgbecker
parents: 962
diff changeset
    38
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
    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
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
    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
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    64
def import_zlib():
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    65
	try:
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    66
		import zlib
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    67
	except ImportError, errMsg:
1143
46a5ec2d3d2c Better import error checking
rgbecker
parents: 998
diff changeset
    68
		_checkImportError(errMsg)
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    69
		zlib = None
1470
fa7ec8bb0816 Added Bernhard Herzog's import_zlib fix
rgbecker
parents: 1396
diff changeset
    70
		from reportlab.rl_config import ZLIB_WARNINGS
962
366d703f3436 Added PIL_WARNINGS/ZLIB_WARNINGS
rgbecker
parents: 822
diff changeset
    71
		if ZLIB_WARNINGS: warnOnce('zlib not available')
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    72
	return zlib
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    73
760
0e51a12a0e39 Changed to PIL_Image
rgbecker
parents: 677
diff changeset
    74
try:
761
ddacc2f18b6f Changed to prefer PIL as package
rgbecker
parents: 760
diff changeset
    75
	from PIL import Image
760
0e51a12a0e39 Changed to PIL_Image
rgbecker
parents: 677
diff changeset
    76
except ImportError, errMsg:
1143
46a5ec2d3d2c Better import error checking
rgbecker
parents: 998
diff changeset
    77
	_checkImportError(errMsg)
998
501275d17bef Imported PIL_WARNINGS
rgbecker
parents: 981
diff changeset
    78
	from reportlab.rl_config import PIL_WARNINGS
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    79
	try:
761
ddacc2f18b6f Changed to prefer PIL as package
rgbecker
parents: 760
diff changeset
    80
		import Image
962
366d703f3436 Added PIL_WARNINGS/ZLIB_WARNINGS
rgbecker
parents: 822
diff changeset
    81
		if PIL_WARNINGS: warnOnce('Python Imaging Library not available as package; upgrade your installation!')
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    82
	except ImportError, errMsg:
1143
46a5ec2d3d2c Better import error checking
rgbecker
parents: 998
diff changeset
    83
		_checkImportError(errMsg)
760
0e51a12a0e39 Changed to PIL_Image
rgbecker
parents: 677
diff changeset
    84
		Image = None
962
366d703f3436 Added PIL_WARNINGS/ZLIB_WARNINGS
rgbecker
parents: 822
diff changeset
    85
		if PIL_WARNINGS: warnOnce('Python Imaging Library not available')
760
0e51a12a0e39 Changed to PIL_Image
rgbecker
parents: 677
diff changeset
    86
PIL_Image = Image
0e51a12a0e39 Changed to PIL_Image
rgbecker
parents: 677
diff changeset
    87
del Image
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
    88
1580
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    89
__StringIO=None
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    90
def getStringIO(buf=None):
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    91
	'''unified StringIO instance interface'''
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    92
	global __StringIO
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    93
	if not __StringIO:
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    94
		try:
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    95
			from cStringIO import StringIO
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    96
		except ImportError:
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    97
			from StringIO import StringIO
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    98
		__StringIO = StringIO
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
    99
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
   100
	s = __StringIO()	#avoid mismatch between StringIO and cStringIO
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
   101
						#initialised cStringIO has no write method
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
   102
	if buf is not None: s.write(buf)
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
   103
	return s
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
   104
1375
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   105
class ArgvDictValue:
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   106
	'''A type to allow clients of getArgvDict to specify a conversion function'''
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   107
	def __init__(self,value,func):
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   108
		self.value = value
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   109
		self.func = func
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   110
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   111
def getArgvDict(**kw):
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   112
	'''	Builds a dictionary from its keyword arguments with overrides from sys.argv.
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   113
		Attempts to be smart about conversions, but the value can be an instance
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   114
		of ArgDictValue to allow specifying a conversion function.
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   115
	'''
1387
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   116
	def handleValue(v,av,func):
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   117
		if func:
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   118
			v = func(av)
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   119
		else:
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   120
			t = type(v)
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   121
			if t is StringType:
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   122
				v = av
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   123
			elif t is FloatType:
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   124
				v = float(av)
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   125
			elif t is IntType:
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   126
				v = int(av)
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   127
			elif t is ListType:
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   128
				v = list(eval(av))
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   129
			elif t is TupleType:
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   130
				v = tuple(eval(av))
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   131
			else:
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   132
				raise TypeError, "Can't convert string '%s' to %s" % (av,str(t))
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   133
		return v
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   134
1375
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   135
	A = sys.argv[1:]
1387
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   136
	R = {}
1375
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   137
	for k, v in kw.items():
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   138
		if isinstance(v,ArgvDictValue):
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   139
			v, func = v.value, v.func
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   140
		else:
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   141
			func = None
1387
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   142
		handled = 0
1375
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   143
		ke = k+'='
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   144
		for a in A:
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   145
			if string.find(a,ke)==0:
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   146
				av = a[len(ke):]
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   147
				A.remove(a)
1387
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   148
				R[k] = handleValue(v,av,func)
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   149
				handled = 1
1375
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   150
				break
1387
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   151
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   152
		if not handled: R[k] = handleValue(v,v,func)
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   153
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   154
	return R
1375
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   155
452
6bb011a0d63e Initial version of D Yoo's pyHnj
rgbecker
parents: 448
diff changeset
   156
def getHyphenater(hDict=None):
6bb011a0d63e Initial version of D Yoo's pyHnj
rgbecker
parents: 448
diff changeset
   157
	try:
6bb011a0d63e Initial version of D Yoo's pyHnj
rgbecker
parents: 448
diff changeset
   158
		from reportlab.lib.pyHnj import Hyphen
6bb011a0d63e Initial version of D Yoo's pyHnj
rgbecker
parents: 448
diff changeset
   159
		if hDict is None: hDict=os.path.join(os.path.dirname(__file__),'hyphen.mashed')
6bb011a0d63e Initial version of D Yoo's pyHnj
rgbecker
parents: 448
diff changeset
   160
		return Hyphen(hDict)
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
   161
	except ImportError, errMsg:
677
35ba945c5572 Exception tests need str()
rgbecker
parents: 674
diff changeset
   162
		if str(errMsg)!='No module named pyHnj': raise
452
6bb011a0d63e Initial version of D Yoo's pyHnj
rgbecker
parents: 448
diff changeset
   163
		return None
6bb011a0d63e Initial version of D Yoo's pyHnj
rgbecker
parents: 448
diff changeset
   164
448
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   165
def _className(self):
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   166
	'''Return a shortened class name'''
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   167
	try:
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   168
		name = self.__class__.__name__
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   169
		i=string.rfind(name,'.')
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   170
		if i>=0: return name[i+1:]
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   171
		return name
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   172
	except AttributeError:
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   173
		return str(self)
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   174
1575
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   175
def open_for_read(name,mode='b'):
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   176
	'''attempt to open a file or URL for reading'''
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   177
	import urllib
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   178
	try:
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   179
		t, o = urllib.splittype(name)
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   180
		if not t or t=='file': raise ValueError
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   181
		o = urllib.urlopen(name)
1580
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
   182
		return getStringIO(o.read())
1575
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   183
	except:
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   184
		return open(name,'r'+mode)
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   185
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   186
class DebugMemo:
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   187
	'''Intended as a simple report back encapsulator
1545
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   188
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   189
	Typical usages
1545
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   190
	1) To record error data		
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   191
		dbg = DebugMemo(fn='dbgmemo.dbg',myVar=value)		
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   192
		dbg.add(anotherPayload='aaaa',andagain='bbb')
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   193
		dbg.dump()
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   194
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   195
	2) To show the recorded info
1545
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   196
		dbg = DebugMemo(fn='dbgmemo.dbg',mode='r')
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   197
		dbg.load()
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   198
		dbg.show()
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   199
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   200
	3) To re-use recorded information
1545
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   201
		dbg = DebugMemo(fn='dbgmemo.dbg',mode='r')
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   202
			dbg.load()
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   203
		myTestFunc(dbg.payload('myVar'),dbg.payload('andagain'))
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   204
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   205
	in addition to the payload variables the dump records many useful bits
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   206
	of information which are also printed in the show() method.
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   207
	'''
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   208
	def __init__(self,fn='rl_dbgmemo.dbg',mode='w',getScript=1,modules=(),**kw):
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   209
		import time, socket
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   210
		self.fn = fn
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   211
		if mode!='w': return
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   212
		self.store = store = {}
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   213
		if sys.exc_info() != (None,None,None):
1580
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
   214
			import traceback
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
   215
			s = getStringIO()
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   216
			traceback.print_exc(None,s)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   217
			store['__traceback'] = s.getvalue()
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   218
		cwd=os.getcwd()
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   219
		lcwd = os.listdir(cwd)
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   220
		exed = os.path.abspath(os.path.dirname(sys.argv[0]))
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   221
		store.update({	'gmt': time.asctime(time.gmtime(time.time())),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   222
						'platform': sys.platform,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   223
						'version': sys.version,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   224
						'executable': sys.executable,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   225
						'prefix': sys.prefix,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   226
						'path': sys.path,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   227
						'argv': sys.argv,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   228
						'cwd': cwd,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   229
						'hostname': socket.gethostname(),
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   230
						'lcwd': lcwd,
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   231
						})
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   232
		if exed!=cwd: store.update({'exed': exed,
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   233
									'lexed': os.listdir(exed),
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   234
									})
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   235
		if hasattr(os,'uname'):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   236
			store.update({
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   237
				'uname': os.uname(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   238
				'ctermid': os.ctermid(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   239
				'getgid': os.getgid(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   240
				'getuid': os.getuid(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   241
				'getegid': os.getegid(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   242
				'geteuid': os.geteuid(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   243
				'getlogin': os.getlogin(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   244
				'getgroups': os.getgroups(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   245
				'getpgrp': os.getpgrp(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   246
				'getpid': os.getpid(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   247
				'getppid': os.getppid(),
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   248
				})
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   249
		if getScript:
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   250
			fn = os.path.abspath(sys.argv[0])
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   251
			if os.path.isfile(fn):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   252
				store['__script'] = open(fn,'r').read()
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   253
		module_versions = {}
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   254
		for n,m in sys.modules.items():
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   255
			if n=='reportlab' or n=='rlextra' or n[:10]=='reportlab.' or n[:8]=='rlextra.':
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   256
				v = getattr(m,'__version__',None)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   257
				if v: module_versions[n] = v
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   258
		store['__module_versions'] = module_versions
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   259
		self.store['__payload'] = {}
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   260
		self._add(kw)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   261
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   262
	def _add(self,D):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   263
		payload = self.store['__payload']
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   264
		for k, v in D.items():
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   265
			payload[k] = v
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   266
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   267
	def add(self,**kw):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   268
		self._add(kw)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   269
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   270
	def dump(self):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   271
		import pickle
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   272
		pickle.dump(self.store,open(self.fn,'wb'))
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   273
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   274
	def load(self):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   275
		import pickle
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   276
		self.store = pickle.load(open(self.fn,'rb'))
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   277
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   278
	def _show_module_versions(self,k,v):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   279
		print k[2:]
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   280
		K = v.keys()
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   281
		K.sort()
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   282
		for k in K:
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   283
			vk = v[k]
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   284
			try:
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   285
				m = recursiveImport(k,sys.path[:],1)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   286
				d = getattr(m,'__version__',None)==vk and 'SAME' or 'DIFFERENT'
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   287
			except:
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   288
				m = None
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   289
				d = '??????unknown??????'
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   290
			print '  %s = %s (%s)' % (k,vk,d)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   291
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   292
	def _banner(self,k,what):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   293
		print '###################%s %s##################' % (what,k[2:])
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   294
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   295
	def _start(self,k):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   296
		self._banner(k,'Start  ')
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   297
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   298
	def _finish(self,k):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   299
		self._banner(k,'Finish ')
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   300
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   301
	def _show_lines(self,k,v):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   302
		self._start(k)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   303
		print v
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   304
		self._finish(k)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   305
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   306
	def _show_payload(self,k,v):
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   307
		if v:
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   308
			import pprint
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   309
			self._start(k)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   310
			pprint.pprint(v)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   311
			self._finish(k)
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   312
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   313
	specials = {'__module_versions': _show_module_versions,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   314
				'__payload': _show_payload,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   315
				'__traceback': _show_lines,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   316
				'__script': _show_lines,
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   317
				}
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   318
	def show(self):
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   319
		K = self.store.keys()
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   320
		K.sort()
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   321
		for k in K:
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   322
			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
   323
		for k in K:
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   324
			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
   325
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   326
	def payload(self,name):
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   327
		return self.store['__payload'][name]
1561
1b10f25e76df Add DebugMemo __g/setitem__
rgbecker
parents: 1545
diff changeset
   328
1b10f25e76df Add DebugMemo __g/setitem__
rgbecker
parents: 1545
diff changeset
   329
	def __setitem__(self,name,value):
1b10f25e76df Add DebugMemo __g/setitem__
rgbecker
parents: 1545
diff changeset
   330
		self.store['__payload'][name] = value
1b10f25e76df Add DebugMemo __g/setitem__
rgbecker
parents: 1545
diff changeset
   331
1b10f25e76df Add DebugMemo __g/setitem__
rgbecker
parents: 1545
diff changeset
   332
	def __getitem__(self,name):
1b10f25e76df Add DebugMemo __g/setitem__
rgbecker
parents: 1545
diff changeset
   333
		return self.store['__payload'][name]