New code for applying edits to an EDL.

This commit is contained in:
Edward Betts 2018-06-04 12:18:39 +01:00
parent 5eb927565d
commit 66ea0d1826
3 changed files with 161 additions and 0 deletions

89
sourcing/edit.py Normal file
View file

@ -0,0 +1,89 @@
import attr
class EditOutOfRange(Exception):
pass
def apply_delete(current_spans, edit):
assert edit
if not current_spans:
raise ValueError('edit is out of bounds')
spans = []
pos = 0
edit_end = edit['start'] + len(edit['old'])
cur_span = current_spans.pop(0)
while pos + cur_span.length < edit['start']:
spans.append(cur_span)
pos += cur_span.length
cur_span = current_spans.pop(0)
if edit['start'] > pos:
new_span = attr.evolve(cur_span, length=edit['start'] - pos)
spans.append(new_span)
while pos + cur_span.length < edit_end:
pos += cur_span.length
cur_span = current_spans.pop(0)
if pos + cur_span.length != edit_end:
offset = cur_span.start - pos
new_start = offset + (edit_end - pos)
diff = new_start - cur_span.start
new_span = attr.evolve(cur_span,
length=cur_span.length - diff,
start=new_start)
spans.append(new_span)
spans += current_spans
return spans
def apply_insert(current_spans, edit):
if not current_spans and edit['0'] == 0:
return edit['span']
pos = 0
spans = []
cur_span = current_spans.pop(0)
while pos + cur_span.length < edit['start']:
spans.append(cur_span)
pos += cur_span.length
cur_span = current_spans.pop(0)
if edit['start'] >= pos:
length_a = edit['start'] - pos
length_b = cur_span.length - length_a
if length_a:
span_a = attr.evolve(cur_span, length=length_a)
pos += length_a
spans.append(span_a)
spans.append(edit['span'])
pos += edit['span'].length
if length_b:
span_b = attr.evolve(cur_span,
start=cur_span.start + length_a,
length=length_b)
spans.append(span_b)
pos += length_b
else:
spans.append(edit['span'])
spans += current_spans
return spans
def apply_edits(spans, edits):
for edit in edits:
if edit['op'] == 'delete':
spans = apply_delete(spans, edit)
continue
if edit['op'] == 'insert':
spans = apply_insert(spans, edit)
continue
return spans

18
sourcing/span.py Normal file
View file

@ -0,0 +1,18 @@
import attr
def greater_than_zero(instance, attribute, value):
if value <= 0:
raise ValueError('must be greater than 0')
def is_positive(instance, attribute, value):
if value < 0:
raise ValueError('must be positive')
@attr.s
class Span:
url: int = attr.ib()
start: int = attr.ib(validator=is_positive)
length: int = attr.ib(validator=greater_than_zero)
def end(self) -> int:
return self.start + self.length