diff --git a/src/ass/line.py b/src/ass/line.py index 5d1defc..5dbbc98 100644 --- a/src/ass/line.py +++ b/src/ass/line.py @@ -41,7 +41,11 @@ def dump(self, field_order=None): if field_order is None: field_order = self.DEFAULT_FIELD_ORDER - return ",".join(_Field.dump(self.fields[field]) + # A field in field_order that the line does not carry (for example when + # a section has a second "Format:" line that redefines the order after + # the lines were parsed) dumps as empty rather than raising KeyError. + return ",".join(_Field.dump(self.fields[field]) if field in self.fields + else "" for field in field_order) def dump_with_type(self, field_order=None): diff --git a/tests/test_ass.py b/tests/test_ass.py index 317880c..a3586bb 100755 --- a/tests/test_ass.py +++ b/tests/test_ass.py @@ -135,6 +135,19 @@ def test_custom_line_section_write(self, line_section): def test_custom_line_section_dump(self, line_section): assert "\n".join(line_section.dump()) == self.TEST_CUSTOM + def test_dump_after_format_redefinition(self): + # A second "Format:" line in a section redefines the field order after + # the lines were parsed; dumping such a document used to raise KeyError. + doc = ass.Document.parse_string(dedent("""\ + [Events] + Format: Layer, Start, End, Style, Text + Dialogue: 0,0:00:01.00,0:00:04.00,Default,Hello + Format: a""")) + out = StringIO() + doc.dump_file(out) + # the dumped document parses again without error + assert ass.Document.parse_string(out.getvalue()) is not None + class TestEvents: