Candidate fix for infinite looping
authorandy_robinson
Wed, 07 Jan 2004 22:58:54 +0000
changeset 2192 955d4bf3b9d2
parent 2191 11115dca3822
child 2193 e19196dc3942
Candidate fix for infinite looping
reportlab/lib/codecharts.py
reportlab/platypus/doctemplate.py
reportlab/platypus/flowables.py
--- a/reportlab/lib/codecharts.py	Wed Jan 07 16:36:34 2004 +0000
+++ b/reportlab/lib/codecharts.py	Wed Jan 07 22:58:54 2004 +0000
@@ -55,7 +55,9 @@
         """Fills boxes in order.  None means skip a box.
         Empty boxes at end get filled with gray"""
         extraNeeded = (self.rows * self.charsPerRow - len(charList))
-        charList = charList + [None] * extraNeeded
+        for i in range(extraNeeded):
+            charList.append(None)
+        #charList.extend([None] * extraNeeded)
         row = 0
         col = 0
         self.canv.setFont(self.fontName, self.boxSize * 0.75)
@@ -305,18 +307,18 @@
     cc3 = SingleByteEncodingChart(charsPerRow=25, hex=0)
     cc3.drawOn(c, 72, 100)
 
-    c.showPage()
-
-    c.setFont('Helvetica-Bold', 24)
-    c.drawString(72, 750, 'Multi-byte Kuten code chart examples')
-    KutenRowCodeChart(1, 'HeiseiMin-W3','EUC-H').drawOn(c, 72, 600)
-    KutenRowCodeChart(16, 'HeiseiMin-W3','EUC-H').drawOn(c, 72, 450)
-    KutenRowCodeChart(84, 'HeiseiMin-W3','EUC-H').drawOn(c, 72, 300)
-
-    c.showPage()
-    c.setFont('Helvetica-Bold', 24)
-    c.drawString(72, 750, 'Big5 Code Chart Examples')
-    #Big5CodeChart(0xA1, 'MSungStd-Light-Acro','ETenms-B5-H').drawOn(c, 72, 500)
+##    c.showPage()
+##
+##    c.setFont('Helvetica-Bold', 24)
+##    c.drawString(72, 750, 'Multi-byte Kuten code chart examples')
+##    KutenRowCodeChart(1, 'HeiseiMin-W3','EUC-H').drawOn(c, 72, 600)
+##    KutenRowCodeChart(16, 'HeiseiMin-W3','EUC-H').drawOn(c, 72, 450)
+##    KutenRowCodeChart(84, 'HeiseiMin-W3','EUC-H').drawOn(c, 72, 300)
+##
+##    c.showPage()
+##    c.setFont('Helvetica-Bold', 24)
+##    c.drawString(72, 750, 'Big5 Code Chart Examples')
+##    #Big5CodeChart(0xA1, 'MSungStd-Light-Acro','ETenms-B5-H').drawOn(c, 72, 500)
 
     c.save()
     print 'saved codecharts.pdf'
--- a/reportlab/platypus/doctemplate.py	Wed Jan 07 16:36:34 2004 +0000
+++ b/reportlab/platypus/doctemplate.py	Wed Jan 07 22:58:54 2004 +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.68 2003/11/13 17:15:19 william_ng Exp $
+#$Header: /tmp/reportlab/reportlab/platypus/doctemplate.py,v 1.69 2004/01/07 22:58:54 andy_robinson Exp $
 
