[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