Compare commits

...
4 Commits
Author SHA1 Message Date
arcanis 3ac5f13f18 Release 2.22.2 2026-10-13 12:44:51 +03:00
arcanis e20deea1dd fix: fix typescript dependencies 2026-10-13 12:11:29 +03:00
arcanis 118ffdffe5 fix: update event bus for the last aiohttp-sse api change 2026-10-13 11:21:24 +03:00
arcanis 19ca1ac797 feat: detect dependencies resolution error 2026-10-13 10:31:11 +03:00
12 changed files with 91 additions and 49 deletions

No files matched your search

@@ -1,4 +1,9 @@
# AUTOMATICALLY GENERATED by https://github.com/tqdm/shtab
# Usage:
# 1) Copy this to somewhere (e.g. ~/.local/share/bash_completion/ahriman).
# 2) Add the following line to your .bashrc:
# source ~/.local/share/bash_completion/ahriman
# See also: https://github.com/scop/bash-completion/blob/main/doc/configuration.md
_shtab_ahriman_subparsers=(add aur-search check clean config config-validate copy daemon help help-commands-unsafe help-updates help-version init key-import package-add package-archives package-changes package-changes-remove package-copy package-hold package-pkgbuild package-pkgbuild-remove package-remove package-rollback package-status package-status-remove package-status-update package-unhold package-update patch-add patch-list patch-remove patch-set-add rebuild remove remove-unknown repo-backup repo-check repo-clean repo-config repo-config-validate repo-create-keyring repo-create-mirrorlist repo-daemon repo-init repo-rebuild repo-remove-unknown repo-report repo-restore repo-setup repo-sign repo-statistics repo-status-update repo-sync repo-tree repo-triggers repo-update report run search service-clean service-config service-config-validate service-key-import service-repositories service-run service-setup service-shell service-tree-migrate setup shell sign status status-update sync update user-add user-list user-remove version web web-reload)
@@ -626,7 +631,7 @@ _set_parser_defaults() {
completed_positional_actions=0
_set_new_action "pos_${completed_positional_actions}" true
_set_new_action "pos_$completed_positional_actions" true
}
# $1=action identifier
@@ -686,13 +691,13 @@ _shtab_ahriman() {
local this_word="${COMP_WORDS[$word_index]}"
if [[ $pos_only = 1 || " $this_word " != " -- " ]]; then
if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" ${this_word} "* ]]; then
if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" $this_word "* ]]; then
# valid subcommand: add it to the prefix & reset the current action
prefix="${prefix}_$(_shtab_replace_nonword $this_word)"
_set_parser_defaults
fi
if [[ " ${current_option_strings[@]} " == *" ${this_word} "* ]]; then
if [[ " ${current_option_strings[@]} " == *" $this_word "* ]]; then
# a new action should be acquired (due to recognised option string or
# no more input expected from current action);
# the next positional action can fill in here
@@ -706,7 +711,7 @@ _shtab_ahriman() {
(( $word_index + 1 - $current_action_args_start_index - $pos_only >= \
$current_action_nargs )); then
$current_action_is_positional && let "completed_positional_actions += 1"
_set_new_action "pos_${completed_positional_actions}" true
_set_new_action "pos_$completed_positional_actions" true
fi
else
pos_only=1 # "--" delimiter encountered
@@ -718,23 +723,31 @@ _shtab_ahriman() {
# Generate the completions
COMPREPLY=()
if [[ $pos_only = 0 && "${completing_word}" == -* ]]; then
if [[ $pos_only = 0 && "$completing_word" == -* &&
( -z "$current_action_compgen" || "$current_action_is_positional" = true ) ]]; then
# optional argument started: use option strings
while IFS= read -r line; do COMPREPLY+=("$line"); done < <(
compgen -W "${current_option_strings[*]}" -- "${completing_word}")
elif [[ "${previous_word}" =~ ^[0-9\&]*[\<\>]\>?$ ]]; then
compgen -W "${current_option_strings[*]}" -- "$completing_word")
elif [[ "$previous_word" =~ ^[0-9\&]*[\<\>]\>?$ ]]; then
# handle redirection operators
while IFS= read -r line; do COMPREPLY+=("$line"); done < <(compgen -f -- "${completing_word}")
compopt -o filenames 2>/dev/null || : # bash>=4
while IFS= read -r line; do COMPREPLY+=("$line"); done < <(compgen -f -- "$completing_word")
else
# use choices & compgen
[ -n "${current_action_compgen}" ] &&
local action_compgen_word="$completing_word"
# handle tab-completing in the middle of a line (#248 <- #116)
[[ -n "$current_action_compgen" && "$completing_word" == -* ]] && action_compgen_word=""
[ -n "$current_action_compgen" ] && {
[[ "$current_action_compgen" =~ _(file|dir|glob|FILE|DIR|GLOB)|File|Dir|Glob ]] &&
compopt -o filenames 2>/dev/null || : # bash>=4
while IFS= read -r line; do COMPREPLY+=("$line"); done < <(
"${current_action_compgen}" "${completing_word}")
"$current_action_compgen" "$action_compgen_word")
}
while IFS= read -r line; do COMPREPLY+=("$line"); done < <(
compgen -W "${current_action_choices[*]}" -- "${completing_word}")
compgen -W "${current_action_choices[*]}" -- "$completing_word")
fi
return 0
}
complete -o filenames -F _shtab_ahriman ahriman
complete -F _shtab_ahriman ahriman
@@ -1,4 +1,4 @@
.TH AHRIMAN "1" "2026\-08\-18" "ahriman 2.22.1" "ArcH linux ReposItory MANager"
.TH AHRIMAN "1" "2026\-10\-13" "ahriman 2.22.2" "ArcH linux ReposItory MANager"
.SH NAME
ahriman \- ArcH linux ReposItory MANager
.SH SYNOPSIS
@@ -1,6 +1,11 @@
#compdef ahriman
# AUTOMATICALLY GENERATED by https://github.com/tqdm/shtab
# Usage:
# 1) Copy this to a file named _ahriman (e.g. ~/.local/share/zsh_completion/_ahriman).
# 2) Add the following line to your .zshrc:
# fpath=(~/.local/share/zsh_completion $fpath)
# See also: https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org
_shtab_ahriman_commands() {
+1 -1
View File
@@ -17,4 +17,4 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
__version__ = "2.22.1"
__version__ = "2.22.2"
@@ -83,6 +83,15 @@ Process stderr:
{self.stderr}"""
class DependencyResolutionError(RuntimeError):
"""
exception raised when package dependencies cannot be resolved
"""
def __init__(self, unprocessed: list[str]) -> None:
RuntimeError.__init__(self, f"Could not process dependencies. Unresolved packages: {unprocessed}")
class DuplicateRunError(RuntimeError):
"""
exception which will be raised if there is another application instance
+6 -1
View File
@@ -22,7 +22,7 @@ from __future__ import annotations
from collections.abc import Iterable
from functools import partial
from ahriman.core.exceptions import PartitionError
from ahriman.core.exceptions import DependencyResolutionError, PartitionError
from ahriman.core.utils import minmax, partition
from ahriman.models.package import Package
@@ -226,6 +226,9 @@ class Tree:
Returns:
list[list[Package]]: sorted list of packages lists based on their dependencies
Raises:
DependencyResolutionError: dependency cycle prevents ordering packages
"""
unsorted: list[list[Leaf]] = []
@@ -235,6 +238,8 @@ class Tree:
# additional workaround with partial in order to hide cell-var-from-loop pylint warning
predicate = partial(Leaf.is_root, packages=unprocessed)
new_level, unprocessed = partition(unprocessed, predicate)
if not new_level:
raise DependencyResolutionError([leaf.package.base for leaf in unprocessed])
unsorted.append(new_level)
# move leaves to the end if they are not required at the next level
+12 -1
View File
@@ -1,6 +1,6 @@
import pytest
from ahriman.core.exceptions import PartitionError
from ahriman.core.exceptions import DependencyResolutionError, PartitionError
from ahriman.core.tree import Leaf, Tree
from ahriman.models.package import Package
from ahriman.models.package_description import PackageDescription
@@ -270,3 +270,14 @@ def test_tree_partitions() -> None:
first, second = tree.partitions(count=3)
assert first == [leaf1.package, leaf2.package, leaf3.package, leaf5.package]
assert second == [leaf4.package]
def test_tree_levels_cycle(leaf_ahriman: Leaf, leaf_python_schedule: Leaf) -> None:
"""
must raise an exception if dependencies contain a cycle
"""
leaf_ahriman.dependencies = set(leaf_python_schedule.items)
leaf_python_schedule.dependencies = set(leaf_ahriman.items)
with pytest.raises(DependencyResolutionError):
Tree([leaf_ahriman, leaf_python_schedule]).levels()
@@ -87,7 +87,8 @@ class EventBusView(BaseView):
"""
while response.is_connected():
try:
event_type, data = await wait_for(queue.get(), timeout=response.ping_interval)
# pylint: disable=protected-access
event_type, data = await wait_for(queue.get(), timeout=response._ping_interval)
except TimeoutError:
continue
except QueueShutDown:
@@ -3,6 +3,7 @@ import pytest
from aiohttp.test_utils import TestClient
from aiohttp.web import HTTPBadRequest
from aiohttp_sse import EventSourceResponse
from asyncio import Queue
from multidict import MultiDict
from pytest_mock import MockerFixture
@@ -95,21 +96,20 @@ def test_routes() -> None:
async def test_run_timeout() -> None:
"""
must handle timeout and continue loop
must recheck the connection after a queue timeout
"""
queue = Queue()
queue = AsyncMock(spec_set=Queue)
queue.get.side_effect = TimeoutError
response = AsyncMock(spec_set=EventSourceResponse())
response._ping_interval = 0.01
response.is_connected.side_effect = [True, False]
async def _shutdown() -> None:
await asyncio.sleep(0.05)
queue.shutdown()
response = AsyncMock()
response.is_connected = lambda: True
response.ping_interval = 0.01
asyncio.create_task(_shutdown())
await EventBusView._run(response, queue)
assert response.is_connected.call_count == 2
queue.get.assert_awaited_once()
response.send.assert_not_awaited()
def test_topics() -> None:
"""
+1 -1
View File
@@ -2,7 +2,7 @@
pkgbase='ahriman'
pkgname=('ahriman' 'ahriman-core' 'ahriman-triggers' 'ahriman-web')
pkgver=2.22.1
pkgver=2.22.2
pkgrel=1
pkgdesc="ArcH linux ReposItory MANager"
arch=('any')
+3 -8
View File
@@ -5,7 +5,7 @@ digraph G {
rankdir = TB;
node [style=filled,fillcolor="#ffffff",fontcolor="#000000",fontname=Helvetica,fontsize=10];
ahriman_application_ahriman [fillcolor="#814b37",fontcolor="#ffffff",label="ahriman\.\napplication\.\nahriman"];
ahriman_application_ahriman [fillcolor="#884f3a",fontcolor="#ffffff",label="ahriman\.\napplication\.\nahriman"];
ahriman_application_application [fillcolor="blue",fontcolor="white",label="ahriman\.\napplication\.\napplication",shape="box"];
ahriman_application_application_application [fillcolor="blue",fontcolor="white",label="ahriman\.\napplication\.\napplication\.\napplication",shape="box"];
ahriman_application_application_application_packages [fillcolor="blue",fontcolor="white",label="ahriman\.\napplication\.\napplication\.\napplication_packages",shape="box"];
@@ -41,12 +41,12 @@ digraph G {
ahriman_application_handlers_run [fillcolor="#8f533d",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nrun"];
ahriman_application_handlers_search [fillcolor="#6b3e2e",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nsearch"];
ahriman_application_handlers_service_updates [fillcolor="#814b37",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nservice_updates"];
ahriman_application_handlers_setup [fillcolor="#6b3e2e",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nsetup"];
ahriman_application_handlers_setup [fillcolor="#724331",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nsetup"];
ahriman_application_handlers_shell [fillcolor="#814b37",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nshell"];
ahriman_application_handlers_sign [fillcolor="#884f3a",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nsign"];
ahriman_application_handlers_statistics [fillcolor="#6b3e2e",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nstatistics"];
ahriman_application_handlers_status [fillcolor="#6b3e2e",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nstatus"];
ahriman_application_handlers_status_update [fillcolor="#724331",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nstatus_update"];
ahriman_application_handlers_status_update [fillcolor="#794734",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nstatus_update"];
ahriman_application_handlers_structure [fillcolor="#794734",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\nstructure"];
ahriman_application_handlers_tree_migrate [fillcolor="#814b37",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\ntree_migrate"];
ahriman_application_handlers_triggers [fillcolor="#8a472e",fontcolor="#ffffff",label="ahriman\.\napplication\.\nhandlers\.\ntriggers"];
@@ -1080,19 +1080,14 @@ digraph G {
ahriman_core_upload_upload -> ahriman_core_upload_s3 [fillcolor="blue",weight="3"];
ahriman_core_upload_upload -> ahriman_core_upload_upload_trigger [fillcolor="blue",weight="3"];
ahriman_core_upload_upload_trigger -> ahriman_core_upload [fillcolor="blue",weight="3"];
ahriman_core_utils -> ahriman_application_ahriman [fillcolor="#db4005",minlen="2"];
ahriman_core_utils -> ahriman_application_application_application_packages [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_add [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_daemon [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_rebuild [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_rollback [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_setup [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_statistics [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_status [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_status_update [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_tree_migrate [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_update [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_handlers_users [fillcolor="#db4005",minlen="3"];
ahriman_core_utils -> ahriman_application_lock [fillcolor="#db4005",minlen="2"];
ahriman_core_utils -> ahriman_core_alpm_pacman [fillcolor="#db4005",minlen="2",weight="2"];
ahriman_core_utils -> ahriman_core_alpm_repo [fillcolor="#db4005",minlen="2",weight="2"];
+15 -12
View File
@@ -2,34 +2,37 @@
"dependencies": {
"@emotion/react": ">=11.14.0 <11.15.0",
"@emotion/styled": ">=11.14.0 <11.15.0",
"@mui/icons-material": ">=9.3.0 <9.4.0",
"@mui/material": ">=9.3.0 <9.4.0",
"@mui/x-data-grid": ">=9.11.0 <9.12.0",
"@tanstack/react-query": ">=5.101.0 <5.102.0",
"@mui/icons-material": ">=9.5.0 <9.6.0",
"@mui/material": ">=9.5.0 <9.6.0",
"@mui/x-data-grid": ">=9.15.0 <9.16.0",
"@tanstack/react-query": ">=5.104.0 <5.105.0",
"chart.js": ">=4.5.0 <4.6.0",
"react": ">=19.2.0 <19.3.0",
"react": ">=19.3.0 <19.4.0",
"react-chartjs-2": ">=5.3.0 <5.4.0",
"react-dom": ">=19.2.0 <19.3.0",
"react-dom": ">=19.3.0 <19.4.0",
"react-error-boundary": ">=6.1.0 <6.2.0",
"react-syntax-highlighter": ">=16.1.0 <16.2.0"
},
"devDependencies": {
"@eslint/js": ">=9.39.0 <9.40.0",
"@stylistic/eslint-plugin": ">=5.10.0 <5.11.0",
"@types/react": ">=19.2.0 <19.3.0",
"@types/react-dom": ">=19.2.0 <19.3.0",
"@types/react": ">=19.3.0 <19.4.0",
"@types/react-dom": ">=19.3.0 <19.4.0",
"@types/react-syntax-highlighter": ">=15.5.0 <15.6.0",
"@vitejs/plugin-react": ">=6.0.0 <6.1.0",
"@vitejs/plugin-react": ">=6.1.0 <6.2.0",
"eslint": ">=9.39.0 <9.40.0",
"eslint-plugin-react": ">=7.37.0 <7.38.0",
"eslint-plugin-react-hooks": ">=7.1.0 <7.2.0",
"eslint-plugin-react-refresh": ">=0.5.0 <0.6.0",
"eslint-plugin-simple-import-sort": ">=14.0.0 <14.1.0",
"typescript": ">=6.0.0 <6.1.0",
"typescript-eslint": ">=8.67.0 <8.68.0",
"vite": ">=8.2.0 <8.3.0"
"typescript-eslint": ">=8.71.0 <8.72.0",
"vite": ">=8.3.0 <8.4.0"
},
"name": "ahriman",
"overrides": {
"@mui/x-internals": "$@mui/x-data-grid"
},
"private": true,
"scripts": {
"build": "tsc && vite build",
@@ -39,5 +42,5 @@
"preview": "vite preview"
},
"type": "module",
"version": "2.22.1"
"version": "2.22.2"
}