Skip to content

Commit

Permalink
Implement high-level manipulation of sources/patches
Browse files Browse the repository at this point in the history
Signed-off-by: Nikola Forró <nforro@redhat.com>
  • Loading branch information
nforro committed Mar 5, 2022
1 parent 8c55a0b commit 3b28aff
Show file tree
Hide file tree
Showing 4 changed files with 596 additions and 5 deletions.
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,20 @@ specfile.add_changelog_entry(
#### Sources and patches

```python
print(specfile.sources)
print(specfile.patches)
print(specfile.sources[0].filename)
specfile.sources.append('tests.tar.gz')
specfile.patches[0] = 'downstream.patch'
with specfile.sources() as sources:
# expanded URL of the first source
print(sources[0].expanded_url)
# adding a source
sources.append('tests.tar.gz')

with specfile.patches() as patches:
# modifying URL of the first patch
patches[0].url = 'downstream.patch'
# removing comments associated with the last patch
patches[-1].comments.clear()
# adding and removing patches
patches.append('another.patch')
del patches[2]

# fetching non-local sources (including patches)
specfile.download_remote_sources()
Expand Down
116 changes: 116 additions & 0 deletions specfile/sourcelist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Copyright Contributors to the Packit project.
# SPDX-License-Identifier: MIT

import collections
from typing import List, Optional, overload

from specfile.rpm import Macros
from specfile.sections import Section
from specfile.tags import Comments


class Source:
"""
Class that represents a spec file source/patch.
Attributes:
url: Literal URL of the source/patch as stored in the spec file.
comments: List of comments associated with the source/patch.
"""

def __init__(self, url: str, comments: Comments) -> None:
self.url = url
self.comments = comments.copy()

def __repr__(self) -> str:
comments = repr(self.comments)
return f"Source('{self.url}', {comments})"

@property
def expanded_url(self) -> str:
"""URL of the source/patch after expanding macros."""
return Macros.expand(self.url)


class SourceList(collections.UserList):
"""
Class that represents entries in a %sourcelist/%patchlist section.
Attributes:
data: List of individual sources/patches.
"""

def __init__(
self, data: Optional[List[Source]] = None, remainder: Optional[List[str]] = None
) -> None:
"""
Constructs a `SourceList` object.
Args:
data: List of individual sources/patches.
remainder: Leftover lines in a section that can't be parsed into sources/patches.
Returns:
Constructed instance of `SourceList` class.
"""
super().__init__()
if data is not None:
self.data = data.copy()
self._remainder = remainder.copy() if remainder is not None else []

def __repr__(self) -> str:
data = repr(self.data)
remainder = repr(self._remainder)
return f"SourceList({data}, {remainder})"

@overload
def __getitem__(self, i: int) -> Source:
pass

@overload
def __getitem__(self, i: slice) -> "SourceList":
pass

def __getitem__(self, i):
if isinstance(i, slice):
return SourceList(self.data[i], self._remainder)
else:
return self.data[i]

def copy(self) -> "SourceList":
return SourceList(self.data, self._remainder)

@staticmethod
def parse(section: Section) -> "SourceList":
"""
Parses a section into sources/patches.
Args:
section: %sourcelist/%patchlist section.
Returns:
Constructed instance of `SourceList` class.
"""
data = []
buffer: List[str] = []
for line in section:
if line and not line.lstrip().startswith("#"):
data.append(Source(line, Comments.parse(buffer)))
buffer = []
else:
buffer.append(line)
return SourceList(data, buffer)

def get_raw_section_data(self) -> List[str]:
"""
Reconstructs section data from sources/patches.
Returns:
List of lines forming the reconstructed section data.
"""
result = []
for source in self.data:
result.extend(source.comments.get_raw_data())
result.append(source.url)
result.extend(self._remainder)
return result
Loading

0 comments on commit 3b28aff

Please sign in to comment.