Skip to content

Commit

Permalink
Set validity of macro definitions based on conditions
Browse files Browse the repository at this point in the history
Signed-off-by: Nikola Forró <[email protected]>
  • Loading branch information
nforro committed Aug 21, 2023
1 parent 6c8f4ef commit 35a235c
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 7 deletions.
56 changes: 50 additions & 6 deletions specfile/macro_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
import collections
import copy
import re
from typing import List, Optional, Tuple, Union, overload
from typing import TYPE_CHECKING, List, Optional, Tuple, Union, overload

from specfile.conditions import process_conditions
from specfile.formatter import formatted
from specfile.types import SupportsIndex

if TYPE_CHECKING:
from specfile.specfile import Specfile


class MacroDefinition:
def __init__(
Expand All @@ -17,12 +21,14 @@ def __init__(
body: str,
is_global: bool,
whitespace: Tuple[str, str, str, str],
valid: bool = True,
preceding_lines: Optional[List[str]] = None,
) -> None:
self.name = name
self.body = body
self.is_global = is_global
self._whitespace = whitespace
self.valid = valid
self._preceding_lines = (
preceding_lines.copy() if preceding_lines is not None else []
)
Expand All @@ -42,7 +48,7 @@ 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._preceding_lines!r})"
f"{self._whitespace!r}, {self.valid!r}, {self._preceding_lines!r})"
)

def __str__(self) -> str:
Expand Down Expand Up @@ -189,7 +195,9 @@ def find(self, name: str) -> int:
raise ValueError

@classmethod
def parse(cls, lines: List[str]) -> "MacroDefinitions":
def _parse(
cls, lines: Union[List[str], List[Tuple[str, bool]]]
) -> "MacroDefinitions":
"""
Parses given lines into macro defintions.
Expand All @@ -200,6 +208,13 @@ def parse(cls, lines: List[str]) -> "MacroDefinitions":
Constructed instance of `MacroDefinitions` class.
"""

def pop(lines):
line = lines.pop(0)
if isinstance(line, str):
return line, True
else:
return line

def count_brackets(s):
bc = pc = 0
chars = list(s)
Expand Down Expand Up @@ -248,7 +263,7 @@ def count_brackets(s):
buffer: List[str] = []
lines = lines.copy()
while lines:
line = lines.pop(0)
line, valid = pop(lines)
m = md_regex.match(line)
if m:
ws0, macro, ws1, name, ws2, body, ws3 = m.groups()
Expand All @@ -257,7 +272,7 @@ def count_brackets(s):
ws3 = ""
bc, pc = count_brackets(body)
while (bc > 0 or pc > 0 or body.endswith("\\")) and lines:
line = lines.pop(0)
line, _ = pop(lines)
body += "\n" + line
bc, pc = count_brackets(body)
tokens = re.split(r"(\s+)$", body, maxsplit=1)
Expand All @@ -268,14 +283,43 @@ def count_brackets(s):
ws3 = ws + ws3
data.append(
MacroDefinition(
name, body, macro == "%global", (ws0, ws1, ws2, ws3), buffer
name,
body,
macro == "%global",
(ws0, ws1, ws2, ws3),
valid,
buffer,
)
)
buffer = []
else:
buffer.append(line)
return cls(data, buffer)

@classmethod
def parse(
cls,
lines: List[str],
with_conditions: bool = False,
context: Optional["Specfile"] = None,
) -> "MacroDefinitions":
"""
Parses given lines into macro defintions.
Args:
lines: Lines to parse.
with_conditions: Whether to process conditions before parsing and populate
the `valid` attribute.
context: `Specfile` instance that defines the context for macro expansions.
Returns:
Constructed instance of `MacroDefinitions` class.
"""
result = cls._parse(lines)
if not with_conditions:
return result
return cls._parse(process_conditions(lines, result, context))

def get_raw_data(self) -> List[str]:
result = []
for macro_definition in self.data:
Expand Down
4 changes: 3 additions & 1 deletion specfile/specfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@ def macro_definitions(self) -> Generator[MacroDefinitions, None, None]:
Macro definitions in the spec file as `MacroDefinitions` object.
"""
with self.lines() as lines:
macro_definitions = MacroDefinitions.parse(lines)
macro_definitions = MacroDefinitions.parse(
lines, with_conditions=True, context=self
)
try:
yield macro_definitions
finally:
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/test_macro_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def test_get_raw_data():
"Test spec file containing several \\\nmacro definitions in various formats (%?1)",
False,
("", " ", " ", ""),
True,
[
"",
"Name: test",
Expand All @@ -119,6 +120,7 @@ def test_get_raw_data():
"spawning across mutiple lines}",
False,
("", " ", " ", ""),
True,
[""],
),
]
Expand Down

0 comments on commit 35a235c

Please sign in to comment.