mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 07:17:17 +00:00
feat: allow to run daemon mode with split packages check (#120)
This commit is contained in:
parent
f6cdd806b2
commit
b4fa10781b
@ -44,6 +44,14 @@ ahriman.application.application.application\_repository module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.application.application.updates\_iterator module
|
||||||
|
--------------------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.application.application.updates_iterator
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
Module contents
|
Module contents
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -60,6 +60,14 @@ ahriman.web.schemas.file\_schema module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.schemas.info\_schema module
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.schemas.info_schema
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.web.schemas.internal\_status\_schema module
|
ahriman.web.schemas.internal\_status\_schema module
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
|
@ -12,6 +12,14 @@ ahriman.web.views.v1.status.changes module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.views.v1.status.info module
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.views.v1.status.info
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.web.views.v1.status.logs module
|
ahriman.web.views.v1.status.logs module
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ _shtab_ahriman_repo_check_option_strings=('-h' '--help' '--changes' '--no-change
|
|||||||
_shtab_ahriman_check_option_strings=('-h' '--help' '--changes' '--no-changes' '-e' '--exit-code' '--vcs' '--no-vcs' '-y' '--refresh')
|
_shtab_ahriman_check_option_strings=('-h' '--help' '--changes' '--no-changes' '-e' '--exit-code' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||||
_shtab_ahriman_repo_create_keyring_option_strings=('-h' '--help')
|
_shtab_ahriman_repo_create_keyring_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_repo_create_mirrorlist_option_strings=('-h' '--help')
|
_shtab_ahriman_repo_create_mirrorlist_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_repo_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--changes' '--no-changes' '--dependencies' '--no-dependencies' '--dry-run' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
|
_shtab_ahriman_repo_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--changes' '--no-changes' '--dependencies' '--no-dependencies' '--dry-run' '--local' '--no-local' '--manual' '--no-manual' '--partitions' '--no-partitions' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||||
_shtab_ahriman_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--changes' '--no-changes' '--dependencies' '--no-dependencies' '--dry-run' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
|
_shtab_ahriman_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--changes' '--no-changes' '--dependencies' '--no-dependencies' '--dry-run' '--local' '--no-local' '--manual' '--no-manual' '--partitions' '--no-partitions' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||||
_shtab_ahriman_repo_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '--increment' '--no-increment' '-e' '--exit-code' '-s' '--status' '-u' '--username')
|
_shtab_ahriman_repo_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '--increment' '--no-increment' '-e' '--exit-code' '-s' '--status' '-u' '--username')
|
||||||
_shtab_ahriman_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '--increment' '--no-increment' '-e' '--exit-code' '-s' '--status' '-u' '--username')
|
_shtab_ahriman_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '--increment' '--no-increment' '-e' '--exit-code' '-s' '--status' '-u' '--username')
|
||||||
_shtab_ahriman_repo_remove_unknown_option_strings=('-h' '--help' '--dry-run')
|
_shtab_ahriman_repo_remove_unknown_option_strings=('-h' '--help' '--dry-run')
|
||||||
@ -277,6 +277,8 @@ _shtab_ahriman_repo_daemon___local_nargs=0
|
|||||||
_shtab_ahriman_repo_daemon___no_local_nargs=0
|
_shtab_ahriman_repo_daemon___no_local_nargs=0
|
||||||
_shtab_ahriman_repo_daemon___manual_nargs=0
|
_shtab_ahriman_repo_daemon___manual_nargs=0
|
||||||
_shtab_ahriman_repo_daemon___no_manual_nargs=0
|
_shtab_ahriman_repo_daemon___no_manual_nargs=0
|
||||||
|
_shtab_ahriman_repo_daemon___partitions_nargs=0
|
||||||
|
_shtab_ahriman_repo_daemon___no_partitions_nargs=0
|
||||||
_shtab_ahriman_repo_daemon___vcs_nargs=0
|
_shtab_ahriman_repo_daemon___vcs_nargs=0
|
||||||
_shtab_ahriman_repo_daemon___no_vcs_nargs=0
|
_shtab_ahriman_repo_daemon___no_vcs_nargs=0
|
||||||
_shtab_ahriman_repo_daemon__y_nargs=0
|
_shtab_ahriman_repo_daemon__y_nargs=0
|
||||||
@ -294,6 +296,8 @@ _shtab_ahriman_daemon___local_nargs=0
|
|||||||
_shtab_ahriman_daemon___no_local_nargs=0
|
_shtab_ahriman_daemon___no_local_nargs=0
|
||||||
_shtab_ahriman_daemon___manual_nargs=0
|
_shtab_ahriman_daemon___manual_nargs=0
|
||||||
_shtab_ahriman_daemon___no_manual_nargs=0
|
_shtab_ahriman_daemon___no_manual_nargs=0
|
||||||
|
_shtab_ahriman_daemon___partitions_nargs=0
|
||||||
|
_shtab_ahriman_daemon___no_partitions_nargs=0
|
||||||
_shtab_ahriman_daemon___vcs_nargs=0
|
_shtab_ahriman_daemon___vcs_nargs=0
|
||||||
_shtab_ahriman_daemon___no_vcs_nargs=0
|
_shtab_ahriman_daemon___no_vcs_nargs=0
|
||||||
_shtab_ahriman_daemon__y_nargs=0
|
_shtab_ahriman_daemon__y_nargs=0
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH AHRIMAN "1" "2023\-12\-08" "ahriman" "Generated Python Manual"
|
.TH AHRIMAN "1" "2023\-12\-26" "ahriman" "Generated Python Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ahriman
|
ahriman
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -485,7 +485,7 @@ create package which contains list of available mirrors as set by configuration.
|
|||||||
.SH COMMAND \fI\,'ahriman repo\-daemon'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-daemon'\/\fR
|
||||||
usage: ahriman repo\-daemon [\-h] [\-i INTERVAL] [\-\-aur | \-\-no\-aur] [\-\-changes | \-\-no\-changes]
|
usage: ahriman repo\-daemon [\-h] [\-i INTERVAL] [\-\-aur | \-\-no\-aur] [\-\-changes | \-\-no\-changes]
|
||||||
[\-\-dependencies | \-\-no\-dependencies] [\-\-dry\-run] [\-\-local | \-\-no\-local]
|
[\-\-dependencies | \-\-no\-dependencies] [\-\-dry\-run] [\-\-local | \-\-no\-local]
|
||||||
[\-\-manual | \-\-no\-manual] [\-\-vcs | \-\-no\-vcs] [\-y]
|
[\-\-manual | \-\-no\-manual] [\-\-partitions | \-\-no\-partitions] [\-\-vcs | \-\-no\-vcs] [\-y]
|
||||||
|
|
||||||
start process which periodically will run update process
|
start process which periodically will run update process
|
||||||
|
|
||||||
@ -518,6 +518,10 @@ enable or disable checking of local packages for updates
|
|||||||
\fB\-\-manual\fR, \fB\-\-no\-manual\fR
|
\fB\-\-manual\fR, \fB\-\-no\-manual\fR
|
||||||
include or exclude manual updates
|
include or exclude manual updates
|
||||||
|
|
||||||
|
.TP
|
||||||
|
\fB\-\-partitions\fR, \fB\-\-no\-partitions\fR
|
||||||
|
instead of updating whole repository, split updates into chunks
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
|
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
|
||||||
fetch actual version of VCS packages
|
fetch actual version of VCS packages
|
||||||
|
@ -157,6 +157,7 @@ _shtab_ahriman_daemon_options=(
|
|||||||
"--dry-run[just perform check for updates, same as check command (default\: False)]"
|
"--dry-run[just perform check for updates, same as check command (default\: False)]"
|
||||||
{--local,--no-local}"[enable or disable checking of local packages for updates (default\: True)]:local:"
|
{--local,--no-local}"[enable or disable checking of local packages for updates (default\: True)]:local:"
|
||||||
{--manual,--no-manual}"[include or exclude manual updates (default\: True)]:manual:"
|
{--manual,--no-manual}"[include or exclude manual updates (default\: True)]:manual:"
|
||||||
|
{--partitions,--no-partitions}"[instead of updating whole repository, split updates into chunks (default\: True)]:partitions:"
|
||||||
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: True)]:vcs:"
|
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: True)]:vcs:"
|
||||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
||||||
)
|
)
|
||||||
@ -364,6 +365,7 @@ _shtab_ahriman_repo_daemon_options=(
|
|||||||
"--dry-run[just perform check for updates, same as check command (default\: False)]"
|
"--dry-run[just perform check for updates, same as check command (default\: False)]"
|
||||||
{--local,--no-local}"[enable or disable checking of local packages for updates (default\: True)]:local:"
|
{--local,--no-local}"[enable or disable checking of local packages for updates (default\: True)]:local:"
|
||||||
{--manual,--no-manual}"[include or exclude manual updates (default\: True)]:manual:"
|
{--manual,--no-manual}"[include or exclude manual updates (default\: True)]:manual:"
|
||||||
|
{--partitions,--no-partitions}"[instead of updating whole repository, split updates into chunks (default\: True)]:partitions:"
|
||||||
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: True)]:vcs:"
|
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: True)]:vcs:"
|
||||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
||||||
)
|
)
|
||||||
|
@ -607,16 +607,22 @@ def _set_repo_daemon_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
parser.add_argument("--dependencies", help="process missing package dependencies",
|
parser.add_argument("--dependencies", help="process missing package dependencies",
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
parser.add_argument("--dry-run", help="just perform check for updates, same as check command", action="store_true")
|
parser.add_argument("--dry-run", help="just perform check for updates, same as check command", action="store_true")
|
||||||
|
parser.add_argument("--increment", help="increment package release (pkgrel) on duplicate",
|
||||||
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
parser.add_argument("--local", help="enable or disable checking of local packages for updates",
|
parser.add_argument("--local", help="enable or disable checking of local packages for updates",
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
parser.add_argument("--manual", help="include or exclude manual updates",
|
parser.add_argument("--manual", help="include or exclude manual updates",
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.add_argument("--partitions", help="instead of updating whole repository, split updates into chunks",
|
||||||
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
|
||||||
parser.add_argument("--vcs", help="fetch actual version of VCS packages",
|
parser.add_argument("--vcs", help="fetch actual version of VCS packages",
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||||
"-yy to force refresh even if up to date",
|
"-yy to force refresh even if up to date",
|
||||||
action="count", default=False)
|
action="count", default=False)
|
||||||
parser.set_defaults(handler=handlers.Daemon, exit_code=False, package=[])
|
parser.set_defaults(handler=handlers.Daemon, exit_code=False,
|
||||||
|
lock=Path(tempfile.gettempdir()) / "ahriman-daemon.lock", package=[])
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
133
src/ahriman/application/application/updates_iterator.py
Normal file
133
src/ahriman/application/application/updates_iterator.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021-2023 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
import time
|
||||||
|
|
||||||
|
from collections.abc import Iterator
|
||||||
|
from typing import Self
|
||||||
|
|
||||||
|
from ahriman.application.application import Application
|
||||||
|
from ahriman.core.tree import Tree
|
||||||
|
|
||||||
|
|
||||||
|
class UpdatesIterator(Iterator[list[str] | None]):
|
||||||
|
"""
|
||||||
|
class-helper for iteration over packages to check for updates. It yields list of packages which were not yet
|
||||||
|
updated
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
application(Application): application instance
|
||||||
|
interval(int): predefined interval for updates. The updates will be split into chunks in the way in which all
|
||||||
|
packages will be updated in the specified interval
|
||||||
|
updated_packages(set[str]): list of packages which have been already updated
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
Typical usage of this class is something like:
|
||||||
|
|
||||||
|
>>> application = ...
|
||||||
|
>>> iterator = UpdatesIterator(application, None)
|
||||||
|
>>>
|
||||||
|
>>> for updates in iterator:
|
||||||
|
>>> print(updates)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, application: Application, interval: int) -> None:
|
||||||
|
"""
|
||||||
|
default constructor
|
||||||
|
|
||||||
|
Args:
|
||||||
|
application(Application): application instance
|
||||||
|
interval(int): predefined interval for updates
|
||||||
|
"""
|
||||||
|
self.application = application
|
||||||
|
self.interval = interval
|
||||||
|
|
||||||
|
self.updated_packages: set[str] = set()
|
||||||
|
|
||||||
|
def select_packages(self) -> tuple[list[str] | None, int]:
|
||||||
|
"""
|
||||||
|
select next packages partition for updates
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple[list[str] | None, int]: packages partition for updates if any and total amount of partitions.
|
||||||
|
"""
|
||||||
|
packages = self.application.repository.packages()
|
||||||
|
if not packages: # empty repository case
|
||||||
|
return None, 1
|
||||||
|
|
||||||
|
# split packages to the maximal available amount of chunks
|
||||||
|
partitions = Tree.partition(packages, count=len(packages))
|
||||||
|
frequency = len(partitions) # must be always not-empty
|
||||||
|
|
||||||
|
for partition in partitions:
|
||||||
|
bases = [package.base for package in partition]
|
||||||
|
# check if all packages from this partition have been already updated
|
||||||
|
if self.updated_packages.issuperset(bases):
|
||||||
|
continue
|
||||||
|
# there are packages which were not checked yet, return them
|
||||||
|
return bases, frequency
|
||||||
|
|
||||||
|
# in this case there is nothing to update or repository is empty
|
||||||
|
self.updated_packages.clear()
|
||||||
|
|
||||||
|
# extract bases from the first partition and return them
|
||||||
|
bases = [package.base for package in next(iter(partitions))]
|
||||||
|
return bases, frequency
|
||||||
|
|
||||||
|
def __iter__(self) -> Self:
|
||||||
|
"""
|
||||||
|
base iterator method
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Self: iterator instance
|
||||||
|
"""
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self) -> list[str] | None:
|
||||||
|
"""
|
||||||
|
retrieve next element in the iterator. This method will delay result for the amount of time equals
|
||||||
|
:attr:`interval` divided by the amount of chunks
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list[str] | None: next packages chunk to be updated. ``None`` means no updates
|
||||||
|
"""
|
||||||
|
to_update, frequency = self.select_packages()
|
||||||
|
if to_update is not None:
|
||||||
|
# update cached built packages
|
||||||
|
self.updated_packages.update(to_update)
|
||||||
|
|
||||||
|
# wait for update before emit
|
||||||
|
time.sleep(self.interval / frequency)
|
||||||
|
|
||||||
|
return to_update
|
||||||
|
|
||||||
|
|
||||||
|
class FixedUpdatesIterator(UpdatesIterator):
|
||||||
|
"""
|
||||||
|
implementation of the :class:`UpdatesIterator` which always emits empty list, which is the same as update all
|
||||||
|
"""
|
||||||
|
|
||||||
|
def select_packages(self) -> tuple[list[str] | None, int]:
|
||||||
|
"""
|
||||||
|
select next packages partition for updates
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple[list[str] | None, int]: packages partition for updates if any and total amount of partitions.
|
||||||
|
"""
|
||||||
|
return [], 1
|
@ -18,8 +18,9 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import argparse
|
import argparse
|
||||||
import threading
|
|
||||||
|
|
||||||
|
from ahriman.application.application import Application
|
||||||
|
from ahriman.application.application.updates_iterator import FixedUpdatesIterator, UpdatesIterator
|
||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.models.repository_id import RepositoryId
|
from ahriman.models.repository_id import RepositoryId
|
||||||
@ -44,9 +45,15 @@ class Daemon(Handler):
|
|||||||
"""
|
"""
|
||||||
from ahriman.application.handlers import Update
|
from ahriman.application.handlers import Update
|
||||||
|
|
||||||
event = threading.Event()
|
application = Application(repository_id, configuration, report=report, refresh_pacman_database=args.refresh)
|
||||||
try:
|
if args.partitions:
|
||||||
while not event.wait(args.interval):
|
iterator = UpdatesIterator(application, args.interval)
|
||||||
Update.run(args, repository_id, configuration, report=report)
|
else:
|
||||||
except KeyboardInterrupt:
|
iterator = FixedUpdatesIterator(application, args.interval)
|
||||||
pass # normal exit
|
|
||||||
|
for packages in iterator:
|
||||||
|
if packages is None:
|
||||||
|
continue # nothing to check case
|
||||||
|
|
||||||
|
args.package = packages
|
||||||
|
Update.run(args, repository_id, configuration, report=report)
|
||||||
|
@ -2,9 +2,11 @@ import pytest
|
|||||||
|
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
from ahriman.application.application import Application
|
||||||
from ahriman.application.application.application_packages import ApplicationPackages
|
from ahriman.application.application.application_packages import ApplicationPackages
|
||||||
from ahriman.application.application.application_properties import ApplicationProperties
|
from ahriman.application.application.application_properties import ApplicationProperties
|
||||||
from ahriman.application.application.application_repository import ApplicationRepository
|
from ahriman.application.application.application_repository import ApplicationRepository
|
||||||
|
from ahriman.application.application.updates_iterator import FixedUpdatesIterator, UpdatesIterator
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
from ahriman.core.repository import Repository
|
from ahriman.core.repository import Repository
|
||||||
@ -71,3 +73,31 @@ def application_repository(configuration: Configuration, database: SQLite, repos
|
|||||||
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
|
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
return ApplicationRepository(repository_id, configuration, report=False)
|
return ApplicationRepository(repository_id, configuration, report=False)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def fixed_updates_iterator(application: Application) -> FixedUpdatesIterator:
|
||||||
|
"""
|
||||||
|
fixture for fixed updates iterator
|
||||||
|
|
||||||
|
Args:
|
||||||
|
application(Application): application fixture
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
FixedUpdatesIterator: fixed updates iterator test instance
|
||||||
|
"""
|
||||||
|
return FixedUpdatesIterator(application, 1)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def updates_iterator(application: Application) -> UpdatesIterator:
|
||||||
|
"""
|
||||||
|
fixture for chunk bases updates iterator
|
||||||
|
|
||||||
|
Args:
|
||||||
|
application(Application): application fixture
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
UpdatesIterator: updates iterator test instance
|
||||||
|
"""
|
||||||
|
return UpdatesIterator(application, 1)
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
from pytest_mock import MockerFixture
|
||||||
|
from unittest.mock import call as MockCall
|
||||||
|
|
||||||
|
from ahriman.application.application.updates_iterator import FixedUpdatesIterator, UpdatesIterator
|
||||||
|
from ahriman.models.package import Package
|
||||||
|
|
||||||
|
|
||||||
|
def test_select_packages(updates_iterator: UpdatesIterator, package_ahriman: Package,
|
||||||
|
package_python_schedule: Package, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must return next partition
|
||||||
|
"""
|
||||||
|
mocker.patch("ahriman.core.repository.Repository.packages",
|
||||||
|
return_value=[package_ahriman, package_python_schedule])
|
||||||
|
|
||||||
|
assert updates_iterator.select_packages() == ([package_python_schedule.base], 2)
|
||||||
|
assert updates_iterator.select_packages() == ([package_python_schedule.base], 2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_select_packages_empty(updates_iterator: UpdatesIterator, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must return None for empty repository
|
||||||
|
"""
|
||||||
|
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[])
|
||||||
|
assert updates_iterator.select_packages() == (None, 1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_select_packages_cycle(updates_iterator: UpdatesIterator, package_ahriman: Package,
|
||||||
|
package_python_schedule: Package, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must cycle over partitions
|
||||||
|
"""
|
||||||
|
mocker.patch("ahriman.core.repository.Repository.packages",
|
||||||
|
return_value=[package_ahriman, package_python_schedule])
|
||||||
|
|
||||||
|
assert updates_iterator.select_packages() == ([package_python_schedule.base], 2)
|
||||||
|
updates_iterator.updated_packages.add(package_python_schedule.base)
|
||||||
|
|
||||||
|
assert updates_iterator.select_packages() == ([package_ahriman.base], 2)
|
||||||
|
updates_iterator.updated_packages.add(package_ahriman.base)
|
||||||
|
|
||||||
|
assert updates_iterator.select_packages() == ([package_python_schedule.base], 2)
|
||||||
|
assert not updates_iterator.updated_packages
|
||||||
|
|
||||||
|
|
||||||
|
def test_iter(updates_iterator: UpdatesIterator) -> None:
|
||||||
|
"""
|
||||||
|
must return self as iterator
|
||||||
|
"""
|
||||||
|
assert updates_iterator.__iter__() == updates_iterator
|
||||||
|
|
||||||
|
|
||||||
|
def test_next(updates_iterator: UpdatesIterator, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must return next chunk to update
|
||||||
|
"""
|
||||||
|
mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.select_packages",
|
||||||
|
side_effect=[([package_ahriman.base], 2), (None, 2), StopIteration])
|
||||||
|
sleep_mock = mocker.patch("time.sleep")
|
||||||
|
|
||||||
|
updates = [packages for packages in updates_iterator]
|
||||||
|
assert updates == [[package_ahriman.base], None]
|
||||||
|
sleep_mock.assert_has_calls([MockCall(0.5), MockCall(0.5)])
|
||||||
|
|
||||||
|
|
||||||
|
def test_fixed_updates_iterator(fixed_updates_iterator: FixedUpdatesIterator, package_ahriman: Package,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must always return empty package list
|
||||||
|
"""
|
||||||
|
assert fixed_updates_iterator.select_packages() == ([], 1)
|
||||||
|
|
||||||
|
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
|
||||||
|
assert fixed_updates_iterator.select_packages() == ([], 1)
|
@ -1,10 +1,11 @@
|
|||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
from unittest.mock import call as MockCall
|
|
||||||
|
|
||||||
from ahriman.application.handlers import Daemon
|
from ahriman.application.handlers import Daemon
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.core.repository import Repository
|
||||||
|
from ahriman.models.package import Package
|
||||||
|
|
||||||
|
|
||||||
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
@ -18,35 +19,60 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
|||||||
argparse.Namespace: generated arguments for these test cases
|
argparse.Namespace: generated arguments for these test cases
|
||||||
"""
|
"""
|
||||||
args.interval = 60 * 60 * 12
|
args.interval = 60 * 60 * 12
|
||||||
args.aur = True
|
args.partitions = True
|
||||||
args.local = True
|
args.refresh = 0
|
||||||
args.manual = True
|
|
||||||
args.vcs = True
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_run(args: argparse.Namespace, configuration: Configuration, package_ahriman: Package, repository: Repository,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run command
|
must run command
|
||||||
"""
|
"""
|
||||||
args = _default_args(args)
|
args = _default_args(args)
|
||||||
|
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||||
run_mock = mocker.patch("ahriman.application.handlers.Update.run")
|
run_mock = mocker.patch("ahriman.application.handlers.Update.run")
|
||||||
wait_mock = mocker.patch("threading.Event.wait", side_effect=[False, True])
|
iter_mock = mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.__iter__",
|
||||||
|
return_value=iter([[package_ahriman.base]]))
|
||||||
|
|
||||||
|
_, repository_id = configuration.check_loaded()
|
||||||
|
Daemon.run(args, repository_id, configuration, report=True)
|
||||||
|
args.package = [package_ahriman.base]
|
||||||
|
run_mock.assert_called_once_with(args, repository_id, configuration, report=True)
|
||||||
|
iter_mock.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_no_partitions(args: argparse.Namespace, configuration: Configuration, repository: Repository,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must run command without partitioning
|
||||||
|
"""
|
||||||
|
args = _default_args(args)
|
||||||
|
args.partitions = False
|
||||||
|
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||||
|
run_mock = mocker.patch("ahriman.application.handlers.Update.run")
|
||||||
|
iter_mock = mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.__iter__",
|
||||||
|
return_value=iter([[]]))
|
||||||
|
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
Daemon.run(args, repository_id, configuration, report=True)
|
Daemon.run(args, repository_id, configuration, report=True)
|
||||||
run_mock.assert_called_once_with(args, repository_id, configuration, report=True)
|
run_mock.assert_called_once_with(args, repository_id, configuration, report=True)
|
||||||
wait_mock.assert_has_calls([MockCall(args.interval), MockCall(args.interval)])
|
iter_mock.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
def test_run_keyboard_interrupt(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_run_no_updates(args: argparse.Namespace, configuration: Configuration, package_ahriman: Package,
|
||||||
|
repository: Repository, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must handle KeyboardInterrupt exception
|
must skip empty update list
|
||||||
"""
|
"""
|
||||||
args = _default_args(args)
|
args = _default_args(args)
|
||||||
mocker.patch("ahriman.application.handlers.Update.run", side_effect=KeyboardInterrupt)
|
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||||
wait_mock = mocker.patch("threading.Event.wait", return_value=False)
|
run_mock = mocker.patch("ahriman.application.handlers.Update.run")
|
||||||
|
iter_mock = mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.__iter__",
|
||||||
|
return_value=iter([[package_ahriman.base], None]))
|
||||||
|
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
Daemon.run(args, repository_id, configuration, report=True)
|
Daemon.run(args, repository_id, configuration, report=True)
|
||||||
wait_mock.assert_called_once_with(args.interval)
|
args.package = [package_ahriman.base]
|
||||||
|
run_mock.assert_called_once_with(args, repository_id, configuration, report=True)
|
||||||
|
iter_mock.assert_called_once_with()
|
||||||
|
Loading…
Reference in New Issue
Block a user