181
180
Py_INCREF_ptr(par_temp[idx])
182
181
Py_DECREF_ptr(ann_temp[idx])
183
182
ann_temp[idx] = par_temp[idx]
186
cdef int _merge_annotations(this_annotation, annotations, parent_annotations,
187
matching_blocks, ann_cache) except -1:
188
cdef Py_ssize_t parent_idx, ann_idx, lines_idx, match_len, idx
190
cdef PyObject *ann_temp, *par_temp
192
_check_annotations_are_lists(annotations, parent_annotations)
196
for parent_idx, lines_idx, match_len in matching_blocks:
197
_check_match_ranges(parent_annotations, annotations,
198
parent_idx, lines_idx, match_len)
199
# For lines which match this parent, we will now resolve whether
200
# this parent wins over the current annotation
201
for idx from 0 <= idx < match_len:
202
ann_idx = lines_idx + idx
203
ann_temp = PyList_GET_ITEM(annotations, ann_idx)
204
par_temp = PyList_GET_ITEM(parent_annotations, parent_idx + idx)
205
if (ann_temp == par_temp):
206
# This is parent, do nothing
207
# Pointer comparison is fine here. Value comparison would
208
# be ok, but it will be handled in the final if clause by
209
# merging the two tuples into the same tuple
210
# Avoiding the Py_INCREF and function call to
211
# PyObject_RichCompareBool using pointer comparison drops
212
# timing from 215ms => 125ms
214
par_ann = <object>par_temp
215
ann = <object>ann_temp
216
if (ann is this_annotation):
217
# Originally claimed 'this', but it was really in this
220
PyList_SetItem(annotations, ann_idx, par_ann)
222
# Resolve the fact that both sides have a different value for
224
if (ann is last_ann and par_ann is last_parent):
226
PyList_SetItem(annotations, ann_idx, last_res)
228
new_ann = _combine_annotations(ann, par_ann, ann_cache)
230
PyList_SetItem(annotations, ann_idx, new_ann)
232
last_parent = par_ann
186
236
class Annotator(_annotator_py.Annotator):
189
239
def _update_from_first_parent(self, key, annotations, lines, parent_key):
190
240
"""Reannotate this text relative to its first parent."""
191
parent_annotations, matching_blocks = self._get_parent_annotations_and_matches(
192
key, lines, parent_key)
242
matching_blocks) = self._get_parent_annotations_and_matches(
243
key, lines, parent_key)
194
245
_apply_parent_annotations(annotations, parent_annotations,
197
248
def _update_from_other_parents(self, key, annotations, lines,
198
249
this_annotation, parent_key):
199
250
"""Reannotate this text relative to a second (or more) parent."""
200
cdef Py_ssize_t parent_idx, ann_idx, lines_idx, match_len, idx
202
cdef PyObject *ann_temp, *par_temp
203
parent_annotations, matching_blocks = self._get_parent_annotations_and_matches(
204
key, lines, parent_key)
205
_check_annotations_are_lists(annotations, parent_annotations)
209
cache = self._ann_tuple_cache
210
for parent_idx, lines_idx, match_len in matching_blocks:
211
_check_match_ranges(parent_annotations, annotations,
212
parent_idx, lines_idx, match_len)
213
# For lines which match this parent, we will now resolve whether
214
# this parent wins over the current annotation
215
for idx from 0 <= idx < match_len:
216
ann_idx = lines_idx + idx
217
ann_temp = PyList_GET_ITEM(annotations, ann_idx)
218
par_temp = PyList_GET_ITEM(parent_annotations, parent_idx + idx)
219
if (ann_temp == par_temp):
220
# This is parent, do nothing
221
# Pointer comparison is fine here. Value comparison would
222
# be ok, but it will be handled in the final if clause by
223
# merging the two tuples into the same tuple
224
# Avoiding the Py_INCREF by using pointer comparison drops
225
# timing from 215ms => 125ms
227
par_ann = <object>par_temp
228
ann = <object>ann_temp
229
if (ann is this_annotation):
230
# Originally claimed 'this', but it was really in this
233
PyList_SetItem(annotations, ann_idx, par_ann)
235
# Resolve the fact that both sides have a different value for
237
if (ann is last_ann and par_ann is last_parent):
239
PyList_SetItem(annotations, ann_idx, last_res)
241
new_ann = _combine_annotations(ann, par_ann, cache)
243
PyList_SetItem(annotations, ann_idx, new_ann)
245
last_parent = par_ann
252
matching_blocks) = self._get_parent_annotations_and_matches(
253
key, lines, parent_key)
254
_merge_annotations(this_annotation, annotations, parent_annotations,
255
matching_blocks, self._ann_tuple_cache)
248
257
def annotate_flat(self, key):
249
258
"""Determine the single-best-revision to source for each line.