def apply_changes(self, lecture: Lecture, changes: CollectedChanges) -> FetchResult: result = FetchResult.create( fetched=changes.unchanged, errored=changes.errored, next_start_index=changes.next_start_index, ) # Build amendement -> position map moved_amendements = { amendement: changes.position_changes[amendement.num] for amendement in lecture.amendements if amendement.num in changes.position_changes } # Reset positions first, so that we never have two with the same position # (which would trigger an integrity error due to the unique constraint) for amendement in moved_amendements: amendement.position = None DBSession.flush() # Create amendements in numerical order, because a "sous-amendement" # must always be created after its parent for create_action in sorted(changes.creates, key=attrgetter("num")): result += create_action.apply(lecture) # Update amendements for update_action in changes.updates: result += update_action.apply(lecture) # Apply new amendement positions for amendement, position in moved_amendements.items(): if amendement.position != position: amendement.position = position DBSession.flush() # Was it the last batch? if changes.next_start_index is None: lecture.reset_fetch_progress() return result
def _fetch(self, lecture: Lecture, dry_run: bool = False) -> FetchResult: created: Set[int] = set() amendements: List[Amendement] = [] # Remember previous positions and reset them old_positions = {} for amendement in lecture.amendements: old_positions[amendement.num] = amendement.position amendement.position = None try: amendements_created = self._fetch_and_parse_all(lecture=lecture, dry_run=dry_run) except NotFound: return FetchResult.create(fetched=set(), created=set()) for amendement, created_ in amendements_created: if created_: created.add(amendement.num) amendements.append(amendement) processed_amendements = list( self._process_amendements(amendements=amendements, lecture=lecture)) lecture.reset_fetch_progress() # Log amendements no longer discussed for amdt in lecture.amendements: if amdt.position is None and old_positions.get( amdt.num) is not None: logger.info("Amendement %s retiré de la discussion", amdt.num) return FetchResult.create( fetched={amdt.num for amdt in processed_amendements}, created=created)