[reportlab-users] Buggy interaction with flowables.py

Aaron Darling reportlab-users@reportlab.com
Thu, 1 Apr 2004 00:16:25 -0600 (CST)


Hi, I've been using Zope BackTalk in conjunction with ReportLab's PDF
generation facilities.  Overall the software has been working
satisfactorily, but I'd like to mention a buggy interaction between
backtalk and ReportLab that I encountered.

Whenever I tried to render a PDF document from backtalk pages that
contain images I would get the following error message (and traceback):

Traceback (innermost last):
Module ZPublisher.Publish, line 98, in publish
Module ZPublisher.mapply, line 88, in mapply
Module ZPublisher.Publish, line 39, in call_object
Module Products.BackTalk.BackTalk, line 356, in manage_makePDF
Module Products.BackTalk.BackTalk, line 393, in makePDF
Module Products.BackTalk.PDFClass, line 292, in __call__
Module Products.BackTalk.PDFClass, line 119, in get_output
Module Products.BackTalk.PDFClass, line 119, in <lambda>
Module Products.BackTalk.PDFClass, line 162, in finish
Module reportlab.platypus.flowables, line 317, in __init__
Module reportlab.platypus.flowables, line 326, in _setup
Module reportlab.platypus.flowables, line 332, in _setup_inner
Module reportlab.platypus.flowables, line 348, in __getattr__
Module reportlab.lib.utils, line 319, in __init__
Module PIL.Image, line 1543, in open

IOError: [Errno 2] No such file or directory: '<StringO object at
0x8d19bd8>'

After much debugging (and learning some python!) I determined the cause of
the problem.
It seems that BackTalk reads in the image file and writes it to a
cStringIO object.  This cStringIO object is then passed to the ReportLab
Image() class as the filename parameter along with the width and height
in 'proportional' mode.  During initialization, the reportlab Image class
runs the following code:

    def __init__(self, filename, width=None, height=None, kind='direct',
mask="auto", lazy=1):
        """If size to draw at not specified, get it from the image."""
        self.hAlign = 'CENTER'
        self._mask = mask
        # if it is a JPEG, will be inlined within the file -
        # but we still need to know its size now
        fp = hasattr(filename,'read')
        if fp:
            self.filename = `filename`
        else:
            self.filename = filename

Because the cStringIO object passed as filename has a 'read' attribute,
self.filename gets the value of `filename`, which ends up being the object
type and address: <StringO object at 0x8d19bd8>
Later, this value is passed as a filename to the Python Imaging Library's
Image.open() function, which of course can't open a file by that name.

I was able to resolve this problem by changing the lines:
        if fp:
            self.filename = `filename`
to:
        if fp:
            self.filename = filename


As I said, I'm new to python, ReportLab, BackTalk, and PIL, and I don't
know whether what I've come up with is the right solution to the problem.
Could somebody else comment?  Do these changes break other functionality?

BTW, I'm using Zope 2.6.1 with Python 2.1.3, BackTalk from CVS, Python
Imaging Library 1.1.4 and ReportLab 1.19.

Thanks
-Aaron