Skip to content

Commit

Permalink
Implement Sections.get_or_create() (#441)
Browse files Browse the repository at this point in the history
Implement `Sections.get_or_create()`

Fixes #404.
RELEASE NOTES BEGIN
There is a new convenience method Sections.get_or_create() that allows you to manipulate a section without checking if it exists first. If a section doesn't exist, it will be appended to the end. For example, this will work properly even on spec files without %changelog:
with spec.sections() as sections:
    changelog = sections.get_or_create("changelog")
    changelog[:] = ["%autochangelog"]

RELEASE NOTES END

Reviewed-by: František Lachman <[email protected]>
  • Loading branch information
softwarefactory-project-zuul[bot] authored Dec 13, 2024
2 parents ecdb644 + b504643 commit b5b95e9
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 0 deletions.
32 changes: 32 additions & 0 deletions specfile/sections.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,38 @@ def find(self, id: str) -> int:
return i
raise ValueError

def get_or_create(self, id: str) -> Section:
"""
Gets an existing section by ID or creates a new section with the given ID.
New section will be appended to the end.
Args:
id: ID of the section (name and options, without the leading '%').
Returns:
Existing or newly created section as an instance of `Section` class.
"""

def split_id(id):
separator = "\n"
tokens = re.split(r"(\s+)", id)
if len(tokens) > 2:
name = tokens[0]
delimiter = tokens[1]
options = Options(
Options.tokenize("".join(tokens[2:])),
SECTION_OPTIONS.get(name.lower()),
)
return name, options, delimiter, separator
return tokens[0], None, "", separator

try:
section = self.get(id)
except (ValueError, KeyError):
section = Section(*split_id(id))
self.data.append(section)
return section

@classmethod
def parse(
cls, lines: List[str], context: Optional["Specfile"] = None
Expand Down
41 changes: 41 additions & 0 deletions tests/unit/test_sections.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,47 @@ def test_get():
sections.get("package foo")


@pytest.mark.parametrize(
"id, existing, name, options, content",
[
(
"package",
True,
"package",
"",
["Name: test", "Version: 0.1", "Release: 1%{?dist}", ""],
),
("prep", True, "prep", "", ["%autosetup", ""]),
("package -n subpkg1", True, "package", "-n subpkg1", [""]),
("package -n subpkg2", False, "package", "-n subpkg2", []),
],
)
def test_get_or_create(id, existing, name, options, content):
sections = Sections.parse(
[
"Name: test",
"Version: 0.1",
"Release: 1%{?dist}",
"",
"%description",
"Test package",
"",
"%prep",
"%autosetup",
"",
"%package -n subpkg1",
"",
"%changelog",
]
)
section = sections.get_or_create(id)
assert section.name == name
assert str(section.options) == options
assert list(section) == content
if not existing:
assert section == sections[-1]


def test_parse():
sections = Sections.parse(
[
Expand Down

0 comments on commit b5b95e9

Please sign in to comment.