def _find_sections(md_ast, sections, last, last_class, total_lines=None):
def child_walker(node):<EOL><INDENT>for child, entering in node.walker():<EOL><INDENT>if child == node:<EOL><INDENT>continue<EOL><DEDENT>yield child, entering<EOL><DEDENT><DEDENT>for child, entering in child_walker(md_ast):<EOL><INDENT>if child.t == '<STR_LIT>':<EOL><INDENT>start_line = child.sourcepos[<NUM_LIT:0>][<NUM_LIT:0>]<EOL>if child.level == <NUM_LIT:2>:<EOL><INDENT>if last:<EOL><INDENT>sections[(last['<STR_LIT>'], last['<STR_LIT>'])] = (last['<STR_LIT>'], start_line - <NUM_LIT:1>)<EOL>last.clear()<EOL><DEDENT><DEDENT>if child.level in set([<NUM_LIT:3>, <NUM_LIT:5>]):<EOL><INDENT>heading_elements = []<EOL>for heading_child, _ in child_walker(child):<EOL><INDENT>heading_elements.append(heading_child)<EOL><DEDENT>if len(heading_elements) != <NUM_LIT:2>:<EOL><INDENT>continue<EOL><DEDENT>first = heading_elements[<NUM_LIT:0>]<EOL>second = heading_elements[<NUM_LIT:1>]<EOL>if first.t != '<STR_LIT:code>':<EOL><INDENT>continue<EOL><DEDENT>if second.t != '<STR_LIT:text>':<EOL><INDENT>continue<EOL><DEDENT>type_name = second.literal.strip()<EOL>identifier = first.literal.strip().replace('<STR_LIT>', '<STR_LIT>').lstrip('<STR_LIT:.>')<EOL>if last:<EOL><INDENT>sections[(last['<STR_LIT>'], last['<STR_LIT>'])] = (last['<STR_LIT>'], start_line - <NUM_LIT:1>)<EOL>last.clear()<EOL><DEDENT>if type_name == '<STR_LIT>':<EOL><INDENT>if child.level != <NUM_LIT:3>:<EOL><INDENT>continue<EOL><DEDENT><DEDENT>if type_name == '<STR_LIT:class>':<EOL><INDENT>if child.level != <NUM_LIT:3>:<EOL><INDENT>continue<EOL><DEDENT>last_class.append(identifier)<EOL><DEDENT>if type_name in set(['<STR_LIT>', '<STR_LIT>']):<EOL><INDENT>if child.level != <NUM_LIT:5>:<EOL><INDENT>continue<EOL><DEDENT>identifier = last_class[-<NUM_LIT:1>] + '<STR_LIT:.>' + identifier<EOL><DEDENT>last.update({<EOL>'<STR_LIT>': type_name,<EOL>'<STR_LIT>': identifier,<EOL>'<STR_LIT>': start_line,<EOL>})<EOL><DEDENT><DEDENT>elif child.t == '<STR_LIT>':<EOL><INDENT>find_sections(child, sections, last, last_class)<EOL><DEDENT><DEDENT>if last:<EOL><INDENT>sections[(last['<STR_LIT>'], last['<STR_LIT>'])] = (last['<STR_LIT>'], total_lines)<EOL><DEDENT>
Walks through a CommonMark AST to find section headers that delineate
content that should be updated by this script

:param md_ast:
    The AST of the markdown document

:param sections:
    A dict to store the start and end lines of a section. The key will be
    a two-element tuple of the section type ("class", "function",
    "method" or "attribute") and identifier. The values are a two-element
    tuple of the start and end line number in the markdown document of the
    section.

:param last:
    A dict containing information about the last section header seen.
    Includes the keys "type_name", "identifier", "start_line".

:param last_class:
    A unicode string of the name of the last class found - used when
    processing methods and attributes.

:param total_lines:
    An integer of the total number of lines in the markdown document -
    used to work around a bug in the API of the Python port of CommonMark