diff --git a/specfile/tags.py b/specfile/tags.py index ea8a469..f89c4a0 100644 --- a/specfile/tags.py +++ b/specfile/tags.py @@ -23,7 +23,7 @@ from specfile.macros import Macros from specfile.sections import Section from specfile.types import SupportsIndex -from specfile.utils import UserList, split_conditional_macro_expansion +from specfile.utils import UserList, count_brackets, split_conditional_macro_expansion if TYPE_CHECKING: from specfile.specfile import Specfile @@ -489,6 +489,13 @@ def parse(cls, section: Section, context: Optional["Specfile"] = None) -> "Tags" New instance of `Tags` class. """ + def pop(lines): + line = lines.pop(0) + if isinstance(line, str): + return line, True + else: + return line + def regex_pattern(tag): name_regex = get_tag_name_regex(tag) return rf"^(?P{name_regex})(?P\s*:\s*)(?P.+)" @@ -498,7 +505,8 @@ def regex_pattern(tag): tag_regexes = [re.compile(regex_pattern(t), re.IGNORECASE) for t in TAG_NAMES] data = [] buffer: List[str] = [] - for line, valid in lines: + while lines: + line, valid = pop(lines) ws = "" tokens = re.split(r"([^\S\n]+)$", line, maxsplit=1) if len(tokens) > 1: @@ -507,10 +515,21 @@ def regex_pattern(tag): # find out if there is a match for one of the tag regexes m = next((m for m in (r.match(line) for r in tag_regexes) if m), None) if m: + value = m.group("v") + if not suffix: + bc, pc = count_brackets(value) + while (bc > 0 or pc > 0) and lines: + value += ws + line, _ = pop(lines) + tokens = re.split(r"([^\S\n]+)$", line, maxsplit=1) + if len(tokens) > 1: + line, ws, _ = tokens + value += "\n" + line + bc, pc = count_brackets(value) data.append( Tag( m.group("n"), - m.group("v"), + value, m.group("s"), Comments.parse(buffer), valid, @@ -534,8 +553,10 @@ def get_raw_section_data(self) -> List[str]: result = [] for tag in self.data: result.extend(tag.comments.get_raw_data()) - result.append( - f"{tag._prefix}{tag.name}{tag._separator}{tag.value}{tag._suffix}" + result.extend( + f"{tag._prefix}{tag.name}{tag._separator}{tag.value}{tag._suffix}".split( + "\n" + ) ) result.extend(self._remainder) return result diff --git a/tests/unit/test_tags.py b/tests/unit/test_tags.py index 7d4218f..b30ec4d 100644 --- a/tests/unit/test_tags.py +++ b/tests/unit/test_tags.py @@ -43,6 +43,11 @@ def test_parse(): "Epoch: 1", "%endif", "", + "License: %{shrink:", + " MIT AND", + " (MIT OR Apache-2.0)", + " }", + "", "Requires: make ", "Requires(post): bash", "", @@ -62,6 +67,13 @@ def test_parse(): assert not tags[1].comments assert tags.release.comments[0].prefix == " # " assert tags.epoch.name == "Epoch" + assert tags[-6].name == "License" + assert ( + tags[-6].value == "%{shrink:\n" + " MIT AND\n" + " (MIT OR Apache-2.0)\n" + " }" + ) assert tags.requires.value == "make" assert "requires(post)" in tags assert tags[-4].name == "Requires(post)" @@ -102,11 +114,20 @@ def test_get_raw_section_data(): Comments([Comment("this is a valid comment", " # ")]), ), Tag("Epoch", "1", ": ", Comments([], ["", "%if 0"])), + Tag( + "License", + "%{shrink:\n" + " MIT AND\n" + " (MIT OR Apache-2.0)\n" + " }", + ": ", + Comments([], ["%endif", ""]), + ), Tag( "Requires", "make", ": ", - Comments([], ["%endif", ""]), + Comments([], [""]), True, "", " ", @@ -141,6 +162,11 @@ def test_get_raw_section_data(): "Epoch: 1", "%endif", "", + "License: %{shrink:", + " MIT AND", + " (MIT OR Apache-2.0)", + " }", + "", "Requires: make ", "Requires(post): bash", "",