Skip to content

Commit

Permalink
Recognize all macro definitions in hash-style comments
Browse files Browse the repository at this point in the history
Macro definitions can be commented out by replacing '%' with '#',
for example `%global debug 1` with `#global debug 1`, to avoid
`Macro expanded in comment` warning. However, the same can be achieved
also by escaping the '%' in the comment, i.e. `#%%global debug 1`,
and even if the '%' is not escaped, it is still parseable, so we should
be able to parse it as well.

Signed-off-by: Nikola Forró <[email protected]>
  • Loading branch information
nforro committed Dec 13, 2023
1 parent a38cede commit 4c9d61b
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 14 deletions.
42 changes: 30 additions & 12 deletions specfile/macro_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
class CommentOutStyle(Enum):
DNL = auto()
HASH = auto()
OTHER = auto()


class MacroDefinition:
Expand All @@ -30,6 +31,7 @@ def __init__(
comment_out_style: CommentOutStyle,
whitespace: Tuple[str, str, str, str],
dnl_whitespace: str = "",
comment_prefix: str = "",
valid: bool = True,
preceding_lines: Optional[List[str]] = None,
) -> None:
Expand All @@ -40,6 +42,7 @@ def __init__(
self.comment_out_style = comment_out_style
self._whitespace = whitespace
self._dnl_whitespace = dnl_whitespace
self._comment_prefix = comment_prefix
self.valid = valid
self._preceding_lines = (
preceding_lines.copy() if preceding_lines is not None else []
Expand All @@ -56,6 +59,7 @@ def __eq__(self, other: object) -> bool:
and self.comment_out_style == other.comment_out_style
and self._whitespace == other._whitespace
and self._dnl_whitespace == other._dnl_whitespace
and self._comment_prefix == other._comment_prefix
and self._preceding_lines == other._preceding_lines
)

Expand All @@ -64,20 +68,26 @@ def __repr__(self) -> str:
return (
f"MacroDefinition({self.name!r}, {self.body!r}, {self.is_global!r}, "
f"{self.commented_out!r}, {self.comment_out_style!r}, {self._whitespace!r}, "
f"{self._dnl_whitespace!r}, {self._comment_prefix!r}, "
f"{self.valid!r}, {self._preceding_lines!r})"
)

def __str__(self) -> str:
ws = self._whitespace
dnl = ""
pre = ""
sc = "%"
if self.commented_out:
if self.comment_out_style is CommentOutStyle.DNL:
dnl = f"%dnl{self._dnl_whitespace}"
elif self.comment_out_style is CommentOutStyle.OTHER:
pre = self._comment_prefix
elif self.comment_out_style is CommentOutStyle.HASH:
sc = "#"
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]}"
return (
f"{ws[0]}{dnl}{pre}{sc}{macro}{ws[1]}{self.name}{ws[2]}{self.body}{ws[3]}"
)

