found_obj = None
for child in self._children.itervalues():
- if isinstance(child, ptype):
+ visited = False
+ if hasattr(child, '_visited'):
+ visited = getattr(child, '_visited')
+
+ if isinstance(child, ptype) and not visited:
if found_obj != None and child != found_obj:
raise AttributeError, \
'parent.any matched more than one: %s %s' % \
result, done = self.find(obj)
if self._search_up:
+ # Search up the tree but mark ourself
+ # as visited to avoid a self-reference
+ self._visited = True
+ obj._visited = True
while not done:
obj = obj._parent
if not obj:
break
result, done = self.find(obj)
+ self._visited = False
+ base._visited = False
+
if not done:
raise AttributeError, \
"Can't resolve proxy '%s' of type '%s' from '%s'" % \
def find(self, obj):
try:
val = getattr(obj, self._attr)
- # for any additional unproxying to be done, pass the
- # current, rather than the original object so that proxy
- # has the right context
- obj = val
+ visited = False
+ if hasattr(val, '_visited'):
+ visited = getattr(val, '_visited')
+
+ if not visited:
+ # for any additional unproxying to be done, pass the
+ # current, rather than the original object so that proxy
+ # has the right context
+ obj = val
+ else:
+ return None, False
except:
return None, False
while isproxy(val):