event bus implementation

This commit is contained in:
2026-03-24 02:23:14 +02:00
parent 1c312bb528
commit d2aed850b6
23 changed files with 459 additions and 147 deletions

View File

@@ -19,6 +19,7 @@ from ahriman.core.repository import Repository
from ahriman.core.repository.package_info import PackageInfo
from ahriman.core.spawn import Spawn
from ahriman.core.status import Client
from ahriman.core.status.event_bus import EventBus
from ahriman.core.status.watcher import Watcher
from ahriman.models.aur_package import AURPackage
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
@@ -690,4 +691,5 @@ def watcher(local_client: Client) -> Watcher:
Watcher: package status watcher test instance
"""
package_info = PackageInfo()
return Watcher(local_client, package_info)
event_bus = EventBus(0)
return Watcher(local_client, package_info, event_bus)

View File

@@ -18,21 +18,21 @@ def test_packages(watcher: Watcher, package_ahriman: Package) -> None:
assert watcher.packages
def test_load(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
async def test_load(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must correctly load packages
"""
cache_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_get",
return_value=[(package_ahriman, BuildStatus())])
watcher.load()
await watcher.load()
cache_mock.assert_called_once_with(None)
package, status = watcher._known[package_ahriman.base]
assert package == package_ahriman
assert status.status == BuildStatusEnum.Unknown
def test_load_known(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
async def test_load_known(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must correctly load packages with known statuses
"""
@@ -40,146 +40,147 @@ def test_load_known(watcher: Watcher, package_ahriman: Package, mocker: MockerFi
mocker.patch("ahriman.core.status.local_client.LocalClient.package_get", return_value=[(package_ahriman, status)])
watcher._known = {package_ahriman.base: (package_ahriman, status)}
watcher.load()
await watcher.load()
_, status = watcher._known[package_ahriman.base]
assert status.status == BuildStatusEnum.Success
def test_package_archives(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
async def test_package_archives(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must return package archives from package info
"""
archives_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.package_archives",
return_value=[package_ahriman])
result = watcher.package_archives(package_ahriman.base)
result = await watcher.package_archives(package_ahriman.base)
assert result == [package_ahriman]
archives_mock.assert_called_once_with(package_ahriman.base)
def test_package_get(watcher: Watcher, package_ahriman: Package) -> None:
async def test_package_get(watcher: Watcher, package_ahriman: Package) -> None:
"""
must return package status
"""
watcher._known = {package_ahriman.base: (package_ahriman, BuildStatus())}
package, status = watcher.package_get(package_ahriman.base)
package, status = await watcher.package_get(package_ahriman.base)
assert package == package_ahriman
assert status.status == BuildStatusEnum.Unknown
def test_package_get_failed(watcher: Watcher, package_ahriman: Package) -> None:
async def test_package_get_failed(watcher: Watcher, package_ahriman: Package) -> None:
"""
must fail on unknown package
"""
with pytest.raises(UnknownPackageError):
watcher.package_get(package_ahriman.base)
await watcher.package_get(package_ahriman.base)
def test_package_hold_update(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
async def test_package_hold_update(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must update package hold status
"""
cache_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_hold_update")
watcher._known = {package_ahriman.base: (package_ahriman, BuildStatus())}
watcher.package_hold_update(package_ahriman.base, enabled=True)
await watcher.package_hold_update(package_ahriman.base, enabled=True)
cache_mock.assert_called_once_with(package_ahriman.base, enabled=True)
_, status = watcher._known[package_ahriman.base]
assert status.is_held is True
def test_package_hold_update_unknown(watcher: Watcher, package_ahriman: Package) -> None:
async def test_package_hold_update_unknown(watcher: Watcher, package_ahriman: Package) -> None:
"""
must fail on unknown package hold update
"""
with pytest.raises(UnknownPackageError):
watcher.package_hold_update(package_ahriman.base, enabled=True)
await watcher.package_hold_update(package_ahriman.base, enabled=True)
def test_package_remove(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
async def test_package_remove(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must remove package base
"""
cache_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_remove")
watcher._known = {package_ahriman.base: (package_ahriman, BuildStatus())}
watcher.package_remove(package_ahriman.base)
await watcher.package_remove(package_ahriman.base)
assert not watcher._known
cache_mock.assert_called_once_with(package_ahriman.base)
def test_package_remove_unknown(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
async def test_package_remove_unknown(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must not fail on unknown base removal
"""
cache_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_remove")
watcher.package_remove(package_ahriman.base)
await watcher.package_remove(package_ahriman.base)
cache_mock.assert_called_once_with(package_ahriman.base)
def test_package_status_update(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
async def test_package_status_update(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must update package status only for known package
"""
cache_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_status_update")
watcher._known = {package_ahriman.base: (package_ahriman, BuildStatus())}
watcher.package_status_update(package_ahriman.base, BuildStatusEnum.Success)
await watcher.package_status_update(package_ahriman.base, BuildStatusEnum.Success)
cache_mock.assert_called_once_with(package_ahriman.base, pytest.helpers.anyvar(int))
package, status = watcher._known[package_ahriman.base]
assert package == package_ahriman
assert status.status == BuildStatusEnum.Success
def test_package_status_update_preserves_hold(watcher: Watcher, package_ahriman: Package,
mocker: MockerFixture) -> None:
async def test_package_status_update_preserves_hold(watcher: Watcher, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must preserve hold status on package status update
"""
mocker.patch("ahriman.core.status.local_client.LocalClient.package_status_update")
watcher._known = {package_ahriman.base: (package_ahriman, BuildStatus(is_held=True))}
watcher.package_status_update(package_ahriman.base, BuildStatusEnum.Success)
await watcher.package_status_update(package_ahriman.base, BuildStatusEnum.Success)
_, status = watcher._known[package_ahriman.base]
assert status.is_held is True
def test_package_status_update_unknown(watcher: Watcher, package_ahriman: Package) -> None:
async def test_package_status_update_unknown(watcher: Watcher, package_ahriman: Package) -> None:
"""
must fail on unknown package status update only
"""
with pytest.raises(UnknownPackageError):
watcher.package_status_update(package_ahriman.base, BuildStatusEnum.Unknown)
await watcher.package_status_update(package_ahriman.base, BuildStatusEnum.Unknown)
def test_package_update(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
async def test_package_update(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must add package to cache
"""
cache_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_update")
watcher.package_update(package_ahriman, BuildStatusEnum.Unknown)
await watcher.package_update(package_ahriman, BuildStatusEnum.Unknown)
assert watcher.packages
cache_mock.assert_called_once_with(package_ahriman, pytest.helpers.anyvar(int))
def test_package_update_preserves_hold(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
async def test_package_update_preserves_hold(watcher: Watcher, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must preserve hold status on package update
"""
mocker.patch("ahriman.core.status.local_client.LocalClient.package_update")
watcher._known = {package_ahriman.base: (package_ahriman, BuildStatus(is_held=True))}
watcher.package_update(package_ahriman, BuildStatusEnum.Success)
await watcher.package_update(package_ahriman, BuildStatusEnum.Success)
_, status = watcher._known[package_ahriman.base]
assert status.is_held is True
def test_status_update(watcher: Watcher) -> None:
async def test_status_update(watcher: Watcher) -> None:
"""
must update service status
"""
watcher.status_update(BuildStatusEnum.Success)
await watcher.status_update(BuildStatusEnum.Success)
assert watcher.status.status == BuildStatusEnum.Success
@@ -204,18 +205,3 @@ def test_call_failed(watcher: Watcher, package_ahriman: Package) -> None:
"""
with pytest.raises(UnknownPackageError):
assert watcher(package_ahriman.base)
def test_getattr(watcher: Watcher) -> None:
"""
must return client method call
"""
assert watcher.package_logs_remove
def test_getattr_unknown_method(watcher: Watcher) -> None:
"""
must raise AttributeError in case if no reporter attribute found
"""
with pytest.raises(AttributeError):
assert watcher.random_method