def find_generated_annotation(elem):
    """Find annotation information for generated element."""
    elem = elem.root
    previous = elem.getprevious()
    insert_after = True
    nodes = []
    if previous is None:
        previous = elem.getparent()
        nodes = [previous] + previous.getchildren()
        insert_after = False
    else:
        while (previous is not None and isinstance(previous, _Element) and
                previous.tag.lower() == 'ins'):
            previous = previous.getprevious()
        if previous is None:
            previous = elem.getparent()
            insert_after = False
            node = previous.getchildren()[0]
        else:
            node = previous
        while node is not None:
            nodes.append(node)
            node = node.getnext()
            if (node is None or
                    isinstance(node, _Element) and node.tag.lower() == 'ins'):
                nodes.append(node)
                break
    annotation = {
        'tagid': previous.attrib.get('data-tagid'),
        'generated': True,
        'insert_after': insert_after
    }
    last_node_ins = False
    start = 0
    # Calculate the length and start position of the slice ignoring the ins
    # tag and with leading whitespace removed
    for node in nodes:
        if (node is not None and isinstance(node, _Element) and
                node.tag.lower() == 'ins'):
            last_node_ins = True
            text_len = len(node.text or '')
            if node == elem:
                annotation['slice'] = start, start + text_len
            else:
                start += text_len
        else:
            text = node.tail if annotation['insert_after'] else node.text
            text = '' if text is None else text
            if not last_node_ins:
                text = text.lstrip()
            start += len(text)
            last_node_ins = False
    return annotation
Find annotation information for generated element.
slybot/slybot/plugins/scrapely_annotations/migration.py