def port_generated(generated_annotations, sel):
    """Port generated annotations to annotations with custom extractors."""
    for annotation in generated_annotations:
        # Find pre and post text
        _slice = annotation.get('slice')
        if not annotation.get('tagid') or not _slice or len(_slice) != 2:
            continue
        element = find_element(annotation, sel)
        if element is None:
            continue
        pre_text, post_text = '', ''
        if annotation.get('insert_after'):
            selector = find_generalized_css_selector(element.getparent(), sel)
            if not selector:
                continue
            annotation['accept_selectors'] = [selector]
            annotation['selector'] = selector
            siblings = list(element.getparent().iterchildren())
            start = siblings.index(element)

            def process_siblings(others, reverse=False):
                text = []
                order = ('tail', 'text') if reverse else ('text', 'tail')
                for elem in others:
                    for t in order:
                        text.append(getattr(elem, t) or ' ')
                    if any(t.strip() for t in text):
                        break
                return ''.join(text)
            pre_text = process_siblings(
                siblings[start - 1: 0: -1] + [siblings[0]], True)
            post_text = process_siblings(siblings[start + 1:], 1)
            text = element.tail
        else:
            text = element.text
        text = (text or '').strip()
        data = annotation['data']
        contentf = annotation.get('text-content', 'content')
        for anno in (a for a in data.values() if a['attribute'] == contentf):
            pre_text = (pre_text + text[0:_slice[0]]).strip()
            post_text = (text[_slice[1]:] + post_text).strip()
            if anno and pre_text or post_text:
                anno['pre_text'] = pre_text
                anno['post_text'] = post_text
        # Create new text region field
        annotation.pop('variant', None)
        del annotation['slice']
    return generated_annotations
Port generated annotations to annotations with custom extractors.
slybot/slybot/plugins/scrapely_annotations/migration.py