mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-06-28 06:41:43 +00:00
Compare commits
4 Commits
feature/br
...
2.18.1
Author | SHA1 | Date | |
---|---|---|---|
7f813cf0c3 | |||
d4eb55ef95 | |||
09350e88ab | |||
2feaa14f46 |
1145
docs/_static/architecture.dot
vendored
1145
docs/_static/architecture.dot
vendored
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
pkgbase='ahriman'
|
pkgbase='ahriman'
|
||||||
pkgname=('ahriman' 'ahriman-core' 'ahriman-triggers' 'ahriman-web')
|
pkgname=('ahriman' 'ahriman-core' 'ahriman-triggers' 'ahriman-web')
|
||||||
pkgver=2.17.1
|
pkgver=2.18.1
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="ArcH linux ReposItory MANager"
|
pkgdesc="ArcH linux ReposItory MANager"
|
||||||
arch=('any')
|
arch=('any')
|
||||||
|
@ -635,6 +635,7 @@ _set_new_action() {
|
|||||||
# ${!x} -> ${hello} -> "world"
|
# ${!x} -> ${hello} -> "world"
|
||||||
_shtab_ahriman() {
|
_shtab_ahriman() {
|
||||||
local completing_word="${COMP_WORDS[COMP_CWORD]}"
|
local completing_word="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
local previous_word="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
local completed_positional_actions
|
local completed_positional_actions
|
||||||
local current_action
|
local current_action
|
||||||
local current_action_args_start_index
|
local current_action_args_start_index
|
||||||
@ -691,6 +692,10 @@ _shtab_ahriman() {
|
|||||||
if [[ $pos_only = 0 && "${completing_word}" == -* ]]; then
|
if [[ $pos_only = 0 && "${completing_word}" == -* ]]; then
|
||||||
# optional argument started: use option strings
|
# optional argument started: use option strings
|
||||||
COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") )
|
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
|
else
|
||||||
# use choices & compgen
|
# use choices & compgen
|
||||||
local IFS=$'\n' # items may contain spaces, so delimit using newline
|
local IFS=$'\n' # items may contain spaces, so delimit using newline
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH AHRIMAN "1" "2025\-01\-05" "ahriman" "Generated Python Manual"
|
.TH AHRIMAN "1" "2025\-06\-16" "ahriman" "Generated Python Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ahriman
|
ahriman
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -17,4 +17,4 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
__version__ = "2.17.1"
|
__version__ = "2.18.1"
|
||||||
|
@ -35,7 +35,7 @@ class Remote(SyncHttpClient):
|
|||||||
>>> package = AUR.info("ahriman")
|
>>> package = AUR.info("ahriman")
|
||||||
>>> search_result = Official.multisearch("pacman", "manager", pacman=pacman)
|
>>> search_result = Official.multisearch("pacman", "manager", pacman=pacman)
|
||||||
|
|
||||||
Differnece between :func:`search()` and :func:`multisearch()` is that :func:`search()` passes all arguments to
|
Difference between :func:`search()` and :func:`multisearch()` is that :func:`search()` passes all arguments to
|
||||||
underlying wrapper directly, whereas :func:`multisearch()` splits search one by one and finds intersection
|
underlying wrapper directly, whereas :func:`multisearch()` splits search one by one and finds intersection
|
||||||
between search results.
|
between search results.
|
||||||
"""
|
"""
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# 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 contextlib
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
@ -87,10 +88,12 @@ class Operations(LazyLogging):
|
|||||||
Returns:
|
Returns:
|
||||||
T: result of the ``query`` call
|
T: result of the ``query`` call
|
||||||
"""
|
"""
|
||||||
with sqlite3.connect(self.path, detect_types=sqlite3.PARSE_DECLTYPES) as connection:
|
with contextlib.closing(sqlite3.connect(self.path, detect_types=sqlite3.PARSE_DECLTYPES)) as connection:
|
||||||
connection.set_trace_callback(self.logger.debug)
|
connection.set_trace_callback(self.logger.debug)
|
||||||
connection.row_factory = self.factory
|
connection.row_factory = self.factory
|
||||||
|
|
||||||
result = query(connection)
|
result = query(connection)
|
||||||
if commit:
|
if commit:
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -40,7 +40,7 @@ class JinjaTemplate:
|
|||||||
|
|
||||||
* homepage - link to homepage, string, optional
|
* homepage - link to homepage, string, optional
|
||||||
* last_update - report generation time, pretty printed datetime, required
|
* last_update - report generation time, pretty printed datetime, required
|
||||||
* link_path - prefix fo packages to download, string, required
|
* link_path - prefix of packages to download, string, required
|
||||||
* has_package_signed - ``True`` in case if package sign enabled, ``False`` otherwise, required
|
* has_package_signed - ``True`` in case if package sign enabled, ``False`` otherwise, required
|
||||||
* has_repo_signed - ``True`` in case if repository database sign enabled, ``False`` otherwise, required
|
* has_repo_signed - ``True`` in case if repository database sign enabled, ``False`` otherwise, required
|
||||||
* packages - sorted list of packages properties, required
|
* packages - sorted list of packages properties, required
|
||||||
@ -64,7 +64,7 @@ class JinjaTemplate:
|
|||||||
Attributes:
|
Attributes:
|
||||||
default_pgp_key(str | None): default PGP key
|
default_pgp_key(str | None): default PGP key
|
||||||
homepage(str | None): homepage link if any (for footer)
|
homepage(str | None): homepage link if any (for footer)
|
||||||
link_path(str): prefix fo packages to download
|
link_path(str): prefix of packages to download
|
||||||
name(str): repository name
|
name(str): repository name
|
||||||
rss_url(str | None): link to the RSS feed
|
rss_url(str | None): link to the RSS feed
|
||||||
sign_targets(set[SignSettings]): targets to sign enabled in configuration
|
sign_targets(set[SignSettings]): targets to sign enabled in configuration
|
||||||
|
@ -71,7 +71,7 @@ class EventLogger:
|
|||||||
>>> with self.in_event(package_base, EventType.PackageUpdated):
|
>>> with self.in_event(package_base, EventType.PackageUpdated):
|
||||||
>>> do_something()
|
>>> do_something()
|
||||||
|
|
||||||
Additional parameter ``failure`` can be set in order to emit an event on exception occured. If none set
|
Additional parameter ``failure`` can be set in order to emit an event on exception occurred. If none set
|
||||||
(default), then no event will be recorded on exception
|
(default), then no event will be recorded on exception
|
||||||
"""
|
"""
|
||||||
with MetricsTimer() as timer:
|
with MetricsTimer() as timer:
|
||||||
|
@ -69,7 +69,7 @@ class Package(LazyLogging):
|
|||||||
:attr:`ahriman.models.package_source.PackageSource.Archive`,
|
:attr:`ahriman.models.package_source.PackageSource.Archive`,
|
||||||
:attr:`ahriman.models.package_source.PackageSource.AUR`,
|
:attr:`ahriman.models.package_source.PackageSource.AUR`,
|
||||||
:attr:`ahriman.models.package_source.PackageSource.Local` and
|
:attr:`ahriman.models.package_source.PackageSource.Local` and
|
||||||
:attr:`ahriman.models.package_source.PackageSource.Repository` repsectively:
|
:attr:`ahriman.models.package_source.PackageSource.Repository` respectively:
|
||||||
|
|
||||||
>>> ahriman_package = Package.from_aur("ahriman")
|
>>> ahriman_package = Package.from_aur("ahriman")
|
||||||
>>> pacman_package = Package.from_official("pacman", pacman)
|
>>> pacman_package = Package.from_official("pacman", pacman)
|
||||||
|
@ -39,7 +39,7 @@ class RemoteSchema(Schema):
|
|||||||
"example": ".",
|
"example": ".",
|
||||||
})
|
})
|
||||||
source = fields.Enum(PackageSource, by_value=True, required=True, metadata={
|
source = fields.Enum(PackageSource, by_value=True, required=True, metadata={
|
||||||
"description": "Pacakge source",
|
"description": "Package source",
|
||||||
})
|
})
|
||||||
web_url = fields.String(metadata={
|
web_url = fields.String(metadata={
|
||||||
"description": "Package repository page",
|
"description": "Package repository page",
|
||||||
|
@ -106,7 +106,7 @@ class PackageView(StatusViewGuard, BaseView):
|
|||||||
@apidocs(
|
@apidocs(
|
||||||
tags=["Packages"],
|
tags=["Packages"],
|
||||||
summary="Update package",
|
summary="Update package",
|
||||||
description="Update package status and set its descriptior optionally",
|
description="Update package status and set its descriptor optionally",
|
||||||
permission=POST_PERMISSION,
|
permission=POST_PERMISSION,
|
||||||
error_400_enabled=True,
|
error_400_enabled=True,
|
||||||
error_404_description="Repository is unknown",
|
error_404_description="Repository is unknown",
|
||||||
|
@ -53,7 +53,7 @@ def test_remote_git_url(remote: Remote) -> None:
|
|||||||
must raise NotImplemented for missing remote git url
|
must raise NotImplemented for missing remote git url
|
||||||
"""
|
"""
|
||||||
with pytest.raises(NotImplementedError):
|
with pytest.raises(NotImplementedError):
|
||||||
remote.remote_git_url("package", "repositorys")
|
remote.remote_git_url("package", "repositories")
|
||||||
|
|
||||||
|
|
||||||
def test_remote_web_url(remote: Remote) -> None:
|
def test_remote_web_url(remote: Remote) -> None:
|
||||||
|
@ -10,7 +10,7 @@ from ahriman.core.exceptions import PacmanError
|
|||||||
|
|
||||||
def test_copy(mocker: MockerFixture) -> None:
|
def test_copy(mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must copy loca database file
|
must copy local database file
|
||||||
"""
|
"""
|
||||||
copy_mock = mocker.patch("shutil.copy")
|
copy_mock = mocker.patch("shutil.copy")
|
||||||
PacmanDatabase.copy(Path("remote"), Path("local"))
|
PacmanDatabase.copy(Path("remote"), Path("local"))
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import pytest
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
@ -24,15 +25,29 @@ def test_factory(database: SQLite) -> None:
|
|||||||
|
|
||||||
def test_with_connection(database: SQLite, mocker: MockerFixture) -> None:
|
def test_with_connection(database: SQLite, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run query inside connection
|
must run query inside connection and close it at the end
|
||||||
"""
|
"""
|
||||||
connection_mock = MagicMock()
|
connection_mock = MagicMock()
|
||||||
connect_mock = mocker.patch("sqlite3.connect", return_value=connection_mock)
|
connect_mock = mocker.patch("sqlite3.connect", return_value=connection_mock)
|
||||||
|
|
||||||
database.with_connection(lambda conn: conn.execute("select 1"))
|
database.with_connection(lambda conn: conn.execute("select 1"))
|
||||||
connect_mock.assert_called_once_with(database.path, detect_types=sqlite3.PARSE_DECLTYPES)
|
connect_mock.assert_called_once_with(database.path, detect_types=sqlite3.PARSE_DECLTYPES)
|
||||||
connection_mock.__enter__().set_trace_callback.assert_called_once_with(database.logger.debug)
|
connection_mock.set_trace_callback.assert_called_once_with(database.logger.debug)
|
||||||
connection_mock.__enter__().commit.assert_not_called()
|
connection_mock.commit.assert_not_called()
|
||||||
|
connection_mock.close.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
|
def test_with_connection_close(database: SQLite, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must close connection on errors
|
||||||
|
"""
|
||||||
|
connection_mock = MagicMock()
|
||||||
|
connection_mock.commit.side_effect = Exception
|
||||||
|
mocker.patch("sqlite3.connect", return_value=connection_mock)
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
database.with_connection(lambda conn: conn.execute("select 1"), commit=True)
|
||||||
|
connection_mock.close.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
def test_with_connection_with_commit(database: SQLite, mocker: MockerFixture) -> None:
|
def test_with_connection_with_commit(database: SQLite, mocker: MockerFixture) -> None:
|
||||||
@ -44,4 +59,4 @@ def test_with_connection_with_commit(database: SQLite, mocker: MockerFixture) ->
|
|||||||
mocker.patch("sqlite3.connect", return_value=connection_mock)
|
mocker.patch("sqlite3.connect", return_value=connection_mock)
|
||||||
|
|
||||||
database.with_connection(lambda conn: conn.execute("select 1"), commit=True)
|
database.with_connection(lambda conn: conn.execute("select 1"), commit=True)
|
||||||
connection_mock.__enter__().commit.assert_called_once_with()
|
connection_mock.commit.assert_called_once_with()
|
||||||
|
@ -285,7 +285,7 @@ def test_set_unknown(client: Client, package_ahriman: Package, mocker: MockerFix
|
|||||||
|
|
||||||
def test_set_unknown_skip(client: Client, package_ahriman: Package, mocker: MockerFixture) -> None:
|
def test_set_unknown_skip(client: Client, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must skip unknown status update in case if pacakge is already known
|
must skip unknown status update in case if package is already known
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.status.Client.package_get", return_value=[(package_ahriman, None)])
|
mocker.patch("ahriman.core.status.Client.package_get", return_value=[(package_ahriman, None)])
|
||||||
update_mock = mocker.patch("ahriman.core.status.Client.package_update")
|
update_mock = mocker.patch("ahriman.core.status.Client.package_update")
|
||||||
|
@ -73,7 +73,7 @@ def test_configuration_sections(configuration: Configuration) -> None:
|
|||||||
|
|
||||||
def test_on_result(trigger: Trigger) -> None:
|
def test_on_result(trigger: Trigger) -> None:
|
||||||
"""
|
"""
|
||||||
must pass execution nto run method
|
must pass execution to run method
|
||||||
"""
|
"""
|
||||||
trigger.on_result(Result(), [])
|
trigger.on_result(Result(), [])
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ from ahriman.models.log_record_id import LogRecordId
|
|||||||
|
|
||||||
def test_init() -> None:
|
def test_init() -> None:
|
||||||
"""
|
"""
|
||||||
must correctly assign proces identifier if not set
|
must correctly assign process identifier if not set
|
||||||
"""
|
"""
|
||||||
assert LogRecordId("1", "2").process_id == LogRecordId.DEFAULT_PROCESS_ID
|
assert LogRecordId("1", "2").process_id == LogRecordId.DEFAULT_PROCESS_ID
|
||||||
assert LogRecordId("1", "2", "3").process_id == "3"
|
assert LogRecordId("1", "2", "3").process_id == "3"
|
||||||
|
Reference in New Issue
Block a user