Changes between Initial Version and Version 4 of Ticket #7204


Ignore:
Timestamp:
05/21/2008 10:50:21 AM (7 years ago)
Author:
jacob
Comment:

Changed title, description to more clearly explain what's going on here

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #7204

    • Property Status changed from new to reopened
    • Property Patch needs improvement unset
    • Property Needs tests unset
    • Property Summary changed from .count() not working to QuerySet cloning can sometimes fail
    • Property Needs documentation unset
    • Property Triage Stage changed from Unreviewed to Accepted
  • Ticket #7204 – Description

    initial v4  
    1 fs.models:
     1[Original bug report removed; see [http://code.djangoproject.com/ticket/7204#comment:2 the second comment] for the original report. --JKM]
    22
    3 {{{
    4 class Topic(models.Model):
    5     def __init__(self, *args, **kwargs):
    6         super(Topic, self).__init__(*args, **kwargs)
    7         self.attrs = Dict(self)
    8     ...
    9 }}}
     3Under some circumstances -- often involving {{{select_related()}}} and {{{count()}}} -- {{{QuerySet.clone()}}} can cause exceptions related to deepcopy(). These exceptions look like {{{TypeError: instancemethod expected at least 2 arguments, got 0}}} or {{{TypeError: function expected at least 2 arguments, got 0}}}.
    104
    11 users.models:
    12 {{{
    13 User.add_to_class('full_name', models.CharField(max_length=200, null=True, blank=True))
    14 User.add_to_class('title', models.CharField(max_length=255, null=True, blank=True, help_text=_("The preferred title for ~/, like the title for youtube channel")))
     5The first one involving {{{instancemethod}}} is probably related to a Python issue: see http://bugs.python.org/issue1515.
    156
    16 def _add_attrs_and_methods(sender, instance, signal, *args, **kwargs):
    17     from users.models import PersonalMessage
    18     import types
    19    
    20     instance.attrs = Dict(instance)
    21     def can_change(self, post):
    22         if self == post.author:
    23             return True
    24         return False
     7The second involving {{{function}}} only seems to occur on Python 2.4 (and not 2.5), but since 1515 isn't fixed yet, it may be a seperate problem.
    258
    26     instance.can_change = types.MethodType(can_change, instance, instance.__class__)
    27 
    28 
    29 dispatcher.connect(_add_attrs_and_methods, sender=User, signal=signals.post_init)
    30 }}}
    31 
    32 
    33 traceback:
    34 {{{
    35 In [1]: from users.models import *
    36 
    37 In [2]: from fs.models import *
    38 
    39 In [3]: u = User.objects.all()[0]
    40 
    41 In [4]: len(Topic.objects.filter(author=u))
    42 Out[4]: 2101
    43 
    44 In [5]: Topic.objects.filter(author=u).count()
    45 ---------------------------------------------------------------------------
    46 TypeError                                 Traceback (most recent call last)
    47 
    48 /home/grey/src/df/<ipython console>
    49 
    50 /usr/lib/python2.4/site-packages/django/db/models/query.py in count(self)
    51     182             return len(self._result_cache)
    52     183
    53 --> 184         return self.query.get_count()
    54     185
    55     186     def get(self, *args, **kwargs):
    56 
    57 /usr/lib/python2.4/site-packages/django/db/models/sql/query.py in get_count(self)
    58     209         """
    59     210         from subqueries import CountQuery
    60 --> 211         obj = self.clone()
    61     212         obj.clear_ordering(True)
    62     213         obj.clear_limits()
    63 
    64 /usr/lib/python2.4/site-packages/django/db/models/sql/query.py in clone(self, klass, **kwargs)
    65     167         obj.select = self.select[:]
    66     168         obj.tables = self.tables[:]
    67 --> 169         obj.where = deepcopy(self.where)
    68     170         obj.where_class = self.where_class
    69     171         obj.group_by = self.group_by[:]
    70 
    71 /usr/lib/python2.4/copy.py in deepcopy(x, memo, _nil)
    72     183             copier = _getspecial(cls, "__deepcopy__")
    73     184             if copier:
    74 --> 185                 y = copier(x, memo)
    75     186             else:
    76     187                 reductor = dispatch_table.get(cls)
    77 
    78 /usr/lib/python2.4/site-packages/django/utils/tree.py in __deepcopy__(self, memodict)
    79      43         obj = Node(connector=self.connector, negated=self.negated)
    80      44         obj.__class__ = self.__class__
    81 ---> 45         obj.children = deepcopy(self.children, memodict)
    82      46         obj.subtree_parents = deepcopy(self.subtree_parents, memodict)
    83      47         return obj
    84 
    85 /usr/lib/python2.4/copy.py in deepcopy(x, memo, _nil)
    86     172     copier = _deepcopy_dispatch.get(cls)
    87     173     if copier:
    88 --> 174         y = copier(x, memo)
    89     175     else:
    90     176         try:
    91 
    92 /usr/lib/python2.4/copy.py in _deepcopy_list(x, memo)
    93     239     memo[id(x)] = y
    94     240     for a in x:
    95 --> 241         y.append(deepcopy(a, memo))
    96     242     return y
    97     243 d[types.ListType] = _deepcopy_list
    98 
    99 /usr/lib/python2.4/copy.py in deepcopy(x, memo, _nil)
    100     172     copier = _deepcopy_dispatch.get(cls)
    101     173     if copier:
    102 --> 174         y = copier(x, memo)
    103     175     else:
    104     176         try:
    105 
    106 /usr/lib/python2.4/copy.py in _deepcopy_tuple(x, memo)
    107     246     y = []
    108     247     for a in x:
    109 --> 248         y.append(deepcopy(a, memo))
    110     249     d = id(x)
    111     250     try:
    112 
    113 /usr/lib/python2.4/copy.py in deepcopy(x, memo, _nil)
    114     202                             raise Error(
    115     203                                 "un(deep)copyable object of type %s" % cls)
    116 --> 204                 y = _reconstruct(x, rv, 1, memo)
    117     205
    118     206     memo[d] = y
    119 
    120 /usr/lib/python2.4/copy.py in _reconstruct(x, info, deep, memo)
    121     349     if state:
    122     350         if deep:
    123 --> 351             state = deepcopy(state, memo)
    124     352         if hasattr(y, '__setstate__'):
    125     353             y.__setstate__(state)
    126 
    127 /usr/lib/python2.4/copy.py in deepcopy(x, memo, _nil)
    128     172     copier = _deepcopy_dispatch.get(cls)
    129     173     if copier:
    130 --> 174         y = copier(x, memo)
    131     175     else:
    132     176         try:
    133 
    134 /usr/lib/python2.4/copy.py in _deepcopy_dict(x, memo)
    135     266     memo[id(x)] = y
    136     267     for key, value in x.iteritems():
    137 --> 268         y[deepcopy(key, memo)] = deepcopy(value, memo)
    138     269     return y
    139     270 d[types.DictionaryType] = _deepcopy_dict
    140 
    141 /usr/lib/python2.4/copy.py in deepcopy(x, memo, _nil)
    142     202                             raise Error(
    143     203                                 "un(deep)copyable object of type %s" % cls)
    144 --> 204                 y = _reconstruct(x, rv, 1, memo)
    145     205
    146     206     memo[d] = y
    147 
    148 /usr/lib/python2.4/copy.py in _reconstruct(x, info, deep, memo)
    149     334     if deep:
    150     335         args = deepcopy(args, memo)
    151 --> 336     y = callable(*args)
    152     337     memo[id(x)] = y
    153     338     if listiter is not None:
    154 
    155 /usr/lib/python2.4/copy_reg.py in __newobj__(cls, *args)
    156      90
    157      91 def __newobj__(cls, *args):
    158 ---> 92     return cls.__new__(cls, *args)
    159      93
    160      94 def _slotnames(cls):
    161 
    162 TypeError: instancemethod expected at least 2 arguments, got 0
    163 }}}
     9In either case, though, the root problem is that for some reason QuerySet is trying to clone instancemethods and unbound functions, which isn't exactly supported -- dunno what a copy of a function would do anyway. The likely fix will involve finding out where and why functions/methods are being coppied, and stop doing that.
Back to Top