[reportlab-users] Bug Report: Default parameter closure bug in several Graphics and Platypus classes

Nate Silva nate at desi.com
Tue Dec 1 13:40:51 EST 2009


SUMMARY

On this list yesterday I complained about, and Tim Roberts identified, a bug that causes Frames to be duplicated between PageTemplates.

See Tim Roberts' e-mail dated 30-Nov-2009 (US) / 01-Dec-2009 (EU).

Here is part of PageTemplate.__init__:

def __init__(self,id=None,frames=[],...):
self.frames = frames
# If the caller did not explicitly pass a value for frames,
# then self.frames now points to a list that is unique per
# CLASS, not per instance as you might expect.

In Python the default value of [] assigned to "frames" is shared by all instances of PageTemplate. That means that, if you do not explicitly specify a value for "frames," other instances of PageTemplate will share the list of Frames with previous instances:

template1 = PageTemplate(id='template1')
template1.frames.append(Frame(...))

template2 = PageTemplate(id='template2')
template2.frames.append(Frame(...))

# template2 now unexpectedly contains two frames!

WORKAROUND

As a workaround, users should always specify a value for the "frames" argument when creating a PageTemplate.

FIX

While the problem is subtle, the fix is simple. Quoting Tim Roberts:


> Probably this should be something like:

> def __init__(self,id=None,frames=None,...):

> if frames is None: frames = [:]

>

> Or, equally good:

>

> self.frames = frames[:]


FINDINGS

The bug occurs anywhere an empty list [] default argument is assigned to an instance variable. These are in the latest Subversion (revision 3604):

reportlab.graphics.shapes.Polygon (shapes.py:1208)
reportlab.graphics.shapes.PolyLine (shapes.py:1230)
reportlab.platypus.doctemplate.PageTemplate (doctemplate.py:246)
reportlab.platypus.flowables.KeepInFrame (flowables.py:878)
reportlab.platypus.flowables.FrameSplitter (flowables.py:1145)
reportlab.platypus.flowables.DocIf (flowables.py:1288)

SAMPLE CODE

A short example, showing how Python handles this:

http://gist.github.com/246507

A short example showing the bug in ReportLab itself:

http://gist.github.com/246511

Regards,
Nate


More information about the reportlab-users mailing list