def get_position(self, container: "MacroDefinitions") -> int:
"""
Expand All @@ -97,10 +107,13 @@ def get_raw_data(self) -> List[str]:
result = self._preceding_lines.copy()
ws = self._whitespace
dnl = ""
pre = ""
sc = "%"
if self.commented_out:
if self.comment_out_style is CommentOutStyle.DNL:
dnl = f"%dnl{self._dnl_whitespace}"
elif self.comment_out_style is CommentOutStyle.OTHER:
pre = self._comment_prefix
elif self.comment_out_style is CommentOutStyle.HASH:
sc = "#"
macro = "global" if self.is_global else "define"
Expand All @@ -109,7 +122,7 @@ def get_raw_data(self) -> List[str]:
body[-1] += ws[3]
else:
body = [ws[3]]
result.append(f"{ws[0]}{dnl}{sc}{macro}{ws[1]}{self.name}{ws[2]}{body[0]}")
result.append(f"{ws[0]}{dnl}{pre}{sc}{macro}{ws[1]}{self.name}{ws[2]}{body[0]}")
result.extend(body[1:])
return result

Expand Down Expand Up @@ -303,16 +316,16 @@ def count_brackets(s):
md_regex = re.compile(
r"""
^
(\s*) # optional preceding whitespace
(%dnl\s+)? # optional DNL prefix
((?(2)%|(?:%|\#))) # starting character
(global|define) # scope-defining macro definition
(\s*) # optional preceding whitespace
(%dnl\s+)? # optional DNL prefix
((?(2)%|(?:%|\#(?:.*?%)?))) # starting character with optional comment prefix
(global|define) # scope-defining macro definition
(\s+)
(\w+(?:\(.*?\))?) # macro name with optional arguments in parentheses
(\w+(?:\(.*?\))?) # macro name with optional arguments in parentheses
(\s+)
(.*?) # macro body
(\s*|\\) # optional following whitespace or a backslash indicating
# that the macro body continues on the next line
(.*?) # macro body
(\s*|\\) # optional following whitespace or a backslash indicating
# that the macro body continues on the next line
$
""",
re.VERBOSE,
Expand Down Expand Up @@ -345,10 +358,15 @@ def count_brackets(s):
name,
body,
macro == "global",
bool(dnl or sc == "#"),
CommentOutStyle.HASH if sc == "#" else CommentOutStyle.DNL,
bool(dnl or sc.startswith("#")),
CommentOutStyle.HASH
if sc == "#"
else CommentOutStyle.OTHER
if sc.startswith("#")
else CommentOutStyle.DNL,
(ws0, ws1, ws2, ws3),
dnl[4:] if dnl else " ",
sc[:-1] if len(sc) > 1 else "",
valid,
buffer,
)
Expand Down
22 changes: 20 additions & 2 deletions tests/unit/test_macro_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def test_parse():
"",
"%dnl %global pre a1",
"#global prerel beta2",
"# %global prerelease pre3",
"",
"Name: test",
"Version: 0.1.0",
Expand All @@ -115,8 +116,11 @@ def test_parse():
assert macro_definitions[4].name == "prerel"
assert macro_definitions[4].commented_out
assert macro_definitions[4].comment_out_style is CommentOutStyle.HASH
assert macro_definitions[5].name == "desc(x)"
assert macro_definitions[5].body == (
assert macro_definitions[5].name == "prerelease"
assert macro_definitions[5].commented_out
assert macro_definitions[5].comment_out_style is CommentOutStyle.OTHER
assert macro_definitions[6].name == "desc(x)"
assert macro_definitions[6].body == (
"Test spec file containing several \\\n"
"macro definitions in various formats (%?1)"
)
Expand Down Expand Up @@ -163,6 +167,7 @@ def test_get_raw_data():
CommentOutStyle.DNL,
("", " ", " ", ""),
" ",
"",
True,
[""],
),
Expand All @@ -174,6 +179,16 @@ def test_get_raw_data():
CommentOutStyle.HASH,
("", " ", " ", ""),
),
MacroDefinition(
"prerelease",
"pre3",
True,
True,
CommentOutStyle.OTHER,
("", " ", " ", ""),
"",
"# ",
),
MacroDefinition(
"desc(x)",
"Test spec file containing several \\\nmacro definitions in various formats (%?1)",
Expand All @@ -182,6 +197,7 @@ def test_get_raw_data():
CommentOutStyle.DNL,
("", " ", " ", ""),
"",
"",
True,
[
"",
Expand All @@ -200,6 +216,7 @@ def test_get_raw_data():
CommentOutStyle.DNL,
("", " ", " ", ""),
"",
"",
True,
[""],
),
Expand All @@ -212,6 +229,7 @@ def test_get_raw_data():
"",
"%dnl %global pre a1",
"#global prerel beta2",
"# %global prerelease pre3",
"",
"Name: test",
"Version: 0.1.0",
Expand Down

0 comments on commit 4c9d61b

Please sign in to comment.