Opened 14 years ago

Last modified 8 years ago

#12134 new Bug

contrib.admin.RelatedFieldWidgetWrapper.__deepcopy__() should copy() the widget attrs

Reported by: James Bennett Owned by: nobody
Component: contrib.admin Version: 1.1
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Otherwise it ends up with a shallow copy which reuses the same attrs dict across separate widget instances, playing merry hell with form classes which want to change widget attrs on a per-(form)-instance basis.

Attachments (1)

12134.diff (489 bytes ) - added by James Bennett 14 years ago.

Download all attachments as: .zip

Change History (7)

by James Bennett, 14 years ago

Attachment: 12134.diff added

comment:1 by Brian Rosner, 14 years ago

Triage Stage: UnreviewedAccepted

comment:2 by Luke Plant, 14 years ago

I think we need some more analysis of why this patch is correct/needed. Here are some simplified extracts of current code:

class RelatedFieldWidgetWrapper(forms.Widget):
    def __init__(self, widget, rel, admin_site):
        self.attrs = widget.attrs
        self.widget = widget
        # <snip>

    def __deepcopy__(self, memo):
        obj = copy.copy(self)
        obj.widget = copy.deepcopy(self.widget, memo)
        obj.attrs = self.widget.attrs
        memo[id(self)] = obj
        return obj

This means:

wrapper1 = RelatedFieldWidgetWrapper(some_widget, some_rel, some_admin_site)
wrapper2 = copy.deepcopy(wrapper1) # as happens when widget is copied via BaseForm.__init__()

assert wrapper1.attrs is wrapper1.widget.attrs
assert wrapper2.attrs is wrapper2.widget.attrs
assert wrapper1.widget is not wrapper2.widget

That all seems to be correct. The attached patch would actually break the second assert, which I'm pretty sure will break the ability of the class instance to work as a wrapper.

comment:3 by Matt McClanahan, 13 years ago

Severity: Normal
Type: Bug

comment:4 by Aymeric Augustin, 12 years ago

UI/UX: unset

Change UI/UX from NULL to False.

comment:5 by Aymeric Augustin, 12 years ago

Easy pickings: unset

Change Easy pickings from NULL to False.

comment:6 by Tim Graham, 8 years ago

I think #26213 gives a demonstration of a behavior which this ticket may fix.

Note: See TracTickets for help on using tickets.
Back to Top