--- a/reportlab/platypus/doctemplate.py Wed Aug 01 10:22:10 2001 +0000
+++ b/reportlab/platypus/doctemplate.py Wed Aug 01 13:01:44 2001 +0000
@@ -1,9 +1,9 @@
#copyright ReportLab Inc. 2000
#see license.txt for license details
#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/doctemplate.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/platypus/doctemplate.py,v 1.40 2001/05/11 15:00:52 rgbecker Exp $
+#$Header: /tmp/reportlab/reportlab/platypus/doctemplate.py,v 1.41 2001/08/01 13:01:44 rgbecker Exp $
-__version__=''' $Id: doctemplate.py,v 1.40 2001/05/11 15:00:52 rgbecker Exp $ '''
+__version__=''' $Id: doctemplate.py,v 1.41 2001/08/01 13:01:44 rgbecker Exp $ '''
__doc__="""
This module contains the core structure of platypus.
@@ -408,15 +408,7 @@
if self.frame.add(S[0], self.canv, trySplit=0):
self.afterFlowable(S[0])
else:
- if hasattr(f,'text'):
- print 'Offending text:'
- print "'''"+f.text+"'''"
- print f.style.fontName, f.style.fontSize, f.style.leading, f.style.firstLineIndent, f.style.leftIndent, f.style.rightIndent
- print S[0].style.fontName, S[0].style.fontSize, S[0].style.leading, S[0].style.firstLineIndent, S[0].style.leftIndent, S[0].style.rightIndent
- elif hasattr(f, 'getPlainText'):
- print 'Offending Paragraph:'
- print f.getPlainText()
- raise "LayoutError", "splitting error type=%s" % type(f)
+ raise "LayoutError", "splitting error on page %d in\n%s" % (self.page,f.identity(30))
del S[0]
for f in xrange(n-1):
flowables.insert(f,S[f]) # put split flowables back on the list
@@ -424,14 +416,11 @@
# this must be cleared when they are finally drawn!
## if hasattr(f,'postponed'):
if hasattr(f,'_postponed'):
- message = "Flowable %s too large on page %d" % (f, self.page)
+ message = "Flowable %s too large on page %d" % (f.identity(30), self.page)
#show us, it might be handy
#HACK = it seems within tables we sometimes
#get an empty paragraph that won't fit and this
#causes it to fall over. FIXME FIXME FIXME
- if hasattr(f, 'getPlainText'):
- print 'Offending Paragraph:'
- print f.getPlainText()
raise "LayoutError", message
## f.postponed = 1
f._postponed = 1
--- a/reportlab/platypus/flowables.py Wed Aug 01 10:22:10 2001 +0000
+++ b/reportlab/platypus/flowables.py Wed Aug 01 13:01:44 2001 +0000
@@ -1,8 +1,8 @@
#copyright ReportLab Inc. 2000
#see license.txt for license details
#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/flowables.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/platypus/flowables.py,v 1.20 2001/06/22 11:23:48 rgbecker Exp $
-__version__=''' $Id: flowables.py,v 1.20 2001/06/22 11:23:48 rgbecker Exp $ '''
+#$Header: /tmp/reportlab/reportlab/platypus/flowables.py,v 1.21 2001/08/01 13:01:44 rgbecker Exp $
+__version__=''' $Id: flowables.py,v 1.21 2001/08/01 13:01:44 rgbecker Exp $ '''
__doc__="""
A flowable is a "floating element" in a document whose exact position is determined by the
other elements that precede it, such as a paragraph, a diagram interspersed between paragraphs,
@@ -108,6 +108,22 @@
"""Hook for IndexingFlowables - things which have cross references"""
return 0
+ def identity(self, maxLen=None):
+ '''
+ This method should attempt to return a string that can be used to identify
+ a particular flowable uniquely. The result can then be used for debugging
+ and or error printouts
+ '''
+ if hasattr(self, 'getPlainText'):
+ r = self.getPlainText()
+ elif hasattr(self, 'text'):
+ r = self.text
+ else:
+ r = '...'
+ if r and maxLen:
+ r = r[:maxLen]
+ return "<%s at %d>%s" % (self.__class__.__name__, id(self), r)
+
class XBox(Flowable):
"""Example flowable - a box with an x through it and a caption.
This has a known size, so does not need to respond to wrap()."""
@@ -230,7 +246,7 @@
def __init__(self, filename, width=None, height=None):
"""If size to draw at not specified, get it from the image."""
from reportlab.lib.utils import PIL_Image #this will raise an error if they do not have PIL.
- self.filename = filename
+ self._filename = self.filename = filename
self.hAlign = 'CENTER'
# if it is a JPEG, will be inlined within the file -
# but we still need to know its size now
@@ -240,7 +256,7 @@
self.imageHeight = info[1]
else:
# we have to assume this is a file like object
- self. filename = img = PIL_Image.open(filename)
+ self.filename = img = PIL_Image.open(filename)
(self.imageWidth, self.imageHeight) = img.size
if width:
self.drawWidth = width
@@ -263,6 +279,13 @@
self.drawWidth,
self.drawHeight
)
+
+ def identity(self,maxLen):
+ r = Flowable.identity(self,maxLen)
+ if r[-4:]=='>...' and type(self._filename) is StringType:
+ r = "%s filename=%s>" % (r[:-4],self._filename)
+ return r
+
class Spacer(Flowable):
"""A spacer just takes up space and doesn't draw anything - it guarantees
a gap between objects."""
@@ -353,5 +376,3 @@
return (0,0)
def draw(self):
exec self.command in globals(), {'canvas':self.canv}
-
-
--- a/reportlab/platypus/tables.py Wed Aug 01 10:22:10 2001 +0000
+++ b/reportlab/platypus/tables.py Wed Aug 01 13:01:44 2001 +0000
@@ -1,8 +1,8 @@
#copyright ReportLab Inc. 2000
#see license.txt for license details
#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/tables.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/platypus/tables.py,v 1.39 2001/05/05 13:37:10 aaron_watters Exp $
-__version__=''' $Id: tables.py,v 1.39 2001/05/05 13:37:10 aaron_watters Exp $ '''
+#$Header: /tmp/reportlab/reportlab/platypus/tables.py,v 1.40 2001/08/01 13:01:44 rgbecker Exp $
+__version__=''' $Id: tables.py,v 1.40 2001/08/01 13:01:44 rgbecker Exp $ '''
__doc__="""
Tables are created by passing the constructor a tuple of column widths, a tuple of row heights and the data in
row order. Drawing of the table can be controlled by using a TableStyle instance. This allows control of the
@@ -25,6 +25,7 @@
from reportlab.platypus import *
from reportlab.lib.styles import PropertySet, getSampleStyleSheet
from reportlab.lib import colors
+from reportlab.lib.utils import fp_str
from reportlab.pdfbase import pdfmetrics
import operator, string
@@ -110,23 +111,23 @@
def __init__(self, data, colWidths=None, rowHeights=None, style=None,
repeatRows=0, repeatCols=0, splitByRow=1):
#print "colWidths", colWidths
- nrows = len(data)
+ self._nrows = nrows = len(data)
if len(data)==0 or type(data) not in _SeqTypes:
- raise ValueError, "Table must have at least 1 row"
+ raise ValueError, "%s must have at least 1 row" % self.identity()
ncols = max(map(_rowLen,data))
if not ncols:
- raise ValueError, "Table must have at least 1 column"
+ raise ValueError, "%s must have at least 1 column" % self.identity()
if colWidths is None: colWidths = ncols*[None]
elif len(colWidths) != ncols:
- raise ValueError, "Data error - %d columns in data but %d in grid" % (ncols, len(colWidths))
+ raise ValueError, "%s data error - %d columns in data but %d in grid" % (self.identity(),ncols, len(colWidths))
if rowHeights is None: rowHeights = nrows*[None]
elif len(rowHeights) != nrows:
- raise ValueError, "Data error - %d rows in data but %d in grid" % (nrows, len(rowHeights))
- self._nrows = nrows
- ncols = self._ncols = len(colWidths)
+ raise ValueError, "%s data error - %d rows in data but %d in grid" % (self.identity(),nrows, len(rowHeights))
+ ncols = len(colWidths)
for i in range(nrows):
if len(data[i]) != ncols:
- raise ValueError, "Not enough data points in row %d!" % i
+ raise ValueError, "%s not enough data points in row %d!" % (self.identity(),i)
+ self._ncols = ncols
self._rowHeights = self._argH = rowHeights
self._colWidths = self._argW = colWidths
self._cellvalues = data
@@ -163,6 +164,43 @@
cv = string.replace(cv, "\n", "\n ")
return "Table(\n rowHeights=%s,\n colWidths=%s,\n%s\n) # end table" % (r,c,cv)
+ def identity(self, maxLen):
+ '''Identify our selves as well as possible'''
+ vx = None
+ nr = self._nrows
+ if not hasattr(self,'_ncols'):
+ nc = 'unknown'
+ else:
+ nc = self._ncols
+ cv = self._cellvalues
+ b = 0
+ for i in xrange(nr):
+ for j in xrange(nc):
+ v = cv[i][j]
+ t = type(v)
+ if t in _SeqTypes or isinstance(v,Flowable):
+ if not t in _SeqTypes: v = (v,)
+ r = ''
+ for vij in v:
+ r = vij.identity(maxLen)
+ if r and r[-4:]!='>...':
+ break
+ if r and r[-4:]!='>...':
+ ix, jx, vx, b = i, j, r, 1
+ else:
+ v = v is None and '' or str(v)
+ ix, jx, vx = i, j, v
+ b = (vx and t is StringType) and 1 or 0
+ if maxLen: vx = vx[:maxLen]
+ if b: break
+ if b: break
+ if vx:
+ vx = ' with cell(%d,%d) containing\n%s' % (ix,jx,repr(vx))
+ else:
+ vx = '...'
+
+ return "<%s at %d %d rows x %s cols>%s" % (self.__class__.__name__, id(self), nr, nc, vx)
+
def _calc(self):
if hasattr(self,'_width'): return
@@ -179,18 +217,19 @@
V = self._cellvalues[i] # values for row i
S = self._cellStyles[i] # styles for row i
h = 0
+ j = 0
for v, s, w in map(None, V, S, W): # value, style, width (lengths must match)
- #print "v,s,w", v,s,w
+ j = j + 1
t = type(v)
if t in _SeqTypes or isinstance(v,Flowable):
if not t in _SeqTypes: v = (v,)
if w is None:
- raise ValueError, "Flowables cell can't have auto width"
+ raise ValueError, "Flowable %s in cell(%d,%d) can't have auto width in\n%s" % (v[0].identity(30),i,j,self.identity(30))
dW,t = _listCellGeom(v,w,s)
#print "leftpadding, rightpadding", s.leftPadding, s.rightPadding
dW = dW + s.leftPadding + s.rightPadding
if dW>w:
- raise "LayoutError", "Flowable %s (%sx%s points) too wide for cell (%sx* points)." % (v,dW,t,w)
+ raise "LayoutError", "Flowable %s (%sx%s points) too wide for cell(%d,%d) (%sx* points) in\n%s" % (v[0].identity(30),fp_str(dW),fp_str(t),i,j, fp_str(w), self.identity(30))
else:
if t is not StringType:
v = v is None and '' or str(v)
@@ -205,22 +244,24 @@
W = W[:]
self._colWidths = W
while None in W:
- i = W.index(None)
- f = lambda x,i=i: operator.getitem(x,i)
+ j = W.index(None)
+ f = lambda x,j=j: operator.getitem(x,j)
V = map(f,self._cellvalues)
S = map(f,self._cellStyles)
w = 0
+ i = 0
d = hasattr(self,'canv') and self.canv or pdfmetrics
for v, s in map(None, V, S):
+ i = i + 1
t = type(v)
if t in _SeqTypes or isinstance(v,Flowable):
- raise ValueError, "Flowables cell can't have auto width"
+ raise ValueError, "Flowable %s in cell(%d,%d) can't have auto width\n%s" % (v.identity(30),i,j,self.identity(30))
elif t is not StringType: v = v is None and '' or str(v)
v = string.split(v, "\n")
t = s.leftPadding+s.rightPadding + max(map(lambda a, b=s.fontname,
c=s.fontsize,d=d.stringWidth: d(a,b,c), v))
if t>w: w = t #record a new maximum
- W[i] = w
+ W[j] = w
height = self._height = reduce(operator.add, H, 0)
#print "height, H", height, H
@@ -954,6 +995,7 @@
I = Image(os.path.join(os.path.dirname(reportlab.platypus.__file__),'..','demos','pythonpoint','leftlogo.gif'))
I.drawHeight = 1.25*inch*I.drawHeight / I.drawWidth
I.drawWidth = 1.25*inch
+ I.drawWidth = 9.25*inch #uncomment to see better messaging
P = Paragraph("<para align=center spaceb=3>The <b>ReportLab Left <font color=red>Logo</font></b> Image</para>", styleSheet["BodyText"])
data= [['A', 'B', 'C', Paragraph("<b>A pa<font color=red>r</font>a<i>graph</i></b><super><font color=yellow>1</font></super>",styleSheet["BodyText"]), 'D'],
['00', '01', '02', [I,P], '04'],