Skip to content

Commit d6b746d

Browse files
Fixes and optimization (#240)
Fixes and optimization Reviewed-by: Jiri Popelka
2 parents 28cb117 + 02c888e commit d6b746d

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

specfile/sections.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
SECTION_OPTIONS,
1313
SIMPLE_SCRIPT_SECTIONS,
1414
)
15+
from specfile.exceptions import RPMException
1516
from specfile.formatter import formatted
1617
from specfile.macro_definitions import MacroDefinitions
1718
from specfile.macros import Macros
@@ -231,19 +232,29 @@ def parse(
231232

232233
def expand(s):
233234
if context:
234-
return context.expand(s)
235+
result = context.expand(
236+
s, skip_parsing=getattr(expand, "skip_parsing", False)
237+
)
238+
# parse only once
239+
expand.skip_parsing = True
240+
return result
235241
return Macros.expand(s)
236242

237243
def split_id(line):
238244
content = []
239245
separator = "\n"
240246
tokens = re.split(r"(\s+)", line)
241-
if len(tokens) > 2:
247+
if len(tokens) > 2 and tokens[-1].startswith("%"):
242248
# if the last token after macro expansion starts with a newline,
243249
# consider it part of section content
244-
if expand(tokens[-1]).startswith("\n"):
245-
content = [tokens.pop()]
246-
separator = tokens.pop()
250+
try:
251+
expanded = expand(tokens[-1])
252+
except RPMException:
253+
pass
254+
else:
255+
if expanded.startswith("\n"):
256+
content = [tokens.pop()]
257+
separator = tokens.pop()
247258
if len(tokens) > 2:
248259
name = tokens[0]
249260
delimiter = tokens[1]

specfile/specfile.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def __init__(
6464
"""
6565
self.autosave = autosave
6666
self._path = Path(path)
67-
self._lines = self.path.read_text().splitlines()
67+
self._lines = self._read_lines(self._path)
6868
self._parser = SpecParser(
6969
Path(sourcedir or self.path.parent), macros, force_parse
7070
)
@@ -101,6 +101,10 @@ def __exit__(
101101
) -> None:
102102
self.save()
103103

104+
@staticmethod
105+
def _read_lines(path: Path) -> List[str]:
106+
return path.read_text(encoding="utf8", errors="surrogateescape").splitlines()
107+
104108
@property
105109
def path(self) -> Path:
106110
"""Path to the spec file."""
@@ -154,28 +158,33 @@ def rpm_spec(self) -> rpm.spec:
154158

155159
def reload(self) -> None:
156160
"""Reload the spec file content."""
157-
self._lines = self.path.read_text().splitlines()
161+
self._lines = self._read_lines(self.path)
158162

159163
def save(self) -> None:
160164
"""Save the spec file content."""
161-
self.path.write_text(str(self))
165+
self.path.write_text(str(self), encoding="utf8", errors="surrogateescape")
162166

163167
def expand(
164168
self,
165169
expression: str,
166170
extra_macros: Optional[List[Tuple[str, str]]] = None,
171+
skip_parsing: bool = False,
167172
) -> str:
168173
"""
169174
Expands an expression in the context of the spec file.
170175
171176
Args:
172177
expression: Expression to expand.
173178
extra_macros: Extra macros to be defined before expansion is performed.
179+
skip_parsing: Do not parse the spec file before expansion is performed.
180+
Defaults to False. Mutually exclusive with extra_macros. Set this to True
181+
only if you are certain that the global macro context is up-to-date.
174182
175183
Returns:
176184
Expanded expression.
177185
"""
178-
self._parser.parse(str(self), extra_macros)
186+
if not skip_parsing or extra_macros is not None:
187+
self._parser.parse(str(self), extra_macros)
179188
return Macros.expand(expression)
180189

181190
def get_active_macros(self) -> List[Macro]:

specfile/value_parser.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,12 @@ def construct_regex(
312312

313313
def expand(s):
314314
if context:
315-
return context.expand(s)
315+
result = context.expand(
316+
s, skip_parsing=getattr(expand, "skip_parsing", False)
317+
)
318+
# parse only once
319+
expand.skip_parsing = True
320+
return result
316321
return Macros.expand(s)
317322

318323
def flatten(nodes):

0 commit comments

Comments
 (0)