From 9c4d01dc99d8ac173b43225be8debb0f99036f7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= Date: Thu, 2 Nov 2023 16:39:37 +0100 Subject: [PATCH] Allow to disable or comment out a macro definition (or vice versa) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nikola Forró --- specfile/macro_definitions.py | 50 +++++++++++++------ specfile/specfile.py | 2 + tests/unit/test_macro_definitions.py | 75 +++++++++++++++++++++++++--- 3 files changed, 104 insertions(+), 23 deletions(-) diff --git a/specfile/macro_definitions.py b/specfile/macro_definitions.py index 166c684..c88074b 100644 --- a/specfile/macro_definitions.py +++ b/specfile/macro_definitions.py @@ -20,14 +20,20 @@ def __init__( name: str, body: str, is_global: bool, + disabled: bool, + commented_out: bool, whitespace: Tuple[str, str, str, str], + dnl_whitespace: str = "", valid: bool = True, preceding_lines: Optional[List[str]] = None, ) -> None: self.name = name self.body = body self.is_global = is_global + self.disabled = disabled + self.commented_out = commented_out self._whitespace = whitespace + self._dnl_whitespace = dnl_whitespace self.valid = valid self._preceding_lines = ( preceding_lines.copy() if preceding_lines is not None else [] @@ -40,7 +46,10 @@ def __eq__(self, other: object) -> bool: self.name == other.name and self.body == other.body and self.is_global == other.is_global + and self.disabled == other.disabled + and self.commented_out == other.commented_out and self._whitespace == other._whitespace + and self._dnl_whitespace == other._dnl_whitespace and self._preceding_lines == other._preceding_lines ) @@ -48,13 +57,16 @@ def __eq__(self, other: object) -> bool: def __repr__(self) -> str: return ( f"MacroDefinition({self.name!r}, {self.body!r}, {self.is_global!r}, " - f"{self._whitespace!r}, {self.valid!r}, {self._preceding_lines!r})" + f"{self.disabled!r}, {self.commented_out!r}, {self._whitespace!r}, " + f"{self.valid!r}, {self._preceding_lines!r})" ) def __str__(self) -> str: ws = self._whitespace - macro = "%global" if self.is_global else "%define" - return f"{ws[0]}{macro}{ws[1]}{self.name}{ws[2]}{self.body}{ws[3]}" + dnl = f"%dnl{self._dnl_whitespace}" if self.disabled else "" + sc = "#" if self.commented_out else "%" + macro = "global" if self.is_global else "define" + return f"{ws[0]}{dnl}{sc}{macro}{ws[1]}{self.name}{ws[2]}{self.body}{ws[3]}" def get_position(self, container: "MacroDefinitions") -> int: """ @@ -73,13 +85,15 @@ def get_position(self, container: "MacroDefinitions") -> int: def get_raw_data(self) -> List[str]: result = self._preceding_lines.copy() ws = self._whitespace - macro = "%global" if self.is_global else "%define" + dnl = f"%dnl{self._dnl_whitespace}" if self.disabled else "" + sc = "#" if self.commented_out else "%" + macro = "global" if self.is_global else "define" body = self.body.splitlines() if body: body[-1] += ws[3] else: body = [ws[3]] - result.append(f"{ws[0]}{macro}{ws[1]}{self.name}{ws[2]}{body[0]}") + result.append(f"{ws[0]}{dnl}{sc}{macro}{ws[1]}{self.name}{ws[2]}{body[0]}") result.extend(body[1:]) return result @@ -249,7 +263,9 @@ def count_brackets(s): r""" ^ (\s*) # optional preceding whitespace - (%(?:global|define)) # scope-defining macro definition + ((?:%dnl\s+)?) # optional DNL prefix + (%|\#) # starting character + (global|define) # scope-defining macro definition (\s+) (\w+(?:\(.*?\))?) # macro name with optional arguments in parentheses (\s+) @@ -267,15 +283,16 @@ def count_brackets(s): line, valid = pop(lines) m = md_regex.match(line) if m: - ws0, macro, ws1, name, ws2, body, ws3 = m.groups() - if ws3 == "\\": - body += ws3 - ws3 = "" - bc, pc = count_brackets(body) - while (bc > 0 or pc > 0 or body.endswith("\\")) and lines: - line, _ = pop(lines) - body += "\n" + line + ws0, dnl, sc, macro, ws1, name, ws2, body, ws3 = m.groups() + if not dnl and sc == "%": + if ws3 == "\\": + body += ws3 + ws3 = "" bc, pc = count_brackets(body) + while (bc > 0 or pc > 0 or body.endswith("\\")) and lines: + line, _ = pop(lines) + body += "\n" + line + bc, pc = count_brackets(body) tokens = re.split(r"(\s+)$", body, maxsplit=1) if len(tokens) == 1: body = tokens[0] @@ -286,8 +303,11 @@ def count_brackets(s): MacroDefinition( name, body, - macro == "%global", + macro == "global", + bool(dnl), + sc == "#", (ws0, ws1, ws2, ws3), + dnl[4:] if dnl else "", valid, buffer, ) diff --git a/specfile/specfile.py b/specfile/specfile.py index 4fd11e5..ab14080 100644 --- a/specfile/specfile.py +++ b/specfile/specfile.py @@ -730,6 +730,8 @@ class Entity: ) for md in macro_definitions if md.valid + and not md.disabled + and not md.commented_out and not protected_regex.match(md.name) and not md.name.endswith(")") # skip macro definitions with options ] diff --git a/tests/unit/test_macro_definitions.py b/tests/unit/test_macro_definitions.py index 4673ca5..8e76728 100644 --- a/tests/unit/test_macro_definitions.py +++ b/tests/unit/test_macro_definitions.py @@ -11,15 +11,24 @@ def test_find(): macro_definitions = MacroDefinitions( [ - MacroDefinition("gitdate", "20160901", True, ("", " ", " ", "")), + MacroDefinition( + "gitdate", "20160901", True, False, False, ("", " ", " ", "") + ), MacroDefinition( "commit", "9ab9717cf7d1be1a85b165a8eacb71b9e5831113", True, + False, + False, ("", " ", " ", ""), ), MacroDefinition( - "shortcommit", "%(c=%{commit}; echo ${c:0:7})", True, ("", " ", " ", "") + "shortcommit", + "%(c=%{commit}; echo ${c:0:7})", + True, + False, + False, + ("", " ", " ", ""), ), ] ) @@ -32,15 +41,24 @@ def test_find(): def test_get(): macro_definitions = MacroDefinitions( [ - MacroDefinition("gitdate", "20160901", True, ("", " ", " ", "")), + MacroDefinition( + "gitdate", "20160901", True, False, False, ("", " ", " ", "") + ), MacroDefinition( "commit", "9ab9717cf7d1be1a85b165a8eacb71b9e5831113", True, + False, + False, ("", " ", " ", ""), ), MacroDefinition( - "shortcommit", "%(c=%{commit}; echo ${c:0:7})", True, ("", " ", " ", "") + "shortcommit", + "%(c=%{commit}; echo ${c:0:7})", + True, + False, + False, + ("", " ", " ", ""), ), ] ) @@ -59,6 +77,9 @@ def test_parse(): "%global commit 9ab9717cf7d1be1a85b165a8eacb71b9e5831113", "%global shortcommit %(c=%{commit}; echo ${c:0:7})", "", + "%dnl %global pre a1", + "#global prerel beta2", + "", "Name: test", "Version: 0.1.0", "", @@ -74,8 +95,12 @@ def test_parse(): assert macro_definitions[1].name == "commit" assert macro_definitions.commit.body == "9ab9717cf7d1be1a85b165a8eacb71b9e5831113" assert macro_definitions[2].name == "shortcommit" - assert macro_definitions[3].name == "desc(x)" - assert macro_definitions[3].body == ( + assert macro_definitions[3].name == "pre" + assert macro_definitions[3].disabled + assert macro_definitions[4].name == "prerel" + assert macro_definitions[4].commented_out + assert macro_definitions[5].name == "desc(x)" + assert macro_definitions[5].body == ( "Test spec file containing several \\\n" "macro definitions in various formats (%?1)" ) @@ -90,21 +115,47 @@ def test_parse(): def test_get_raw_data(): macro_definitions = MacroDefinitions( [ - MacroDefinition("gitdate", "20160901", True, ("", " ", " ", "")), + MacroDefinition( + "gitdate", "20160901", True, False, False, ("", " ", " ", "") + ), MacroDefinition( "commit", "9ab9717cf7d1be1a85b165a8eacb71b9e5831113", True, + False, + False, ("", " ", " ", ""), ), MacroDefinition( - "shortcommit", "%(c=%{commit}; echo ${c:0:7})", True, ("", " ", " ", "") + "shortcommit", + "%(c=%{commit}; echo ${c:0:7})", + True, + False, + False, + ("", " ", " ", ""), + ), + MacroDefinition( + "pre", + "a1", + True, + True, + False, + ("", " ", " ", ""), + " ", + True, + [""], + ), + MacroDefinition( + "prerel", "beta2", True, False, True, ("", " ", " ", "") ), MacroDefinition( "desc(x)", "Test spec file containing several \\\nmacro definitions in various formats (%?1)", False, + False, + False, ("", " ", " ", ""), + "", True, [ "", @@ -119,7 +170,10 @@ def test_get_raw_data(): "This an example of a macro definition with body \n" "spawning across mutiple lines}", False, + False, + False, ("", " ", " ", ""), + "", True, [""], ), @@ -130,6 +184,9 @@ def test_get_raw_data(): "%global commit 9ab9717cf7d1be1a85b165a8eacb71b9e5831113", "%global shortcommit %(c=%{commit}; echo ${c:0:7})", "", + "%dnl %global pre a1", + "#global prerel beta2", + "", "Name: test", "Version: 0.1.0", "", @@ -149,6 +206,8 @@ def test_copy_macro_definitions(): "commit", "9ab9717cf7d1be1a85b165a8eacb71b9e5831113", True, + False, + False, ("", " ", " ", ""), ), ],