Change repository member iterator to yield model

Add the private method `_extract_db_member_package_name()` which can be
used to extract the package name from the name of a member of repository
Rename `_read_db_file_member()` to `_db_file_member_as_model()` and
change the method to yield a `models.RepoDbMemberData` instead of a
`tarfile.TarInfo` to provide actual data (and required context) to
callers of the method.

Add parametrized test for `_extract_db_member_package_name()`.
Change test for `_db_file_member_as_model()` to assert the correct
return type.
parent 45e96813
import io
import re
import tarfile
from pathlib import Path
from typing import Iterator
from repo_management import defaults, models
def _read_db_file(db_path: Path, compression: str = "gz") -> tarfile.TarFile:
"""Read a repository database file
......@@ -32,9 +35,30 @@ def _read_db_file(db_path: Path, compression: str = "gz") -> tarfile.TarFile:
return, mode=f"r:{compression}")
def _read_db_file_member(db_file: tarfile.TarFile, regex: str = "(/desc|/files)$") -> Iterator[tarfile.TarInfo]:
"""Read the members of a database file, represented by an instance of tarfile.TarFile and yield the members as
instances of tarfile.TarInfo
def _extract_db_member_package_name(name: str) -> str:
"""Extract and return the package name from a repository database member name
name: str
The name of a member of a repository database (i.e. one of tarfile.Tarfile.getnames())
The package name extracted from name
return "".join(re.split("(-)", re.sub("(/desc|/files)$", "", name))[:-4])
def _db_file_member_as_model(
db_file: tarfile.TarFile, regex: str = "(/desc|/files)$"
) -> Iterator[models.RepoDbMemberData]:
"""Iterate over the members of a database file, represented by an instance of tarfile.TarFile and yield the members
as instances of models.RepoDbMemberData
The method filters the list of evaluated members using a regular expression. Depending on member name one of
defaults.RepoDbMemberType is chosen.
......@@ -46,4 +70,20 @@ def _read_db_file_member(db_file: tarfile.TarFile, regex: str = "(/desc|/files)$
for name in [name for name in db_file.getnames() if, name)]:
yield db_file.getmember(name)
file_type = defaults.RepoDbMemberType.UNKNOWN
if"(/desc)$", name):
file_type = defaults.RepoDbMemberType.DESC
if"(/files)$", name):
file_type = defaults.RepoDbMemberType.FILES
yield models.RepoDbMemberData(
db_file.extractfile(name).read(), # type: ignore
......@@ -6,9 +6,9 @@ from contextlib import nullcontext as does_not_raise
from pathlib import Path
from typing import Iterator, List
from pytest import fixture, raises
from pytest import fixture, mark, raises
from repo_management import files
from repo_management import files, models
def create_db_file(compression: str = "gz", remove_db: bool = False) -> Path:
......@@ -77,6 +77,24 @@ def test__read_db_file_wrong_db_compression(create_bzip_db_file: Path) -> None:
assert files._read_db_file(create_bzip_db_file)
def test__read_db_file_member(create_gz_db_file: Path) -> None:
for member in files._read_db_file_member(db_file=files._read_db_file(create_gz_db_file)):
assert member
def test__read_db_file_member_as_model(create_gz_db_file: Path) -> None:
for member in files._db_file_member_as_model(db_file=files._read_db_file(create_gz_db_file)):
assert isinstance(member, models.RepoDbMemberData)
"member_name, result",
("foo-bar-1.0.0-42", "foo-bar"),
("foobar-1.0.0-42", "foobar"),
("foo-bar-1.0.0-42/desc", "foo-bar"),
("foo-bar-1.0.0-42/files", "foo-bar"),
("foobar-1.0.0-42/desc", "foobar"),
("foobar-1.0.0-42/files", "foobar"),
def test__extract_db_member_package_name(
member_name: str,
result: str,
) -> None:
assert files._extract_db_member_package_name(name=member_name) == result
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment