# Buggy code
def _filter_stmts(self, stmts, frame, offset):
    """Filter the given list of statements to remove ignorable statements.

    If self is not a frame itself and the name is found in the inner
    frame locals, statements will be filtered to remove ignorable
    statements according to self's location.

    :param stmts: The statements to filter.
    :type stmts: list(NodeNG)

    :param frame: The frame that all of the given statements belong to.
    :type frame: NodeNG

    :param offset: The line offset to filter statements up to.
    :type offset: int

    :returns: The filtered statements.
    :rtype: list(NodeNG)
    """
    # if offset == -1, my actual frame is not the inner frame but its parent
    #
    # class A(B): pass
    #
    # we need this to resolve B correctly
    if offset == -1:
        myframe = self.frame().parent.frame()
    else:
        myframe = self.frame()
        # If the frame of this node is the same as the statement
        # of this node, then the node is part of a class or
        # a function definition and the frame of this node should be the
        # the upper frame, not the frame of the definition.
        # For more information why this is important,
        # see Pylint issue #295.
        # For example, for 'b', the statement is the same
        # as the frame / scope:
        #
        # def test(b=1):
        #     ...

        if self.statement() is myframe and myframe.parent:
            myframe = myframe.parent.frame()
    mystmt = self.statement()
    # line filtering if we are in the same frame
    #
    # take care node may be missing lineno information (this is the case for
    # nodes inserted for living objects)
    if myframe is frame and mystmt.fromlineno is not None:
        assert mystmt.fromlineno is not None, mystmt
        mylineno = mystmt.fromlineno + offset
    else:
        # disabling lineno filtering
        mylineno = 0
    _stmts = []
    _stmt_parents = []
    for node in stmts:
        stmt = node.statement()
        # line filtering is on and we have reached our location, break
        if stmt.fromlineno > mylineno > 0:
            break
        assert hasattr(node, "assign_type"), (node, node.scope(), node.scope().locals)
        assign_type = node.assign_type()
        if node.has_base(self):
            break

        _stmts, done = assign_type._get_filtered_stmts(self, node, _stmts, mystmt)
        if done:
            break

        optional_assign = assign_type.optional_assign
        if optional_assign and assign_type.parent_of(self):
            # we are inside a loop, loop var assignment is hiding previous
            # assignment
            _stmts = [node]
            _stmt_parents = [stmt.parent]
            continue

        # XXX comment various branches below!!!
        try:
            pindex = _stmt_parents.index(stmt.parent)
        except ValueError:
            pass
        else:
            # we got a parent index, this means the currently visited node
            # is at the same block level as a previously visited node
            if _stmts[pindex].assign_type().parent_of(assign_type):
                # both statements are not at the same block level
                continue
            # if currently visited node is following previously considered
            # assignment and both are not exclusive, we can drop the
            # previous one. For instance in the following code ::
            #
            #   if a:
            #     x = 1
            #   else:
            #     x = 2
            #   print x
            #
            # we can't remove neither x = 1 nor x = 2 when looking for 'x'
            # of 'print x'; while in the following ::
            #
            #   x = 1
            #   x = 2
            #   print x
            #
            # we can remove x = 1 when we see x = 2
            #
            # moreover, on loop assignment types, assignment won't
            # necessarily be done if the loop has no iteration, so we don't
            # want to clear previous assignments if any (hence the test on
            # optional_assign)
            if not (optional_assign or are_exclusive(_stmts[pindex], node)):
                del _stmt_parents[pindex]
                del _stmts[pindex]
        if isinstance(node, AssignName):
            if not optional_assign and stmt.parent is mystmt.parent:
                _stmts = []
                _stmt_parents = []
        elif isinstance(node, DelName):
            _stmts = []
            _stmt_parents = []
            continue
        if not are_exclusive(self, node):
            _stmts.append(node)
            _stmt_parents.append(stmt.parent)
    return _stmts


