Ivan Sagalaev wrote:
>>
> I think so too... I was investigating Alex's report and it looks like 
> somewhere onr thread is creating a QueryDict and another tries to access 
> it while it's being created. It's the only place where it doesn't 
> contain self._mutable.
> 
> This may mean that mod_python somehow supplies shared request object 
> which it shouldn't. On a mod-python list I saw a suggestion 

I reproduced it in python interpreter. I don't think it is 
mod_python-related problem.

There are two problems as far as I can tell:

1) QueryDict uses the hacks with class-level variables, which are 
reassigned temporarily during copy(). Its base class (MultiValueDict) 
does the same. It's a no-no for multithreaded programming. The same goes 
for module-level variables. In short: all changes to common variables 
should be analyzed and synchronized, or avoided. The latter is the best 
approach.

2) copy.deepcopy() doesn't like to be fooled with dynamic class 
modifications, e.g. with replacing __setitem__. Example:

=====================================
class Ex(dict):

    def __init__(self, mutable=True):
        dict.__init__(self)
        self._mutable = mutable

    def _setitem_if_mutable(self, key, value):
        print 'Setting', key, 'to', value
        self._assert_mutable()
        dict.__setitem__(self, key, value)
    __setitem__ = _setitem_if_mutable

    def _assert_mutable(self):
        if not self._mutable:
            raise AttributeError, "This Ex instance is immutable"

    def copy(self):
        "Returns a mutable copy of this object."
        import copy
        # Our custom __setitem__ must be disabled for copying machinery.
        old_mutable = self._mutable
        self._mutable = True
        cp = copy.deepcopy(self)
        self._mutable = old_mutable
        return cp

a = Ex()
# it works fine
# a is fully functional

b = a.copy()
# it works fine
# b is fully functional

c = b.copy()
# it blows: AttributeError: 'Ex' object has no attribute '_mutable'

c = a.copy()
# it works fine
=====================================

Try to play with it.

The right way to handle copy/deepcopy is to define proper 
___copy__/__deepcopy__ methods, or to define custom pickling helpers. 
Incidentally it was a point of the hacks in #1.

I implemented a patch for #1 and #2, and sent it to Alex. If he confirms 
it, I'll create a ticket. Otherwise I'll dig more. I am afraid we'll 
find more places with class-level (like this) or module-level (like in 
uncommitted #1442 patch) variables.

Thanks,

Eugene


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-users
-~----------~----~----~----~------~----~------~--~---

Reply via email to