def scan(client, query=None, scroll='5m', raise_on_error=True, preserve_order=False, **kwargs):
    if not preserve_order:
        body = query.copy() if query else {}
        body["sort"] = "_doc"
    # initial search
    resp = client.search(body=query, scroll=scroll, **kwargs)

    scroll_id = resp.get('_scroll_id')
    if scroll_id is None:
        return

    first_run = True
    while True:
        # if we didn't set search_type to scan initial search contains data
        if first_run:
            first_run = False
        else:
            resp = client.scroll(scroll_id, scroll=scroll)

        for hit in resp['hits']['hits']:
            yield hit

        # check if we have any errrors
        if resp["_shards"]["failed"]:
            logger.warning(
                'Scroll request has failed on %d shards out of %d.',
                resp['_shards']['failed'], resp['_shards']['total']
            )
            if raise_on_error:
                raise ScanError(
                    'Scroll request has failed on %d shards out of %d.' %
                    (resp['_shards']['failed'], resp['_shards']['total'])
                )

        scroll_id = resp.get('_scroll_id')
        # end of scroll
        if scroll_id is None or not resp['hits']['hits']:
            break
Decipher whether the output passes, fails, or initializes
dataset/ETHPy150Open elastic/elasticsearch-py/elasticsearch/helpers/__init__.py/scan--crossover with--dataset/ETHPy150Open geopython/pycsw/tests/run_tests.py/get_validity