# Traceback (RuntimeError)
Traceback (most recent call last):
File "/Users/rwilliams/src/oss/pylint/venv/bin/pylint", line 9, in <module>
load_entry_point('pylint==2.0.0', 'console_scripts', 'pylint')()
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/pylint-2.0.0-py2.7.egg/pylint/__init__.py", line 13, in run_pylint
Run(sys.argv[1:])
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/pylint-2.0.0-py2.7.egg/pylint/lint.py", line 1300, in __init__
linter.check(args)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/pylint-2.0.0-py2.7.egg/pylint/lint.py", line 726, in check
self._do_check(files_or_modules)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/pylint-2.0.0-py2.7.egg/pylint/lint.py", line 855, in _do_check
self.check_astroid_module(ast_node, walker, rawcheckers, tokencheckers)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/pylint-2.0.0-py2.7.egg/pylint/lint.py", line 934, in check_astroid_module
walker.walk(ast_node)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/pylint-2.0.0-py2.7.egg/pylint/utils.py", line 997, in walk
self.walk(child)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/pylint-2.0.0-py2.7.egg/pylint/utils.py", line 994, in walk
cb(astroid)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/pylint-2.0.0-py2.7.egg/pylint/checkers/base.py", line 388, in visit_functiondef
self._check_redefinition(node.is_method() and 'method' or 'function', node)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/scoped_nodes.py", line 876, in is_method
return self.type != 'function' and isinstance(self.parent.frame(), ClassDef)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/decorators.py", line 65, in __get__
val = self.wrapped(inst)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/scoped_nodes.py", line 807, in type
_type = _infer_decorator_callchain(current)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/scoped_nodes.py", line 611, in _infer_decorator_callchain
result = next(node.infer_call_result(node.parent))
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/scoped_nodes.py", line 963, in infer_call_result
for inferred in returnnode.value.infer(context):
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/decorators.py", line 85, in wrapped
res = next(generator)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/bases.py", line 95, in _infer_stmts
for inferred in stmt.infer(context=context):
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/context.py", line 40, in cache_generator
for result in generator:
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/decorators.py", line 82, in wrapped
generator = _func(node, context, **kwargs)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/inference.py", line 723, in infer_assign
stmts = list(self.assigned_stmts(context=context))
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/protocols.py", line 292, in _arguments_infer_argname
functype = self.parent.type
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/decorators.py", line 65, in __get__
val = self.wrapped(inst)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/scoped_nodes.py", line 807, in type
_type = _infer_decorator_callchain(current)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/scoped_nodes.py", line 611, in _infer_decorator_callchain
result = next(node.infer_call_result(node.parent))
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/scoped_nodes.py", line 963, in infer_call_result
for inferred in returnnode.value.infer(context):
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/decorators.py", line 85, in wrapped
res = next(generator)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/bases.py", line 95, in _infer_stmts
for inferred in stmt.infer(context=context):
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/context.py", line 40, in cache_generator
for result in generator:
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/decorators.py", line 82, in wrapped
generator = _func(node, context, **kwargs)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/inference.py", line 723, in infer_assign
stmts = list(self.assigned_stmts(context=context))
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/protocols.py", line 292, in _arguments_infer_argname
functype = self.parent.type
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/decorators.py", line 65, in __get__
val = self.wrapped(inst)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/scoped_nodes.py", line 807, in type
_type = _infer_decorator_callchain(current)
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/scoped_nodes.py", line 611, in _infer_decorator_callchain
result = next(node.infer_call_result(node.parent))
File "/Users/rwilliams/src/oss/pylint/venv/lib/python2.7/site-packages/astroid-1.5.0-py2.7.egg/astroid/scoped_nodes.py", line 963, in infer_call_result
.
.
.
RuntimeError: maximum recursion depth exceeded