-__version__=''' $Id: doctemplate.py,v 1.68 2003/11/13 17:15:19 william_ng Exp $ '''
+__version__=''' $Id: doctemplate.py,v 1.69 2004/01/07 22:58:54 andy_robinson Exp $ '''
 
 __doc__="""
 This module contains the core structure of platypus.
@@ -38,6 +38,8 @@
 from types import *
 import sys
 
+class LayoutError(Exception):
+    pass
 
 def _doNothing(canvas, doc):
     "Dummy callback for onPage"
@@ -111,6 +113,9 @@
     def __call__(self):
         return self
 
+    def identity(self, maxLen=None):
+        return "ActionFlowable: %s" % str(self.action)
+    
 class NextFrameFlowable(ActionFlowable):
     def __init__(self,ix,resume=0):
         ActionFlowable.__init__(self,('nextFrame',ix,resume))
@@ -306,6 +311,12 @@
         self._onProgress = None
         self._flowableCount = 0  # so we know how far to go
 
+
+        #infinite loop detection if we start doing lots of empty pages
+        self._curPageFlowableCount = 0
+        self._emptyPages = 0
+        self._emptyPagesAllowed = 3
+
         #context sensitive margins - set by story, not from outside
         self._leftExtraIndent = 0.0
         self._rightExtraIndent = 0.0
@@ -357,6 +368,8 @@
         self.pageTemplate.onPage(self.canv,self)
         for f in self.pageTemplate.frames: f._reset()
         self.beforePage()
+        #keep a count of flowables added to this page.  zero indicates bad stuff
+        self._curPageFlowableCount = 0
         if hasattr(self,'_nextFrameIndex'):
             del self._nextFrameIndex
         self.frame = self.pageTemplate.frames[0]
@@ -367,6 +380,15 @@
             check the next page template
             hang a page begin
         '''
+        #detect infinite loops...
+        if self._curPageFlowableCount == 0:
+            self._emptyPages = self._emptyPages + 1
+        else:
+            self._emptyPages = 0
+        if self._emptyPages >= self._emptyPagesAllowed:
+            raise LayoutError("More than %d pages generated without content - halting layout.  Likely that a flowable is too large for any frame." % self._emptyPagesAllowed)
+
+
         if self._onProgress:
             self._onProgress('PAGE', self.canv.getPageNumber())
         self.pageTemplate.afterDrawPage(self.canv, self)
@@ -507,6 +529,7 @@
         self.handle_breakBefore(flowables)
         self.handle_keepWithNext(flowables)
         f = flowables[0]
+        #print 'handling flowable %s' % f.identity()
         del flowables[0]
         if f is None:
             return
@@ -520,6 +543,7 @@
         else:
             #try to fit it then draw it
             if self.frame.add(f, self.canv, trySplit=self.allowSplitting):
+                self._curPageFlowableCount = self._curPageFlowableCount + 1
                 self.afterFlowable(f)
             else:
                 #if isinstance(f, KeepTogether): print 'could not add it to frame'
@@ -533,6 +557,7 @@
                 #if isinstance(f, KeepTogether): print 'n=%d' % n
                 if n:
                     if self.frame.add(S[0], self.canv, trySplit=0):
+                        self._curPageFlowableCount = self._curPageFlowableCount + 1
                         self.afterFlowable(S[0])
                     else:
                         print 'n = %d' % n
@@ -545,6 +570,7 @@
 ##                  if hasattr(f,'postponed'):
                     if hasattr(f,'_postponed'):
                         message = "Flowable %s too large on page %d" % (f.identity(30), self.page)
+                        #print message
                         #show us, it might be handy
                         #HACK = it seems within tables we sometimes
                         #get an empty paragraph that won't fit and this
--- a/reportlab/platypus/flowables.py	Wed Jan 07 16:36:34 2004 +0000
+++ b/reportlab/platypus/flowables.py	Wed Jan 07 22:58:54 2004 +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.43 2003/12/10 11:35:20 rgbecker Exp $
-__version__=''' $Id: flowables.py,v 1.43 2003/12/10 11:35:20 rgbecker Exp $ '''
+#$Header: /tmp/reportlab/reportlab/platypus/flowables.py,v 1.44 2004/01/07 22:58:54 andy_robinson Exp $
+__version__=''' $Id: flowables.py,v 1.44 2004/01/07 22:58:54 andy_robinson 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,
@@ -370,7 +370,7 @@
             self._img = None
             self._lazy = lazy
 
-    def identity(self,maxLen):
+    def identity(self,maxLen=None):
         r = Flowable.identity(self,maxLen)
         if r[-4:]=='>...' and type(self.filename) is StringType:
             r = "%s filename=%s>" % (r[:-4],self.filename)