From ea9a85b874442979bdfd56d35d79967e369211a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= Date: Mon, 1 Jul 2024 15:05:06 +0200 Subject: [PATCH 1/2] Handle trailing whitespace in tag values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nikola Forró --- specfile/tags.py | 8 ++++++-- tests/unit/test_tags.py | 14 +++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/specfile/tags.py b/specfile/tags.py index bf892cd..ea8a469 100644 --- a/specfile/tags.py +++ b/specfile/tags.py @@ -499,6 +499,10 @@ def regex_pattern(tag): data = [] buffer: List[str] = [] for line, valid in lines: + ws = "" + tokens = re.split(r"([^\S\n]+)$", line, maxsplit=1) + if len(tokens) > 1: + line, ws, _ = tokens line, prefix, suffix = split_conditional_macro_expansion(line) # 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) @@ -511,13 +515,13 @@ def regex_pattern(tag): Comments.parse(buffer), valid, prefix, - suffix, + suffix + ws, context, ) ) buffer = [] else: - buffer.append(prefix + line + suffix) + buffer.append(prefix + line + suffix + ws) return cls(data, buffer) def get_raw_section_data(self) -> List[str]: diff --git a/tests/unit/test_tags.py b/tests/unit/test_tags.py index 66c7bff..7d4218f 100644 --- a/tests/unit/test_tags.py +++ b/tests/unit/test_tags.py @@ -43,7 +43,7 @@ def test_parse(): "Epoch: 1", "%endif", "", - "Requires: make", + "Requires: make ", "Requires(post): bash", "", "Provides: testX = %{version}-%{release}", @@ -102,7 +102,15 @@ def test_get_raw_section_data(): Comments([Comment("this is a valid comment", " # ")]), ), Tag("Epoch", "1", ": ", Comments([], ["", "%if 0"])), - Tag("Requires", "make", ": ", Comments([], ["%endif", ""])), + Tag( + "Requires", + "make", + ": ", + Comments([], ["%endif", ""]), + True, + "", + " ", + ), Tag("Requires(post)", "bash", ": ", Comments()), Tag( "Suggests", @@ -133,7 +141,7 @@ def test_get_raw_section_data(): "Epoch: 1", "%endif", "", - "Requires: make", + "Requires: make ", "Requires(post): bash", "", "%{?fedora:Suggests: diffutils}", From cac33a0540264e20db07f343851bada00b074205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= Date: Mon, 1 Jul 2024 15:06:47 +0200 Subject: [PATCH 2/2] Fix regexes to split only prefixes/suffixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In theory this shouldn't be necessary, but it's better to be safe. Signed-off-by: Nikola Forró --- specfile/prep.py | 4 ++-- specfile/sources.py | 2 +- specfile/value_parser.py | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/specfile/prep.py b/specfile/prep.py index 8a1311e..bf5c880 100644 --- a/specfile/prep.py +++ b/specfile/prep.py @@ -112,7 +112,7 @@ class PatchMacro(PrepMacro): @property def number(self) -> int: """Number of the %patch macro.""" - tokens = re.split(r"(\d+)", self.name, maxsplit=1) + tokens = re.split(r"(\d+)$", self.name, maxsplit=1) if len(tokens) > 1: return int(tokens[1]) if self.options.P is not None: @@ -123,7 +123,7 @@ def number(self) -> int: @number.setter def number(self, value: int) -> None: - tokens = re.split(r"(\d+)", self.name, maxsplit=1) + tokens = re.split(r"(\d+)$", self.name, maxsplit=1) if len(tokens) > 1: self.name = f"{tokens[0]}{value}" elif self.options.P is not None: diff --git a/specfile/sources.py b/specfile/sources.py index aa1994a..a4c2bf0 100644 --- a/specfile/sources.py +++ b/specfile/sources.py @@ -104,7 +104,7 @@ def _extract_number(self) -> Optional[str]: Returns: Extracted number or `None` if there isn't one. """ - tokens = re.split(r"(\d+)", self._tag.name, maxsplit=1) + tokens = re.split(r"(\d+)$", self._tag.name, maxsplit=1) if len(tokens) > 1: return tokens[1] return None diff --git a/specfile/value_parser.py b/specfile/value_parser.py index d5241be..1b57c26 100644 --- a/specfile/value_parser.py +++ b/specfile/value_parser.py @@ -74,7 +74,7 @@ class MacroSubstitution(Node): """Node representing macro substitution, e.g. _%version_.""" def __init__(self, body: str) -> None: - tokens = re.split(r"([?!]*)", body, maxsplit=1) + tokens = re.split(r"^([?!]*)", body, maxsplit=1) if len(tokens) == 1: self.prefix, self.name = "", tokens[0] else: @@ -97,7 +97,7 @@ class EnclosedMacroSubstitution(Node): """Node representing macro substitution enclosed in brackets, e.g. _%{?dist}_.""" def __init__(self, body: str) -> None: - tokens = re.split(r"([?!]*)", body, maxsplit=1) + tokens = re.split(r"^([?!]*)", body, maxsplit=1) if len(tokens) == 1: self.prefix, rest = "", tokens[0] else: @@ -129,7 +129,7 @@ class ConditionalMacroExpansion(Node): """Node representing conditional macro expansion, e.g. _%{?prerel:0.}_.""" def __init__(self, condition: str, body: List[Node]) -> None: - tokens = re.split(r"([?!]*)", condition, maxsplit=1) + tokens = re.split(r"^([?!]*)", condition, maxsplit=1) if len(tokens) == 1: self.prefix, self.name = "", tokens[0] else: @@ -271,7 +271,7 @@ def find_macro_end(index): elif value[start + 1] == "{": if ":" in value[start:end]: condition, body = value[start + 2 : end - 1].split(":", maxsplit=1) - tokens = re.split(r"([?!]*)", condition, maxsplit=1) + tokens = re.split(r"^([?!]*)", condition, maxsplit=1) prefix = tokens[0 if len(tokens) == 1 else 1] if "?" in prefix: result.append(