def map_event_section(events, patterns, text = "\n"): """ Map each event to a section in the text. Sections are provided by patterns. """ def make_event_data(pad, revs, event, args = ()): return pad, revs, event, args for event_data in events: pad, revs, event, data = make_event_data(*event_data) event_changeset = text_events.parse_event_changeset(event[u'changeset']) text, changes, new_changes = text_events.text_apply_event(text, event_changeset) range_sections = [] for start, end, section in make_sections_mapping(patterns, text): for change_start, change_end in new_changes: if start <= change_start < end or start < change_end <= end: if section and (start, end, section) not in range_sections: range_sections.append((start, end, section)) sections = [] for s_start, s_end, s_section in range_sections: for e_start, e_end, e_section in range_sections: if s_section != e_section and s_start <= e_start and e_end <= s_end: if e_end - e_start < s_end - s_start: break else: sections.append(s_section[-1]) # get only last part (section,) = sections if len(sections) == 1 else (None,) yield pad, revs, event, data + (section,)
def build_event_text(events, text = "\n"): import text_events for event in events: event_data = text_events.text_apply_event(text, event.changeset_data) text, event_changes, event_new_changes = event_data return text
def build_event_text(events, text="\n"): import text_events for event in events: event_data = text_events.text_apply_event(text, event.changeset_data) text, event_changes, event_new_changes = event_data return text
def map_event_section(events, patterns, text="\n"): """ Map each event to a section in the text. Sections are provided by patterns. """ def make_event_data(pad, revs, event, args=()): return pad, revs, event, args for event_data in events: pad, revs, event, data = make_event_data(*event_data) event_changeset = text_events.parse_event_changeset( event[u'changeset']) text, changes, new_changes = text_events.text_apply_event( text, event_changeset) range_sections = [] for start, end, section in make_sections_mapping(patterns, text): for change_start, change_end in new_changes: if start <= change_start < end or start < change_end <= end: if section and (start, end, section) not in range_sections: range_sections.append((start, end, section)) sections = [] for s_start, s_end, s_section in range_sections: for e_start, e_end, e_section in range_sections: if s_section != e_section and s_start <= e_start and e_end <= s_end: if e_end - e_start < s_end - s_start: break else: sections.append(s_section[-1]) # get only last part (section, ) = sections if len(sections) == 1 else (None, ) yield pad, revs, event, data + (section, )
def merge_events(events, threshold, text = "\n"): """ Merge events with the same author and if they overlap or have common bounds. Events may even not be subsequent, but they shouldn't depend on alternating events happened in the middle. "event_queue" is filled while events are in time window (threshold), then it is processed by taking the expanding event subsequence and trying to get a changeset from it. The longest event subsequence with correct independent changeset is merged into one event. """ events = iter(events) event_queue = [] next_event = next(events, None) while next_event or event_queue: while next_event: if event_queue: base_merge_event, base_include = event_queue[0] timestamp = base_merge_event.events[0].timestamp new_timestamp = next_event.events[-1].timestamp if new_timestamp - timestamp >= threshold: break event_queue.append((next_event, True)) next_event = next(events, None) event_author = None check_queue = [] check_event_queue = [] max_event_queue = [] max_event_positive_change = None max_event_negative_change = None for merge_event, include in event_queue: if event_author is None: event_author = merge_event.events[0].author if merge_event.events[0].author == event_author: check_event_queue.append(merge_event) check_queue_length = 0 for event in merge_event.events: check_include = include and event.author == event_author check_queue.append((event.changeset_data, check_include)) if check_include: check_queue_length = len(check_queue) if not check_queue_length: continue event_changes = text_events.text_make_changes_events(text, check_queue[:check_queue_length]) if event_changes: max_event_queue = list(check_event_queue) max_event_positive_change, max_event_negative_change = event_changes new_event_index = 0 for event_index, (merge_event, include) in enumerate(event_queue): include &= merge_event not in max_event_queue if new_event_index or include: event_queue[new_event_index] = merge_event, include new_event_index += 1 else: for event in merge_event.events: event_data = text_events.text_apply_event(text, event.changeset_data) text, event_changes, event_new_changes = event_data del event_queue[new_event_index:] if max_event_queue: merge_event = MergeEvent([event for merge_event in max_event_queue for event in merge_event.events]) merge_event.positive_changes = max_event_positive_change merge_event.negative_changes = max_event_negative_change merge_event.merge_count = len(max_event_queue) yield merge_event