Robin Becker wrote:
I found that this error
Exception RuntimeError: 'maximum recursion depth exceeded in
__subclasscheck__' in <type 'exceptions.AttributeError'> ignored
occurs when attempting to copy (copy.copy(inst)) an instance of a class
that looks like this
class LazyParagraph(_LazyMixin,TTParagraph):
SUPER=TTParagraph
_CLEAN_SPACE=1
........
I have attempted to abstract the problem, but so far I haven't found the
vital bits.
OK this turns out to be one of those useful exercises after all. After
instrumenting the copy instance copy func my colleague and I found the problem
occurs in this innocuous looking example
###################
import copy
class _LazyMixin:
"""don't do any initialization until later"""
def __init__(self,*args):
self._args = args
self._initialized = 0
def __getattr__(self,a):
if not self._initialized:
self._Initialize()
return getattr(self,a)
raise AttributeError("No attribute '%s'" % a)
def _Initialize(self):
if not self._initialized:
self._initialized = 1
del self._args
l=_LazyMixin()
print l._initialized
copy.debug=1
copy.copy(l)
###################
it turns out that in the absence of other info _copy_inst creates a dummy
instance and changes its class to the incoming class. It then asks the new
unpopulated instance if it has an attribute __setstate__, that triggers the
_LazyMixin __getattr__ which fails because there's no _initialize member so
__getattr__ gets recalled etc etc. Presumably in earlier pythons this bad
behaviour is just hidden. The fix for us is to provide a __setstate__ which does
what the no __setstate__ code does ie update __dict__.
However, since the _copy_inst code knows there can be no members on the new
instance should it not be asking the __class__ for __setstate__?
--
Robin Becker
--
http://mail.python.org/mailman/listinfo/python-list