Compare commits

...

3 Commits

7 changed files with 624 additions and 594 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
pkgbase='ahriman'
pkgname=('ahriman' 'ahriman-core' 'ahriman-triggers' 'ahriman-web')
pkgver=2.17.1
pkgver=2.18.0
pkgrel=1
pkgdesc="ArcH linux ReposItory MANager"
arch=('any')

View File

@ -635,6 +635,7 @@ _set_new_action() {
# ${!x} -> ${hello} -> "world"
_shtab_ahriman() {
local completing_word="${COMP_WORDS[COMP_CWORD]}"
local previous_word="${COMP_WORDS[COMP_CWORD-1]}"
local completed_positional_actions
local current_action
local current_action_args_start_index
@ -691,6 +692,10 @@ _shtab_ahriman() {
if [[ $pos_only = 0 && "${completing_word}" == -* ]]; then
# optional argument started: use option strings
COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") )
elif [[ "${previous_word}" == ">" || "${previous_word}" == ">>" ||
"${previous_word}" =~ ^[12]">" || "${previous_word}" =~ ^[12]">>" ]]; then
# handle redirection operators
COMPREPLY=( $(compgen -f -- "${completing_word}") )
else
# use choices & compgen
local IFS=$'\n' # items may contain spaces, so delimit using newline

View File

@ -1,4 +1,4 @@
.TH AHRIMAN "1" "2025\-01\-05" "ahriman" "Generated Python Manual"
.TH AHRIMAN "1" "2025\-06\-13" "ahriman" "Generated Python Manual"
.SH NAME
ahriman
.SH SYNOPSIS

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.17.1"
__version__ = "2.18.0"

View File

@ -23,7 +23,7 @@ import sys
from collections.abc import Generator, Mapping, MutableMapping
from string import Template
from typing import ClassVar
from typing import Any, ClassVar
from ahriman.core.configuration.shell_template import ShellTemplate
@ -85,7 +85,7 @@ class ShellInterpolator(configparser.Interpolation):
"prefix": sys.prefix,
}
def before_get(self, parser: MutableMapping[str, Mapping[str, str]], section: str, option: str, value: str,
def before_get(self, parser: MutableMapping[str, Mapping[str, str]], section: Any, option: Any, value: str,
defaults: Mapping[str, str]) -> str:
"""
interpolate option value
@ -100,8 +100,8 @@ class ShellInterpolator(configparser.Interpolation):
Args:
parser(MutableMapping[str, Mapping[str, str]]): option parser
section(str): section name
option(str): option name
section(Any): section name
option(Any): option name
value(str): source (not-converted) value
defaults(Mapping[str, str]): default values

View File

@ -1,8 +1,8 @@
import pytest
import pytest_asyncio
from aiohttp.test_utils import TestClient
from aiohttp.web import Application, Resource, UrlMappingMatchInfo
from asyncio import BaseEventLoop
from collections.abc import Awaitable, Callable
from marshmallow import Schema
from pytest_mock import MockerFixture
@ -164,15 +164,13 @@ def application_with_auth(configuration: Configuration, user: User, spawner: Spa
return application
@pytest.fixture
def client(application: Application, event_loop: BaseEventLoop, aiohttp_client: Any,
mocker: MockerFixture) -> TestClient:
@pytest_asyncio.fixture
async def client(application: Application, aiohttp_client: Any, mocker: MockerFixture) -> TestClient:
"""
web client fixture
Args:
application(Application): application fixture
event_loop(BaseEventLoop): context event loop
aiohttp_client(Any): aiohttp client fixture
mocker(MockerFixture): mocker object
@ -180,37 +178,35 @@ def client(application: Application, event_loop: BaseEventLoop, aiohttp_client:
TestClient: web client test instance
"""
mocker.patch("pathlib.Path.iterdir", return_value=[])
return event_loop.run_until_complete(aiohttp_client(application))
return await aiohttp_client(application)
@pytest.fixture
def client_with_auth(application_with_auth: Application, event_loop: BaseEventLoop, aiohttp_client: Any,
mocker: MockerFixture) -> TestClient:
"""
web client fixture with full authorization functions
Args:
application_with_auth(Application): application fixture
event_loop(BaseEventLoop): context event loop
aiohttp_client(Any): aiohttp client fixture
mocker(MockerFixture): mocker object
Returns:
TestClient: web client test instance
"""
mocker.patch("pathlib.Path.iterdir", return_value=[])
return event_loop.run_until_complete(aiohttp_client(application_with_auth))
@pytest.fixture
def client_with_oauth_auth(application_with_auth: Application, event_loop: BaseEventLoop, aiohttp_client: Any,
@pytest_asyncio.fixture
async def client_with_auth(application_with_auth: Application, aiohttp_client: Any,
mocker: MockerFixture) -> TestClient:
"""
web client fixture with full authorization functions
Args:
application_with_auth(Application): application fixture
event_loop(BaseEventLoop): context event loop
aiohttp_client(Any): aiohttp client fixture
mocker(MockerFixture): mocker object
Returns:
TestClient: web client test instance
"""
mocker.patch("pathlib.Path.iterdir", return_value=[])
return await aiohttp_client(application_with_auth)
@pytest_asyncio.fixture
async def client_with_oauth_auth(application_with_auth: Application, aiohttp_client: Any,
mocker: MockerFixture) -> TestClient:
"""
web client fixture with full authorization functions
Args:
application_with_auth(Application): application fixture
aiohttp_client(Any): aiohttp client fixture
mocker(MockerFixture): mocker object
@ -219,4 +215,4 @@ def client_with_oauth_auth(application_with_auth: Application, event_loop: BaseE
"""
mocker.patch("pathlib.Path.iterdir", return_value=[])
application_with_auth[AuthKey] = MagicMock(spec=OAuth)
return event_loop.run_until_complete(aiohttp_client(application_with_auth))
return await aiohttp_client(application_with_auth)