[reportlab-users] PageTemplate unexpectedly copies Frames from earlier PageTemplates

Tim Roberts timr at probo.com
Mon Nov 30 19:59:55 EST 2009


Nate Silva wrote:

> I've been pulling my hair out and finally boiled it down to the following snippet. Is this a bug?

>


My goodness! It's the famous default parameter closure bug, but it's
uncommon to find this in code actually released in the wild.

class PageTemplate:
"""
essentially a list of Frames and an onPage routine to call at the start
of a page when this is selected. onPageEnd gets called at the end.
derived classes can also implement beforeDrawPage and afterDrawPage
if they
"""
def __init__(self,id=None,frames=[],onPage=_doNothing,
onPageEnd=_doNothing,
pagesize=None):
if type(frames) not in (ListType,TupleType): frames = [frames]
assert filter(lambda x: not isinstance(x,Frame), frames)==[],
"frames argument error")
self.id = id
self.frames = frames
self.onPage = onPage

The problem here is that all of the instances of PageTemplate share the
same instance of [] in the default "frames" parameter. So, all of the
self.frames values are bound to the same object. It starts out being a
null list, but later, when any instance modifies the list in place, it
modifies ALL instances.

Probably this should be something like:
def __init__(self,id=None,frames=None,...):
if frames is None: frames = [:]

Or, equally good:

self.frames = frames[:]

--
Tim Roberts, timr at probo.com
Providenza & Boekelheide, Inc.



More information about the reportlab-users mailing list