feat: add counters to repository stats overview

This commit is contained in:
2025-01-09 15:51:10 +02:00
parent a07b20bf50
commit 15ca143b70
26 changed files with 519 additions and 28 deletions

View File

@ -11,6 +11,7 @@ from ahriman.core.repository import Repository
from ahriman.core.utils import pretty_datetime, utcnow
from ahriman.models.event import Event, EventType
from ahriman.models.package import Package
from ahriman.models.repository_stats import RepositoryStats
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
@ -40,13 +41,16 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
"""
args = _default_args(args)
events = [Event("1", "1"), Event("2", "2")]
stats = RepositoryStats(bases=1, packages=2, archive_size=3, installed_size=4)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
events_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.event_get", return_value=events)
stats_mock = mocker.patch("ahriman.core.status.client.Client.statistics", return_value=stats)
application_mock = mocker.patch("ahriman.application.handlers.statistics.Statistics.stats_per_package")
_, repository_id = configuration.check_loaded()
Statistics.run(args, repository_id, configuration, report=False)
events_mock.assert_called_once_with(args.event, args.package, None, None, args.limit, args.offset)
stats_mock.assert_called_once_with()
application_mock.assert_called_once_with(args.event, events, args.chart)

View File

@ -12,6 +12,7 @@ from ahriman.core.formatters import \
PackageStatsPrinter, \
PatchPrinter, \
RepositoryPrinter, \
RepositoryStatsPrinter, \
StatusPrinter, \
StringPrinter, \
TreePrinter, \
@ -25,6 +26,7 @@ from ahriman.models.changes import Changes
from ahriman.models.package import Package
from ahriman.models.pkgbuild_patch import PkgbuildPatch
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_stats import RepositoryStats
from ahriman.models.user import User
@ -134,12 +136,29 @@ def repository_printer(repository_id: RepositoryId) -> RepositoryPrinter:
"""
fixture for repository printer
Args:
repository_id(RepositoryId): repository identifier fixture
Returns:
RepositoryPrinter: repository printer test instance
"""
return RepositoryPrinter(repository_id)
@pytest.fixture
def repository_stats_printer(repository_id: RepositoryId) -> RepositoryStatsPrinter:
"""
fixture for repository stats printer
Args:
repository_id(RepositoryId): repository identifier fixture
Returns:
RepositoryStatsPrinter: repository stats printer test instance
"""
return RepositoryStatsPrinter(repository_id, RepositoryStats(bases=1, packages=2, archive_size=3, installed_size=4))
@pytest.fixture
def status_printer() -> StatusPrinter:
"""

View File

@ -15,13 +15,6 @@ def test_properties_empty() -> None:
assert EventStatsPrinter("event", []).properties()
def test_properties_single() -> None:
"""
must skip calculation of the standard deviation for single event
"""
assert EventStatsPrinter("event", [1]).properties()
def test_title(event_stats_printer: EventStatsPrinter) -> None:
"""
must return non-empty title

View File

@ -0,0 +1,15 @@
from ahriman.core.formatters import RepositoryStatsPrinter
def test_properties(repository_stats_printer: RepositoryStatsPrinter) -> None:
"""
must return non-empty properties list
"""
assert repository_stats_printer.properties()
def test_title(repository_stats_printer: RepositoryStatsPrinter) -> None:
"""
must return non-empty title
"""
assert repository_stats_printer.title()

View File

@ -16,6 +16,7 @@ from ahriman.models.internal_status import InternalStatus
from ahriman.models.log_record_id import LogRecordId
from ahriman.models.package import Package
from ahriman.models.pkgbuild_patch import PkgbuildPatch
from ahriman.models.repository_stats import RepositoryStats
def test_load_dummy_client(configuration: Configuration) -> None:
@ -285,6 +286,14 @@ def test_set_unknown_skip(client: Client, package_ahriman: Package, mocker: Mock
update_mock.assert_not_called()
def test_statistics(client: Client, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must correctly fetch statistics
"""
mocker.patch("ahriman.core.status.Client.package_get", return_value=[(package_ahriman, None)])
assert client.statistics() == RepositoryStats(bases=1, packages=1, archive_size=4200, installed_size=4200000)
def test_status_get(client: Client) -> None:
"""
must return dummy status for web service

View File

@ -14,6 +14,7 @@ from ahriman.models.package_description import PackageDescription
from ahriman.models.package_source import PackageSource
from ahriman.models.pkgbuild import Pkgbuild
from ahriman.models.remote_source import RemoteSource
from ahriman.models.repository_stats import RepositoryStats
@pytest.fixture
@ -71,8 +72,9 @@ def internal_status(counters: Counters) -> InternalStatus:
status=BuildStatus(),
architecture="x86_64",
packages=counters,
version=__version__,
repository="aur",
stats=RepositoryStats(bases=1, packages=2, archive_size=3, installed_size=4),
version=__version__,
)

View File

@ -68,3 +68,10 @@ def test_lt_invalid() -> None:
"""
with pytest.raises(ValueError):
assert RepositoryId("x86_64", "a") < 42
def test_str() -> None:
"""
must convert identifier to string
"""
assert str(RepositoryId("x86_64", "a")) == "a (x86_64)"

View File

@ -0,0 +1,24 @@
from dataclasses import asdict
from ahriman.models.package import Package
from ahriman.models.repository_stats import RepositoryStats
def test_repository_stats_from_json_view(package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must construct same object from json
"""
stats = RepositoryStats.from_packages([package_ahriman, package_python_schedule])
assert RepositoryStats.from_json(asdict(stats)) == stats
def test_from_packages(package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must generate stats from packages list
"""
assert RepositoryStats.from_packages([package_ahriman, package_python_schedule]) == RepositoryStats(
bases=2,
packages=3,
archive_size=12603,
installed_size=12600003,
)

View File

@ -0,0 +1,80 @@
from ahriman.models.series_statistics import SeriesStatistics
def test_max() -> None:
"""
must return maximal value
"""
assert SeriesStatistics([1, 3, 2]).max == 3
def test_max_empty() -> None:
"""
must return None as maximal value if series is empty
"""
assert SeriesStatistics([]).max is None
def test_mean() -> None:
"""
must return mean value
"""
assert SeriesStatistics([1, 3, 2]).mean == 2
def test_mean_empty() -> None:
"""
must return None as mean value if series is empty
"""
assert SeriesStatistics([]).mean is None
def test_min() -> None:
"""
must return minimal value
"""
assert SeriesStatistics([1, 3, 2]).min == 1
def test_min_empty() -> None:
"""
must return None as minimal value if series is empty
"""
assert SeriesStatistics([]).min is None
def test_st_dev() -> None:
"""
must return standard deviation
"""
assert SeriesStatistics([1, 3, 2]).st_dev == 1
def test_st_dev_empty() -> None:
"""
must return None as standard deviation if series is empty
"""
assert SeriesStatistics([]).st_dev is None
def test_st_dev_single() -> None:
"""
must return 0 as standard deviation if series contains only one element
"""
assert SeriesStatistics([1]).st_dev == 0
def test_total() -> None:
"""
must return size of collection
"""
assert SeriesStatistics([1]).total == 1
assert SeriesStatistics([]).total == 0
def test_bool() -> None:
"""
must correctly define empty collection
"""
assert SeriesStatistics([1])
assert not SeriesStatistics([])

View File

@ -0,0 +1 @@
# schema testing goes in view class tests