I can now demonstrate exactly where the unbound recursion happens. The following is a debugger that warns me when the stack gets too big. It is a subclass of pdb, but it overrides two methods in bdb.py. Here it is:: class debugger(pdb.Pdb): def __init__(self,completekey='tab',stdin=None,stdout=None): pdb.Pdb.__init__(self,completekey,stdin,stdout) self.stackLimit = 200 # Found by trial and error. # dispatch_call (override bdb) def dispatch_call(self, frame, arg): # XXX 'arg' is no longer used # EKR: new code. stack,junk = self.get_stack(frame,None) if len(stack) > self.stackLimit: print('(debugger.stop_here) stackCount %s' % len(stack)) self.interaction(frame,None) # Existing code. if self.botframe is None: # First call of dispatch since reset() self.botframe = frame.f_back # (CT) Note that this may also be None! return self.trace_dispatch if not (self.stop_here(frame) or self.break_anywhere(frame)): # No need to trace this function return # None self.user_call(frame, arg) if self.quitting: raise BdbQuit return self.trace_dispatch # set_continue (override bdb) def set_continue(self): # Don't stop except at breakpoints or when finished self._set_stopinfo(self.botframe, None) # EKR: Always run with overhead if False: if not self.breaks: # no breakpoints; run without debugger overhead sys.settrace(None) frame = sys._getframe().f_back while frame and frame is not self.botframe: del frame.f_trace frame = frame.f_back And here is the stack trace when the stack limit tripped. It includes some print statements I inserted while stepping through the code. Breakpoint 1 at c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\node_classes.py:256 > c:\python26\lib\site-packages\pylint-0.19.0-py2.6.egg\pylint\lint.py(782)__init__() -> self._rcfile = None (Pdb) disable 1 (Pdb) c manager.py: astng_from_file: not in cache: c:\leo.repo\until\pylintTest.py manager.py: astng_from_file: calling file_build(pylintTest) manager.py: astng_from_file: not in cache: c:\leo.repo\until\leo\__init__.py manager.py: astng_from_file: calling file_build(leo) manager.py: astng_from_file: not in cache: c:\leo.repo\until\leo\core\__init__.py manager.py: astng_from_file: calling file_build(leo.core) manager.py: astng_from_file: not in cache: c:\leo.repo\until\leo\core\leoGlobals.py manager.py: astng_from_file: calling file_build(leo.core.leoGlobals) manager.py: astng_from_file: not in cache: c:\leo.repo\until\leo\core\leoApp.py manager.py: astng_from_file: calling file_build(leo.core.leoApp) (debugger.stop_here) stackCount 201 > c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\inference.py(52)_set_proxied() -> def _set_proxied(const): (Pdb) w ('pdb.py:print_stack_trace', 201) c:\python26\lib\bdb.py(404)runcall() -> res = func(*args, **kwds) c:\python26\lib\site-packages\pylint-0.19.0-py2.6.egg\pylint\lint.py(915)__init__() -> linter.check(args) c:\python26\lib\site-packages\pylint-0.19.0-py2.6.egg\pylint\lint.py(503)check() -> self.check_astng_module(astng, checkers) c:\python26\lib\site-packages\pylint-0.19.0-py2.6.egg\pylint\lint.py(583)check_astng_module() -> self.astng_events(astng, aList,top=True) c:\python26\lib\site-packages\pylint-0.19.0-py2.6.egg\pylint\lint.py(618)astng_events() -> self.astng_events(child, checkers, _reversed_checkers,top=False) c:\python26\lib\site-packages\pylint-0.19.0-py2.6.egg\pylint\lint.py(610)astng_events() -> checker.visit(astng) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\utils.py(323)visit() -> method(node) c:\python26\lib\site-packages\pylint-0.19.0-py2.6.egg\pylint\checkers\variables.py(408)visit_import() -> self._check_module_attrs(node, module, parts[1:]) c:\python26\lib\site-packages\pylint-0.19.0-py2.6.egg\pylint\checkers\variables.py(464)_check_module_attrs() -> module = module.getattr(name)[0].infer().next() c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\scoped_nodes.py(50)wrapper() -> nodes = [n for n in func(*args, **kwargs) if not isinstance(n, cls)] c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\scoped_nodes.py(154)getattr() -> return [self.import_module(name, relative_only=True)] c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\scoped_nodes.py(203)import_module() -> return MANAGER.astng_from_module_name(absmodname) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\manager.py(187)astng_from_module_name() -> return self.astng_from_file(filepath, modname, fallback=False) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\manager.py(138)astng_from_file() -> astng = ASTNGBuilder(self).file_build(filepath, modname) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\builder.py(118)file_build() -> node = self.string_build(data, modname, path) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\builder.py(128)string_build() -> return self.ast_build(parse(data + '\n'), modname, path) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\builder.py(147)ast_build() -> self.rebuilder.walk(node) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\rebuilder.py(94)walk() -> self.delayed_visit_assattr(dnode) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\rebuilder.py(278)delayed_visit_assattr() -> for infered in node.expr.infer(): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(203)wrapped() -> for res in _func(node, context, **kwargs): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(168)_infer_stmts() -> for infered in stmt.infer(context): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(203)wrapped() -> for res in _func(node, context, **kwargs): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\inference.py(391)infer_ass() -> stmts = list(self.assigned_stmts(context=context)) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(231)wrapper() -> for node in func(*args, **kwargs): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\protocols.py(251)assign_assigned_stmts() -> for infered in _resolve_asspart(self.value.infer(context), asspath, context): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\protocols.py(261)_resolve_asspart() -> for part in parts: c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(203)wrapped() -> for res in _func(node, context, **kwargs): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(231)wrapper() -> for node in func(*args, **kwargs): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\inference.py(201)infer_callfunc() -> for callee in self.func.infer(context): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(203)wrapped() -> for res in _func(node, context, **kwargs): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(231)wrapper() -> for node in func(*args, **kwargs): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\inference.py(259)infer_getattr() -> for obj in owner.igetattr(self.attrname, context): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(273)igetattr() -> self._wrap_attr(self.getattr(name, context, lookupclass=False), context), c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(248)getattr() -> values = self._proxied.instance_attr(name, context) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\inference.py(53)_set_proxied() -> if not hasattr(const, '__proxied'): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(44)__getattr__() -> return getattr(self._proxied, name) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\inference.py(53)_set_proxied() -> if not hasattr(const, '__proxied'): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(44)__getattr__() -> return getattr(self._proxied, name) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\inference.py(53)_set_proxied() -> if not hasattr(const, '__proxied'): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(44)__getattr__() -> return getattr(self._proxied, name) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\inference.py(53)_set_proxied() -> if not hasattr(const, '__proxied'): c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\infutils.py(44)__getattr__() -> return getattr(self._proxied, name) c:\python26\lib\site-packages\logilab_astng-0.19.3-py2.6.egg\logilab\astng\inference.py(53)_set_proxied() And so on... I still don't understand the code, but now I know where the unbounded recursion is. Edward