[reportlab-users] How are split, wrap, wrapOn supposed to work?

Henning von Bargen H.vonBargen at t-p.com
Wed Oct 29 12:25:44 EDT 2014


Hi all,

after a long, long time I'm finally trying to make Wordaxe work with
ReportLab again (RL 3.1.8),
mainly because I'm going to use it in a commercial application.

The test case "test1" from the file
c:\wordaxe\trunk\tests\test_platypus_paragraphs.py
runs into an endless loop and I think this could be a bug in RL.

Adding print statements like """print "_listWrapOn", availWidth"""
in several places the ReportLab code (mainly in platypus\flowables.py)
and raising an exception in c:\wordaxe-svn\trunk\rl\NewParagraph.py
in the i_wrap method like this:

...
        def iter_widths(max_widths=max_widths):
            # an iterator that repeats the last element infinitely
            for w in max_widths: yield w
            while True: yield w
        width_iter = iter_widths()
        max_width = width_iter.next()
        if max_width < 0:
            raise ValueError("Paragraph id %s: Max width is < 0: %s.
Text: %s" % (id(self), max_width, self.text[:200]))
...
I could see this output for the test case:

ImageAndFlowables wrap returning 298.0 123
67246472 wrap 55.0 268435455
65397704 wrap 298.0 696.661417323
65397704 i_wrap 298.0 696.661417323 [298.0, 298.0]
ImageAndFlowables wrap 298.0 673.161417323
ImageAndFlowables _findSplit -3.0 122.2 
65388360 wrap -3.0 268435455
65388360 i_wrap -3.0 268435455 [-3.0, -3.0]
E
======================================================================
ERROR: test1 (__main__.ParagraphSplitTestCase)
This makes one long multi-page paragraph.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_platypus_paragraphs.py", line 317, in test1
    doc.multiBuild(story)
  File
"c:\Python27\lib\site-packages\reportlab\platypus\doctemplate.py", line
970, in multiBuild
    self.build(tempStory, **buildKwds)
  File
"c:\Python27\lib\site-packages\reportlab\platypus\doctemplate.py", line
890, in build
    self.handle_flowable(flowables)
  File
"c:\Python27\lib\site-packages\reportlab\platypus\doctemplate.py", line
773, in handle_flowab
le
    if frame.add(f, canv, trySplit=self.allowSplitting):
  File "c:\Python27\lib\site-packages\reportlab\platypus\frames.py",
line 161, in _add
    w, h = flowable.wrap(aW, h)
  File "c:\Python27\lib\site-packages\reportlab\platypus\flowables.py",
line 1195, in wrap
    W,H0,self._C0,self._C1 = self._findSplit(canv,self._iW,aH)
  File "c:\Python27\lib\site-packages\reportlab\platypus\flowables.py",
line 1266, in _findSplit
    w,h = f.wrapOn(canv,availWidth,0xfffffff)
  File "c:\Python27\lib\site-packages\reportlab\platypus\flowables.py",
line 121, in wrapOn
    w, h = self.wrap(aW,aH)
  File "c:\wordaxe-svn\wordaxe\rl\NewParagraph.py", line 536, in wrap
    return self.i_wrap(availW, availH, max_widths)
  File "c:\wordaxe-svn\wordaxe\rl\NewParagraph.py", line 563, in i_wrap
    raise ValueError("Paragraph id %s: Max width is < 0: %s. Text: %s" %
(id(self), max_width, self.
text[:200]))
ValueError: Paragraph id 65388360: Max width is < 0: -3.0. Text: The
CCCC of an integrated one box s
olution for advanced voice and data applications began with the
introduction of the IMACS. The IMACS
 200 carries on that tradition with an integrated solution optimi

The long numbers are from id(self), the numbers after the description
are usually availWidth/availHeight

Note: I changed the test data text a bit to see that the story fragment
caused the endless loop:
        story.append(Paragraph('Image larger than the frame',h3))
--->    story.append(ImageAndFlowables(... <---- causing the loop

It is remarkable that ImageAndFlowables calls _findSplit with a negative
availWidth,
which in turns calls the flowable's wrap method (here: of the WordAxe
Paragraph instance)
with a negative instance:

ImageAndFlowables _findSplit -3.0 122.2 
65388360 wrap -3.0 268435455

My gut feeling tells me that this is either a bug in RL or that I am
misunderstanding
something here.

So my main question is:

****************************************
How is a flowable's wrap method supposed to react when availWidth or
availHeight is <= 0?
****************************************

Running into an endless loop (as WordAxe does) is for sure not the best
solution.
I always assumed that wrap is only called after it has been assured that
everything fits.

And if this case is not expected, then it's a bug in ImageAndFlowable,
isn't it?

Furthermore, there are some bits in flowables.py that seem possibly
wrong:

1) In class Image:

    def identity(self,maxLen=None):
        r = Flowable.identity(self,maxLen)
        if r[-4:]=='>...' and isinstance(self.filename,str):
            r = "%s filename=%s>" % (r[:-4],self.filename)
        return r

   Shouldn't isinstance be used with basestr instead of str?

2) In ImageAndFlowables _findSplit method:

            if H>availHeight:
                from reportlab.platypus.paragraph import Paragraph
                aH = availHeight-(H-h)
                if isinstance(f,(Paragraph,Preformatted)):
                    leading = f.style.leading

    Using isinstance here doesn't look very pythonish
    and at the moment prevents this to work correctly with Wordaxe.


Best regards
Henning von Bargen


More information about the reportlab-users mailing list