#16563: Error pickling request.user
---------------------------------+------------------------------------
     Reporter:  zero.fuxor@…     |                    Owner:  nobody
         Type:  Bug              |                   Status:  new
    Component:  contrib.auth     |                  Version:  1.3
     Severity:  Release blocker  |               Resolution:
     Keywords:                   |             Triage Stage:  Accepted
    Has patch:  0                |      Needs documentation:  0
  Needs tests:  0                |  Patch needs improvement:  0
Easy pickings:  0                |                    UI/UX:  0
---------------------------------+------------------------------------

Comment (by lukeplant):

 OK, this has turned out to be rather tricky.

 The previous patch only works for objects that have no state. The basic
 problem is that due to proxying the `__class__` attribute, the pickling
 machinery is confused (I think), and so it stores a reference to the class
 of the wrapped object, rather than `SimpleLazyObject`.

 So, we need to define the `__reduce__` method for full customization,
 rather than the simpler `__getstate__` method. However, for some reason,
 the presence of the `__class__` attribute proxying causes this to fail -
 if you define `__reduce__` on `SimpleLazyObject`, it is never called when
 pickling unless you remove the `__class__` hacking.

 This takes us back to using `__getstate__` (which, for some reason,
 doesn't suffer from the same problem as `__reduce__`). But now we have to
 cooperate with the fact that pickling will skip `SimpleLazyObject` and
 store a reference to the wrapped class, and define `__getstate__` so that
 it returns the state from the wrapped object. This appears to work:

 {{{
 #!python
     def __getstate__(self):
         if self._wrapped is empty:
             self._setup()
         return self._wrapped.__dict__
 }}}

 The result is that on unpickling, the `SimpleLazyObject` wrapper
 disappears entirely, which should be OK.

 I still get failure if `SimpleLazyObject` is wrapping a builtin, and
 nothing but removing the `__class__` proxying appears to be able to fix
 that. But that bug has always been there, and this change doesn't affect
 it.

 I've confirmed that with this patch you can pickle `request.user`, and on
 pickling get an object that compares equal to the original, so I'm
 therefore committing my improved patch.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/16563#comment:21>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to