#12049: New LazyObject-wrapped User breaks queries in template tags
----------------------------+-----------------------------------------------
Reporter: chipx86 | Owner: nobody
Status: new | Milestone:
Component: Authentication | Version: SVN
Keywords: | Stage: Unreviewed
Has_patch: 1 |
----------------------------+-----------------------------------------------
I spent a couple days tracking this down since the last fix (ticket
#12037) for the new lazy-wrapped User. Basically, if you have a template
tag that grabs the User from the context and performs a complex query with
two or more {{{Q()}}}'s chained together, it will fail. The failure case
on Python 2.4 is fatal, while on 2.5/2.6 it seems to not fail but does log
internally caught exception spew.
Basically, when a deepcopy() is performed on the node list, it sees a
{{{function()}}} for the wrapped User and just fails.
Imagine you have a template tag that takes in the context and starts to
build a query, like so:
{{{
query = Q(user=context['user']) & Q(someflag=True)
}}}
The process of using a Q() on a wrapped User and chaining with another Q()
will break. On Python 2.4, we see:
{{{
File "/usr/lib/python2.4/site-packages/django/db/models/query_utils.py",
line 162, in __and__
return self._combine(other, self.AND)
File "/usr/lib/python2.4/site-packages/django/db/models/query_utils.py",
line 154, in _combine
obj = deepcopy(self)
File "/usr/lib/python2.4/copy.py", line 185, in deepcopy
y = copier(x, memo)
File "/usr/lib/python2.4/site-packages/django/utils/tree.py", line 61,
in __deepcopy__
obj.children = deepcopy(self.children, memodict)
File "/usr/lib/python2.4/copy.py", line 174, in deepcopy
y = copier(x, memo)
File "/usr/lib/python2.4/copy.py", line 241, in _deepcopy_list
y.append(deepcopy(a, memo))
File "/usr/lib/python2.4/copy.py", line 174, in deepcopy
y = copier(x, memo)
File "/usr/lib/python2.4/copy.py", line 248, in _deepcopy_tuple
y.append(deepcopy(a, memo))
File "/usr/lib/python2.4/copy.py", line 204, in deepcopy
y = _reconstruct(x, rv, 1, memo)
File "/usr/lib/python2.4/copy.py", line 351, in _reconstruct
state = deepcopy(state, memo)
File "/usr/lib/python2.4/copy.py", line 174, in deepcopy
y = copier(x, memo)
File "/usr/lib/python2.4/copy.py", line 268, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "/usr/lib/python2.4/copy.py", line 204, in deepcopy
y = _reconstruct(x, rv, 1, memo)
File "/usr/lib/python2.4/copy.py", line 336, in _reconstruct
y = callable(*args)
File "/usr/lib/python2.4/copy_reg.py", line 92, in __newobj__
return cls.__new__(cls, *args)
TypeError: function() takes at least 2 arguments (0 given)
}}}
On Python 2.5 and 2.6, the call succeeds (or at least doesn't throw a
fatal exception, but I don't know if there are internal side effects
here), but does log the following:
{{{
Exception RuntimeError: 'maximum recursion depth exceeded while calling a
Python object' in <type 'exceptions.AttributeError'> ignored
}}}
I'm attaching a diff that simply amends the test_user_attrs testcase to
simulate this. After the other checks, it pulls out the User and then
builds a dummy query.
--
Ticket URL: <http://code.djangoproject.com/ticket/12049>
Django <http://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
-~----------~----~----~----~------~----~------~--~---