# Fixed code
def _filter_stmts(self, stmts, frame, offset):
    """Filter the given list of statements to remove ignorable statements.

    If self is not a frame itself and the name is found in the inner
    frame locals, statements will be filtered to remove ignorable
    statements according to self's location.

    :param stmts: The statements to filter.
    :type stmts: list(NodeNG)

    :param frame: The frame that all of the given statements belong to.
    :type frame: NodeNG

    :param offset: The line offset to filter statements up to.
    :type offset: int

    :returns: The filtered statements.
    :rtype: list(NodeNG)
    """
    # if offset == -1, my actual frame is not the inner frame but its parent
    #
    # class A(B): pass
    #
    # we need this to resolve B correctly
    if offset == -1:
        myframe = self.frame().parent.frame()
    else:
        myframe = self.frame()
        # If the frame of this node is the same as the statement
        # of this node, then the node is part of a class or
        # a function definition and the frame of this node should be the
        # the upper frame, not the frame of the definition.
        # For more information why this is important,
        # see Pylint issue #295.
        # For example, for 'b', the statement is the same
        # as the frame / scope:
        #
        # def test(b=1):
        #     ...

        if self.statement() is myframe and myframe.parent:
            myframe = myframe.parent.frame()
    mystmt = self.statement()
    # line filtering if we are in the same frame
    #
    # take care node may be missing lineno information (this is the case for
    # nodes inserted for living objects)
    if myframe is frame and mystmt.fromlineno is not None:
        assert mystmt.fromlineno is not None, mystmt
        mylineno = mystmt.fromlineno + offset
    else:
        # disabling lineno filtering
        mylineno = 0
    _stmts = []
    _stmt_parents = []
    for node in stmts:
        stmt = node.statement()
        # line filtering is on and we have reached our location, break
        if stmt.fromlineno > mylineno > 0:
            break
        # Ignore decorators with the same name as the
        # decorated function
        # Fixes issue #375
        if mystmt is stmt and is_from_decorator(self):
            continue
        assert hasattr(node, "assign_type"), (node, node.scope(), node.scope().locals)
        assign_type = node.assign_type()
        if node.has_base(self):
            break

        _stmts, done = assign_type._get_filtered_stmts(self, node, _stmts, mystmt)
        if done:
            break

        optional_assign = assign_type.optional_assign
        if optional_assign and assign_type.parent_of(self):
            # we are inside a loop, loop var assignment is hiding previous
            # assignment
            _stmts = [node]
            _stmt_parents = [stmt.parent]
            continue

        # XXX comment various branches below!!!
        try:
            pindex = _stmt_parents.index(stmt.parent)
        except ValueError:
            pass
        else:
            # we got a parent index, this means the currently visited node
            # is at the same block level as a previously visited node
            if _stmts[pindex].assign_type().parent_of(assign_type):
                # both statements are not at the same block level
                continue
            # if currently visited node is following previously considered
            # assignment and both are not exclusive, we can drop the
            # previous one. For instance in the following code ::
            #
            #   if a:
            #     x = 1
            #   else:
            #     x = 2
            #   print x
            #
            # we can't remove neither x = 1 nor x = 2 when looking for 'x'
            # of 'print x'; while in the following ::
            #
            #   x = 1
            #   x = 2
            #   print x
            #
            # we can remove x = 1 when we see x = 2
            #
            # moreover, on loop assignment types, assignment won't
            # necessarily be done if the loop has no iteration, so we don't
            # want to clear previous assignments if any (hence the test on
            # optional_assign)
            if not (optional_assign or are_exclusive(_stmts[pindex], node)):
                del _stmt_parents[pindex]
                del _stmts[pindex]
        if isinstance(node, AssignName):
            if not optional_assign and stmt.parent is mystmt.parent:
                _stmts = []
                _stmt_parents = []
        elif isinstance(node, DelName):
            _stmts = []
            _stmt_parents = []
            continue
        if not are_exclusive(self, node):
            _stmts.append(node)
            _stmt_parents.append(stmt.parent)
    return _stmts