diff --git a/plans/functional.fmf b/plans/functional.fmf new file mode 100644 index 00000000..6b622520 --- /dev/null +++ b/plans/functional.fmf @@ -0,0 +1,11 @@ +summary: + Functional tests +discover+: + filter: tier:2 +prepare: + - how: install + package: xz + - how: shell + script: | + curl -O https://src.fedoraproject.org/lookaside/rpm-specs-latest.tar.xz + tar -xf rpm-specs-latest.tar.xz -C /tmp diff --git a/specfile/sections.py b/specfile/sections.py index b98284fd..f467c6d9 100644 --- a/specfile/sections.py +++ b/specfile/sections.py @@ -12,6 +12,7 @@ SECTION_OPTIONS, SIMPLE_SCRIPT_SECTIONS, ) +from specfile.exceptions import RPMException from specfile.formatter import formatted from specfile.macro_definitions import MacroDefinitions from specfile.macros import Macros @@ -241,9 +242,14 @@ def split_id(line): if len(tokens) > 2: # if the last token after macro expansion starts with a newline, # consider it part of section content - if expand(tokens[-1]).startswith("\n"): - content = [tokens.pop()] - separator = tokens.pop() + try: + expanded = expand(tokens[-1]) + except RPMException: + pass + else: + if expanded.startswith("\n"): + content = [tokens.pop()] + separator = tokens.pop() if len(tokens) > 2: name = tokens[0] delimiter = tokens[1] diff --git a/specfile/specfile.py b/specfile/specfile.py index b4a8bb98..400b4bb7 100644 --- a/specfile/specfile.py +++ b/specfile/specfile.py @@ -64,7 +64,7 @@ def __init__( """ self.autosave = autosave self._path = Path(path) - self._lines = self.path.read_text().splitlines() + self._lines = self._read_lines(self._path) self._parser = SpecParser( Path(sourcedir or self.path.parent), macros, force_parse ) @@ -101,6 +101,10 @@ def __exit__( ) -> None: self.save() + @staticmethod + def _read_lines(path: Path) -> List[str]: + return path.read_text(encoding="utf8", errors="surrogateescape").splitlines() + @property def path(self) -> Path: """Path to the spec file.""" @@ -154,11 +158,11 @@ def rpm_spec(self) -> rpm.spec: def reload(self) -> None: """Reload the spec file content.""" - self._lines = self.path.read_text().splitlines() + self._lines = self._read_lines(self.path) def save(self) -> None: """Save the spec file content.""" - self.path.write_text(str(self)) + self.path.write_text(str(self), encoding="utf8", errors="surrogateescape") def expand( self, diff --git a/tests/functional.fmf b/tests/functional.fmf new file mode 100644 index 00000000..18036396 --- /dev/null +++ b/tests/functional.fmf @@ -0,0 +1,15 @@ +summary: + Functional tests +require: + - python3-pytest + - python3-specfile + - redhat-rpm-config + - rpmautospec-rpm-macros + - "*-srpm-macros" +tag: + - functional +tier: 2 +duration: 1h +# running from the "tests" directory prevents pytest from processing "tests/functional/conftest.py" +path: / +test: python3 -m pytest --verbose --specdir=/tmp/rpm-specs tests/functional diff --git a/tests/functional/__init__.py b/tests/functional/__init__.py new file mode 100644 index 00000000..e01ff12d --- /dev/null +++ b/tests/functional/__init__.py @@ -0,0 +1,2 @@ +# Copyright Contributors to the Packit project. +# SPDX-License-Identifier: MIT diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py new file mode 100644 index 00000000..93475816 --- /dev/null +++ b/tests/functional/conftest.py @@ -0,0 +1,20 @@ +# Copyright Contributors to the Packit project. +# SPDX-License-Identifier: MIT + +from pathlib import Path + + +def pytest_addoption(parser): + parser.addoption( + "--specdir", + action="store", + default=None, + help="path to a directory containing spec files", + ) + + +def pytest_generate_tests(metafunc): + if "spec_path" in metafunc.fixturenames: + specdir = metafunc.config.getoption("specdir") + specs = list(Path(specdir).glob("*.spec")) if specdir else [] + metafunc.parametrize("spec_path", specs, ids=lambda p: p.name) diff --git a/tests/functional/test_parse.py b/tests/functional/test_parse.py new file mode 100644 index 00000000..a26ecf6e --- /dev/null +++ b/tests/functional/test_parse.py @@ -0,0 +1,9 @@ +# Copyright Contributors to the Packit project. +# SPDX-License-Identifier: MIT + +from specfile import Specfile + + +def test_parse(spec_path): + spec = Specfile(spec_path, force_parse=True) + assert spec.expanded_version