From 2acaf3fdaa8ab04a7d1c86210698323038233d94 Mon Sep 17 00:00:00 2001 From: Jany Belluz Date: Thu, 19 Jul 2018 16:46:32 +0100 Subject: [PATCH] Fix crash when round-tripping a GSFeaturePrefix containing only a comment --- Lib/glyphsLib/builder/features.py | 19 +++++++++++-------- tests/builder/features_test.py | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Lib/glyphsLib/builder/features.py b/Lib/glyphsLib/builder/features.py index 17cfc6d47..71d13743e 100644 --- a/Lib/glyphsLib/builder/features.py +++ b/Lib/glyphsLib/builder/features.py @@ -346,8 +346,8 @@ def __init__(self, list): self.index = 0 self.list = list - def has_next(self): - return self.index < len(self.list) + def has_next(self, n=0): + return (self.index + n) < len(self.list) def next(self): res = self.list[self.index] @@ -425,10 +425,11 @@ def _process_prefix(self): if self.PREFIX_RE.match(st.text): break # ...or if it is the "automatic" comment just before a class - next_st = self.statements.peek(1) - if self.AUTOMATIC_RE.match(st.text) and isinstance( - next_st, ast.GlyphClassDefinition): - break + if self.statements.has_next(1): + next_st = self.statements.peek(1) + if self.AUTOMATIC_RE.match(st.text) and isinstance( + next_st, ast.GlyphClassDefinition): + break prefix_statements.append(st) self.statements.next() @@ -576,7 +577,9 @@ def _pop_comment_block(self, statements, header_re): return (match, dedent(''.join(c.text[1:] + "\n" for c in comments)), res) + # Strip up to the given number of newlines from the right end of the string def _rstrip_newlines(self, string, number=1): - if len(string) >= number and string[-number:] == '\n' * number: - string = string[:-number] + for i in range(number): + if string and string[-1] == '\n': + string = string[:-1] return string diff --git a/tests/builder/features_test.py b/tests/builder/features_test.py index e2f27c04f..9fdebf8af 100644 --- a/tests/builder/features_test.py +++ b/tests/builder/features_test.py @@ -335,3 +335,24 @@ def test_roundtrip_automatic_feature(): assert feature_r.name == "ccmp" assert feature_r.code == "sub c by c.ss03;" assert feature_r.automatic is True + + +def test_roundtrip_feature_prefix_with_only_a_comment(): + font = to_glyphs([defcon.Font()]) + prefix = classes.GSFeaturePrefix(name="include") + # Contents: just a comment + prefix.code = "#include(../family.fea)" + font.featurePrefixes.append(prefix) + + ufo, = to_ufos(font) + + assert ufo.features.text == dedent('''\ + # Prefix: include + #include(../family.fea) + ''') + + font_r = to_glyphs([ufo]) + assert len(font_r.featurePrefixes) == 1 + prefix_r = font_r.featurePrefixes[0] + assert prefix_r.name == 'include' + assert prefix_r.code == "#include(../family.fea)"