Skip to content

Commit 1ab7eb4

Browse files
Merge pull request #188 from packit/sections
Ignore sections in macro definitions Fixes #184. Reviewed-by: Jiri Popelka <None>
2 parents 6085078 + fab0c7a commit 1ab7eb4

File tree

4 files changed

+110
-15
lines changed

4 files changed

+110
-15
lines changed

specfile/macro_definitions.py

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def get_raw_data(self) -> List[str]:
6767
result = self._preceding_lines.copy()
6868
ws = self._whitespace
6969
macro = "%global" if self.is_global else "%define"
70-
body = self.body.replace("\n", "\\\n").splitlines()
70+
body = self.body.splitlines()
7171
if body:
7272
body[-1] += ws[3]
7373
else:
@@ -198,6 +198,36 @@ def parse(cls, lines: List[str]) -> "MacroDefinitions":
198198
Returns:
199199
Constructed instance of `MacroDefinitions` class.
200200
"""
201+
202+
def count_brackets(s):
203+
bc = pc = 0
204+
chars = list(s)
205+
while chars:
206+
c = chars.pop(0)
207+
if c == "\\" and chars:
208+
chars.pop(0)
209+
continue
210+
if c == "%" and chars:
211+
c = chars.pop(0)
212+
if c == "{":
213+
bc += 1
214+
elif c == "(":
215+
pc += 1
216+
continue
217+
if c == "{" and bc > 0:
218+
bc += 1
219+
continue
220+
if c == "}" and bc > 0:
221+
bc -= 1
222+
continue
223+
if c == "(" and pc > 0:
224+
pc += 1
225+
continue
226+
if c == ")" and pc > 0:
227+
pc -= 1
228+
continue
229+
return bc, pc
230+
201231
md_regex = re.compile(
202232
r"""
203233
^
@@ -215,21 +245,26 @@ def parse(cls, lines: List[str]) -> "MacroDefinitions":
215245
)
216246
data = []
217247
buffer: List[str] = []
248+
lines = lines.copy()
218249
while lines:
219250
line = lines.pop(0)
220251
m = md_regex.match(line)
221252
if m:
222253
ws0, macro, ws1, name, ws2, body, ws3 = m.groups()
223254
if ws3 == "\\":
224-
while line.endswith("\\") and lines:
225-
line = lines.pop(0)
226-
body += "\n" + line.rstrip("\\")
227-
tokens = re.split(r"(\s+)$", body, maxsplit=1)
228-
if len(tokens) == 1:
229-
body = tokens[0]
230-
ws3 = ""
231-
else:
232-
body, ws3, _ = tokens
255+
body += ws3
256+
ws3 = ""
257+
bc, pc = count_brackets(body)
258+
while (bc > 0 or pc > 0 or body.endswith("\\")) and lines:
259+
line = lines.pop(0)
260+
body += "\n" + line
261+
bc, pc = count_brackets(body)
262+
tokens = re.split(r"(\s+)$", body, maxsplit=1)
263+
if len(tokens) == 1:
264+
body = tokens[0]
265+
else:
266+
body, ws, _ = tokens
267+
ws3 = ws + ws3
233268
data.append(
234269
MacroDefinition(
235270
name, body, macro == "%global", (ws0, ws1, ws2, ws3), buffer

specfile/sections.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
SIMPLE_SCRIPT_SECTIONS,
1414
)
1515
from specfile.formatter import formatted
16+
from specfile.macro_definitions import MacroDefinitions
1617
from specfile.macros import Macros
1718
from specfile.options import Options
1819

@@ -258,12 +259,20 @@ def split_id(line):
258259
return name, options, delimiter, separator, content
259260
return tokens[0], None, "", separator, content
260261

262+
excluded_lines = []
263+
macro_definitions = MacroDefinitions.parse(lines)
264+
for md in macro_definitions:
265+
position = md.get_position(macro_definitions)
266+
excluded_lines.append(range(position, position + len(md.get_raw_data())))
261267
section_id_regexes = [
262-
re.compile(rf"^%{re.escape(n)}(\s+.*$|$)", re.IGNORECASE)
268+
re.compile(rf"^%{re.escape(n)}(\s+.*(?<!\\)$|$)", re.IGNORECASE)
263269
for n in SECTION_NAMES
264270
]
265271
section_starts = []
266272
for i, line in enumerate(lines):
273+
# section can not start inside macro definition body
274+
if any(i in r for r in excluded_lines):
275+
continue
267276
if line.startswith("%"):
268277
for r in section_id_regexes:
269278
if r.match(line):

tests/unit/test_macro_definitions.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,27 @@ def test_parse():
6464
"",
6565
"%define desc(x) Test spec file containing several \\",
6666
"macro definitions in various formats (%?1)",
67+
"",
68+
"%define example() %{expand:",
69+
"This an example of a macro definition with body ",
70+
"spawning across mutiple lines}",
6771
]
6872
)
6973
assert macro_definitions[0].name == "gitdate"
7074
assert macro_definitions[1].name == "commit"
7175
assert macro_definitions.commit.body == "9ab9717cf7d1be1a85b165a8eacb71b9e5831113"
7276
assert macro_definitions[2].name == "shortcommit"
73-
assert macro_definitions[-1].name == "desc(x)"
74-
assert macro_definitions[-1].body == (
75-
"Test spec file containing several \n"
77+
assert macro_definitions[3].name == "desc(x)"
78+
assert macro_definitions[3].body == (
79+
"Test spec file containing several \\\n"
7680
"macro definitions in various formats (%?1)"
7781
)
82+
assert macro_definitions[-1].name == "example()"
83+
assert macro_definitions[-1].body == (
84+
"%{expand:\n"
85+
"This an example of a macro definition with body \n"
86+
"spawning across mutiple lines}"
87+
)
7888

7989

8090
def test_get_raw_data():
@@ -92,7 +102,7 @@ def test_get_raw_data():
92102
),
93103
MacroDefinition(
94104
"desc(x)",
95-
"Test spec file containing several \nmacro definitions in various formats (%?1)",
105+
"Test spec file containing several \\\nmacro definitions in various formats (%?1)",
96106
False,
97107
("", " ", " ", ""),
98108
[
@@ -102,6 +112,15 @@ def test_get_raw_data():
102112
"",
103113
],
104114
),
115+
MacroDefinition(
116+
"example()",
117+
"%{expand:\n"
118+
"This an example of a macro definition with body \n"
119+
"spawning across mutiple lines}",
120+
False,
121+
("", " ", " ", ""),
122+
[""],
123+
),
105124
]
106125
)
107126
assert macro_definitions.get_raw_data() == [
@@ -114,6 +133,10 @@ def test_get_raw_data():
114133
"",
115134
"%define desc(x) Test spec file containing several \\",
116135
"macro definitions in various formats (%?1)",
136+
"",
137+
"%define example() %{expand:",
138+
"This an example of a macro definition with body ",
139+
"spawning across mutiple lines}",
117140
]
118141

119142

tests/unit/test_sections.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,34 @@ def test_parse_invalid_name():
103103
assert sections.description[2] == "%description(fr)"
104104

105105

106+
def test_parse_macro_definitions():
107+
sections = Sections.parse(
108+
[
109+
"%package -n test",
110+
"Summary: Subpackage test",
111+
"",
112+
"%description -n test",
113+
"Subpackage test.",
114+
"",
115+
"%define template1()\\",
116+
"%package -n %{1}\\",
117+
"Summary: Subpackage %{1}\\",
118+
"\\",
119+
"%description -n %{1}\\",
120+
"Subpackage %{1}.",
121+
"",
122+
"%define template2() %{expand:",
123+
"%package -n %{1}",
124+
"Summary: Subpackage %{1}",
125+
"",
126+
"%description -n %{1}",
127+
"Subpackage %{1}.}",
128+
]
129+
)
130+
assert len(sections) == 3
131+
assert sections[1].id == "package -n test"
132+
133+
106134
def test_get_raw_data():
107135
sections = Sections(
108136
[

0 commit comments

Comments
 (0)