(repeater, feed_name)
Iterates over a paginated atom feed, yields patients updated since
    repeater.patients_last_polled_at, and updates the repeater.
Iterates over a paginated atom feed, yields patients updated since
    repeater.patients_last_polled_at, and updates the repeater.
Iterates over a paginated atom feed yields patients updated since repeater . patients_last_polled_at and updates the repeater .
def get_feed_updates(repeater, feed_name):
    """
    Iterates over a paginated atom feed, yields patients updated since
    repeater.patients_last_polled_at, and updates the repeater.
    """
    def has_new_entries_since(last_polled_at, element, xpath='./atom:updated'):
        return not last_polled_at or get_timestamp(element, xpath) > last_polled_at

    assert feed_name in ATOM_FEED_NAMES
    atom_feed_status = repeater.atom_feed_status.get(feed_name, AtomFeedStatus())
    last_polled_at = atom_feed_status['last_polled_at']
    page = atom_feed_status['last_page']
    get_uuid = get_patient_uuid if feed_name == ATOM_FEED_NAME_PATIENT else get_encounter_uuid
    # The OpenMRS Atom feeds' timestamps are timezone-aware. So when we
    # compare timestamps in has_new_entries_since(), this timestamp
    # must also be timezone-aware. repeater.patients_last_polled_at is
    # set to a UTC timestamp (datetime.utcnow()), but the timezone gets
    # dropped because it is stored as a jsonobject DateTimeProperty.
    # This sets it as a UTC timestamp again:
    last_polled_at = pytz.utc.localize(last_polled_at) if last_polled_at else None
    try:
        while True:
            feed_xml = get_feed_xml(repeater.requests, feed_name, page)
            if has_new_entries_since(last_polled_at, feed_xml):
                for entry in feed_xml.xpath('./atom:entry', namespaces={'atom': 'http://www.w3.org/2005/Atom'}):
                    if has_new_entries_since(last_polled_at, entry, './atom:published'):
                        entry_uuid = get_uuid(entry)
                        if entry_uuid:
                            yield entry_uuid
            next_page = feed_xml.xpath(
                './atom:link[@rel="next-archive"]',
                namespaces={'atom': 'http://www.w3.org/2005/Atom'}
            )
            if next_page:
                href = next_page[0].get('href')
                page = href.split('/')[-1]
            else:
                if not page:
                    this_page = feed_xml.xpath(
                        './atom:link[@rel="via"]',
                        namespaces={'atom': 'http://www.w3.org/2005/Atom'}
                    )
                    href = this_page[0].get('href')
                    page = href.split('/')[-1]
                break
    except (RequestException, HTTPError):
        # Don't update repeater if OpenMRS is offline
        return
    except OpenmrsFeedDoesNotExist:
        repeater.atom_feed_status[feed_name] = AtomFeedStatus()
        repeater.save()
    else:
        repeater.atom_feed_status[feed_name] = AtomFeedStatus(
            last_polled_at=datetime.utcnow(),
            last_page=page,
        )
        repeater.save()
def get_feed_updates ( repeater , feed_name ) : def has_new_entries_since ( last_polled_at , element , xpath = './atom:updated' ) : return not last_polled_at or get_timestamp ( element , xpath ) > last_polled_at assert feed_name in ATOM_FEED_NAMES atom_feed_status = repeater . atom_feed_status . get ( feed_name , AtomFeedStatus ( ) ) last_polled_at = atom_feed_status [ 'last_polled_at' ] page = atom_feed_status [ 'last_page' ] get_uuid = get_patient_uuid if feed_name == ATOM_FEED_NAME_PATIENT else get_encounter_uuid # The OpenMRS Atom feeds' timestamps are timezone-aware. So when we # compare timestamps in has_new_entries_since(), this timestamp # must also be timezone-aware. repeater.patients_last_polled_at is # set to a UTC timestamp (datetime.utcnow()), but the timezone gets # dropped because it is stored as a jsonobject DateTimeProperty. # This sets it as a UTC timestamp again: last_polled_at = pytz . utc . localize ( last_polled_at ) if last_polled_at else None try : while True : feed_xml = get_feed_xml ( repeater . requests , feed_name , page ) if has_new_entries_since ( last_polled_at , feed_xml ) : for entry in feed_xml . xpath ( './atom:entry' , namespaces = { 'atom' : 'http://www.w3.org/2005/Atom' } ) : if has_new_entries_since ( last_polled_at , entry , './atom:published' ) : entry_uuid = get_uuid ( entry ) if entry_uuid : yield entry_uuid next_page = feed_xml . xpath ( './atom:link[@rel="next-archive"]' , namespaces = { 'atom' : 'http://www.w3.org/2005/Atom' } ) if next_page : href = next_page [ 0 ] . get ( 'href' ) page = href . split ( '/' ) [ - 1 ] else : if not page : this_page = feed_xml . xpath ( './atom:link[@rel="via"]' , namespaces = { 'atom' : 'http://www.w3.org/2005/Atom' } ) href = this_page [ 0 ] . get ( 'href' ) page = href . split ( '/' ) [ - 1 ] break except ( RequestException , HTTPError ) : # Don't update repeater if OpenMRS is offline return except OpenmrsFeedDoesNotExist : repeater . atom_feed_status [ feed_name ] = AtomFeedStatus ( ) repeater . save ( ) else : repeater . atom_feed_status [ feed_name ] = AtomFeedStatus ( last_polled_at = datetime . utcnow ( ) , last_page = page , ) repeater . save ( )