mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-11-12 19:43:42 +00:00
Compare commits
4 Commits
939a94d889
...
2.19.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 6280c9dbe6 | |||
| 3d1fdd5517 | |||
| ab022071e8 | |||
| a01f76df42 |
@ -140,14 +140,6 @@ ahriman.web.schemas.logs\_schema module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.logs\_search\_schema module
|
||||
-----------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.logs_search_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.oauth2\_schema module
|
||||
-----------------------------------------
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
pkgbase='ahriman'
|
||||
pkgname=('ahriman' 'ahriman-core' 'ahriman-triggers' 'ahriman-web')
|
||||
pkgver=2.19.0
|
||||
pkgver=2.19.1
|
||||
pkgrel=1
|
||||
pkgdesc="ArcH linux ReposItory MANager"
|
||||
arch=('any')
|
||||
|
||||
@ -101,8 +101,6 @@
|
||||
<button id="package-info-update-button" type="submit" class="btn btn-success" onclick="packageInfoUpdate()" data-bs-dismiss="modal"><i class="bi bi-play"></i><span class="d-none d-sm-inline"> update</span></button>
|
||||
<button id="package-info-remove-button" type="submit" class="btn btn-danger" onclick="packageInfoRemove()" data-bs-dismiss="modal"><i class="bi bi-trash"></i><span class="d-none d-sm-inline"> remove</span></button>
|
||||
{% endif %}
|
||||
<input id="package-info-autoreload-button" type="checkbox" class="btn-check" autocomplete="off" onclick="togglePackageInfoAutoReload()" checked>
|
||||
<label for="package-info-autoreload-button" class="btn btn-outline-secondary" title="toggle auto reload"><i class="bi bi-clock"></i></label>
|
||||
<button type="button" class="btn btn-secondary" onclick="showPackageInfo()"><i class="bi bi-arrow-clockwise"></i><span class="d-none d-sm-inline"> reload</span></button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"><i class="bi bi-x"></i><span class="d-none d-sm-inline"> close</span></button>
|
||||
</div>
|
||||
@ -142,9 +140,6 @@
|
||||
|
||||
const packageInfoRefreshInput = document.getElementById("package-info-refresh-input");
|
||||
|
||||
const packageInfoAutoReloadButton = document.getElementById("package-info-autoreload-button");
|
||||
let packageInfoAutoReloadTask = null;
|
||||
|
||||
function clearChart() {
|
||||
packageInfoEventsUpdateChartCanvas.hidden = true;
|
||||
if (packageInfoEventsUpdateChart) {
|
||||
@ -153,13 +148,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function convertLogs(data, filter) {
|
||||
return data
|
||||
.filter((filter || Boolean))
|
||||
.map(log_record => `[${new Date(1000 * log_record.created).toISOString()}] ${log_record.message}`)
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
async function copyChanges() {
|
||||
const changes = packageInfoChangesInput.textContent;
|
||||
await copyToClipboard(changes, packageInfoChangesCopyButton);
|
||||
@ -331,19 +319,15 @@
|
||||
const link = document.createElement("a");
|
||||
link.classList.add("dropdown-item");
|
||||
|
||||
link.dataset.version = version.version;
|
||||
link.dataset.processId = version.process_id;
|
||||
link.dataset.logs = convertLogs(data, log_record => log_record.version === version.version && log_record.process_id === version.process_id);
|
||||
|
||||
link.textContent = new Date(1000 * version.created).toISOStringShort();
|
||||
link.href = "#";
|
||||
link.onclick = _ => {
|
||||
// check if we are at the bottom of the code block
|
||||
const isScrolledToBottom = packageInfoLogsInput.scrollTop + packageInfoLogsInput.clientHeight >= packageInfoLogsInput.scrollHeight;
|
||||
packageInfoLogsInput.textContent = link.dataset.logs;
|
||||
const logs = data
|
||||
.filter(log_record => log_record.version === version.version && log_record.process_id === version.process_id)
|
||||
.map(log_record => `[${new Date(1000 * log_record.created).toISOString()}] ${log_record.message}`);
|
||||
|
||||
packageInfoLogsInput.textContent = logs.join("\n");
|
||||
highlight(packageInfoLogsInput);
|
||||
if (isScrolledToBottom)
|
||||
packageInfoLogsInput.scrollTop = packageInfoLogsInput.scrollHeight; // scroll to the new end
|
||||
|
||||
Array.from(packageInfoLogsVersions.children).forEach(el => el.classList.remove("active"));
|
||||
link.classList.add("active");
|
||||
@ -419,46 +403,23 @@
|
||||
}
|
||||
|
||||
function packageInfoRemove() {
|
||||
const packageBase = packageInfoModal.dataset.package;
|
||||
const packageBase = packageInfoModal.package;
|
||||
packagesRemove([packageBase]);
|
||||
}
|
||||
|
||||
function packageInfoUpdate() {
|
||||
const packageBase = packageInfoModal.dataset.package;
|
||||
const packageBase = packageInfoModal.package;
|
||||
packagesAdd(packageBase, [], repository, {refresh: packageInfoRefreshInput.checked});
|
||||
}
|
||||
|
||||
function reloadActiveLogs(packageBase) {
|
||||
const activeLogSelector = packageInfoLogsVersions.querySelector(".active");
|
||||
|
||||
if (activeLogSelector) {
|
||||
makeRequest(
|
||||
`/api/v2/packages/${packageBase}/logs`,
|
||||
{
|
||||
query: {
|
||||
architecture: repository.architecture,
|
||||
repository: repository.repository,
|
||||
version: activeLogSelector.dataset.version,
|
||||
process_id: activeLogSelector.dataset.processId,
|
||||
},
|
||||
convert: response => response.json(),
|
||||
},
|
||||
data => {
|
||||
activeLogSelector.dataset.logs = convertLogs(data);
|
||||
activeLogSelector.click();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function showPackageInfo(packageBase) {
|
||||
const isPackageBaseSet = packageBase !== undefined;
|
||||
if (isPackageBaseSet) {
|
||||
// set package base as currently used
|
||||
packageInfoModal.dataset.package = packageBase;
|
||||
packageInfoModal.package = packageBase;
|
||||
} else {
|
||||
// read package base from the current window attribute
|
||||
packageBase = packageInfoModal.dataset.package;
|
||||
packageBase = packageInfoModal.package;
|
||||
}
|
||||
|
||||
const onFailure = error => {
|
||||
@ -477,21 +438,6 @@
|
||||
|
||||
if (isPackageBaseSet) {
|
||||
bootstrap.Modal.getOrCreateInstance(packageInfoModal).show();
|
||||
togglePackageInfoAutoReload();
|
||||
}
|
||||
}
|
||||
|
||||
function togglePackageInfoAutoReload() {
|
||||
clearInterval(packageInfoAutoReloadTask);
|
||||
if (packageInfoAutoReloadButton.checked) {
|
||||
packageInfoAutoReloadTask = setInterval(_ => {
|
||||
if (!hasActiveSelection()) {
|
||||
const packageBase = packageInfoModal.dataset.package;
|
||||
// we only poll status and logs here
|
||||
loadPackage(packageBase);
|
||||
reloadActiveLogs(packageBase);
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
@ -522,9 +468,6 @@
|
||||
packageInfoChangesInput.textContent = "";
|
||||
packageInfoEventsTable.bootstrapTable("load", []);
|
||||
clearChart();
|
||||
|
||||
clearInterval(packageInfoAutoReloadTask);
|
||||
packageInfoAutoReloadTask = null; // not really required (?) but lets clear everything
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -58,10 +58,6 @@
|
||||
return value.includes(dataList[index].toLowerCase());
|
||||
}
|
||||
|
||||
function hasActiveSelection() {
|
||||
return !document.getSelection().isCollapsed; // not sure if it is a valid way, but I guess so
|
||||
}
|
||||
|
||||
function headerClass(status) {
|
||||
if (status === "pending") return ["bg-warning"];
|
||||
if (status === "building") return ["bg-warning"];
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
.TH AHRIMAN "1" "2025\-06\-29" "ahriman 2.19.0" "ArcH linux ReposItory MANager"
|
||||
.TH AHRIMAN "1" "2025\-07\-14" "ahriman 2.19.1" "ArcH linux ReposItory MANager"
|
||||
.SH NAME
|
||||
ahriman \- ArcH linux ReposItory MANager
|
||||
.SH SYNOPSIS
|
||||
|
||||
@ -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.19.0"
|
||||
__version__ = "2.19.1"
|
||||
|
||||
@ -267,7 +267,8 @@ class Pacman(LazyLogging):
|
||||
Package: list of packages which were returned by the query
|
||||
"""
|
||||
def is_package_provided(package: Package) -> bool:
|
||||
return package_name in package.provides
|
||||
provides = [trim_package(name) for name in package.provides]
|
||||
return package_name in provides
|
||||
|
||||
for database in self.handle.get_syncdbs():
|
||||
yield from filter(is_package_provided, database.search(package_name))
|
||||
|
||||
@ -146,7 +146,7 @@ class AUR(Remote):
|
||||
# search api provides reduced models
|
||||
for stub in self.package_search(package_name, pacman=pacman, search_by="provides")
|
||||
# verity that found package actually provides it
|
||||
if package_name in (package := self.package_info(stub.package_base, pacman=pacman)).provides
|
||||
if package_name in (package := self.package_info(stub.name, pacman=pacman)).provides
|
||||
]
|
||||
|
||||
def package_search(self, *keywords: str, pacman: Pacman | None, search_by: str | None) -> list[AURPackage]:
|
||||
|
||||
@ -203,6 +203,8 @@ def migrate_package_repository(connection: Connection, configuration: Configurat
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
_, repository_id = configuration.check_loaded()
|
||||
if repository_id.is_empty:
|
||||
return # no repository available yet
|
||||
|
||||
connection.execute("""update build_queue set repository = :repository""", {"repository": repository_id.id})
|
||||
connection.execute("""update package_bases set repository = :repository""", {"repository": repository_id.id})
|
||||
|
||||
@ -29,15 +29,13 @@ class LogsOperations(Operations):
|
||||
logs operations
|
||||
"""
|
||||
|
||||
def logs_get(self, package_base: str, version: str | None = None, process_id: str | None = None,
|
||||
limit: int = -1, offset: int = 0, repository_id: RepositoryId | None = None) -> list[LogRecord]:
|
||||
def logs_get(self, package_base: str, limit: int = -1, offset: int = 0,
|
||||
repository_id: RepositoryId | None = None) -> list[LogRecord]:
|
||||
"""
|
||||
extract logs for specified package base
|
||||
|
||||
Args:
|
||||
package_base(str): package base to extract logs
|
||||
version(str | None, optional): package version to filter (Default value = None)
|
||||
process_id(str | None, optional): process identifier to filter (Default value = None)
|
||||
limit(int, optional): limit records to the specified count, -1 means unlimited (Default value = -1)
|
||||
offset(int, optional): records offset (Default value = 0)
|
||||
repository_id(RepositoryId, optional): repository unique identifier override (Default value = None)
|
||||
@ -54,17 +52,12 @@ class LogsOperations(Operations):
|
||||
"""
|
||||
select created, message, version, process_id from (
|
||||
select * from logs
|
||||
where package_base = :package_base
|
||||
and repository = :repository
|
||||
and (:version is null or version = :version)
|
||||
and (:process_id is null or process_id = :process_id)
|
||||
where package_base = :package_base and repository = :repository
|
||||
order by created desc limit :limit offset :offset
|
||||
) order by created asc
|
||||
""",
|
||||
{
|
||||
"package_base": package_base,
|
||||
"version": version,
|
||||
"process_id": process_id,
|
||||
"repository": repository_id.id,
|
||||
"limit": limit,
|
||||
"offset": offset,
|
||||
|
||||
@ -72,8 +72,8 @@ class SyncHttpClient(LazyLogging):
|
||||
"""
|
||||
session = requests.Session()
|
||||
python_version = ".".join(map(str, sys.version_info[:3])) # just major.minor.patch
|
||||
session.headers["User-Agent"] = f"ahriman/{__version__}" \
|
||||
f"{requests.utils.default_user_agent()}" \
|
||||
session.headers["User-Agent"] = f"ahriman/{__version__} " \
|
||||
f"{requests.utils.default_user_agent()} " \
|
||||
f"python/{python_version}"
|
||||
|
||||
return session
|
||||
|
||||
@ -203,15 +203,12 @@ class Client:
|
||||
"""
|
||||
# this method does not raise NotImplementedError because it is actively used as dummy client for http log
|
||||
|
||||
def package_logs_get(self, package_base: str, version: str | None = None, process_id: str | None = None,
|
||||
limit: int = -1, offset: int = 0) -> list[LogRecord]:
|
||||
def package_logs_get(self, package_base: str, limit: int = -1, offset: int = 0) -> list[LogRecord]:
|
||||
"""
|
||||
get package logs
|
||||
|
||||
Args:
|
||||
package_base(str): package base
|
||||
version(str | None, optional): package version to search (Default value = None)
|
||||
process_id(str | None, optional): process identifier to search (Default value = None)
|
||||
limit(int, optional): limit records to the specified count, -1 means unlimited (Default value = -1)
|
||||
offset(int, optional): records offset (Default value = 0)
|
||||
|
||||
|
||||
@ -152,22 +152,19 @@ class LocalClient(Client):
|
||||
"""
|
||||
self.database.logs_insert(log_record, self.repository_id)
|
||||
|
||||
def package_logs_get(self, package_base: str, version: str | None = None, process_id: str | None = None,
|
||||
limit: int = -1, offset: int = 0) -> list[LogRecord]:
|
||||
def package_logs_get(self, package_base: str, limit: int = -1, offset: int = 0) -> list[LogRecord]:
|
||||
"""
|
||||
get package logs
|
||||
|
||||
Args:
|
||||
package_base(str): package base
|
||||
version(str | None, optional): package version to search (Default value = None)
|
||||
process_id(str | None, optional): process identifier to search (Default value = None)
|
||||
limit(int, optional): limit records to the specified count, -1 means unlimited (Default value = -1)
|
||||
offset(int, optional): records offset (Default value = 0)
|
||||
|
||||
Returns:
|
||||
list[LogRecord]: package logs
|
||||
"""
|
||||
return self.database.logs_get(package_base, version, process_id, limit, offset, self.repository_id)
|
||||
return self.database.logs_get(package_base, limit, offset, self.repository_id)
|
||||
|
||||
def package_logs_remove(self, package_base: str, version: str | None) -> None:
|
||||
"""
|
||||
|
||||
@ -109,7 +109,7 @@ class Watcher(LazyLogging):
|
||||
|
||||
package_logs_add: Callable[[LogRecord], None]
|
||||
|
||||
package_logs_get: Callable[[str, str | None, str | None, int, int], list[LogRecord]]
|
||||
package_logs_get: Callable[[str, int, int], list[LogRecord]]
|
||||
|
||||
package_logs_remove: Callable[[str, str | None], None]
|
||||
|
||||
|
||||
@ -326,15 +326,12 @@ class WebClient(Client, SyncAhrimanClient):
|
||||
self.make_request("POST", self._logs_url(log_record.log_record_id.package_base),
|
||||
params=self.repository_id.query(), json=payload, suppress_errors=True)
|
||||
|
||||
def package_logs_get(self, package_base: str, version: str | None = None, process_id: str | None = None,
|
||||
limit: int = -1, offset: int = 0) -> list[LogRecord]:
|
||||
def package_logs_get(self, package_base: str, limit: int = -1, offset: int = 0) -> list[LogRecord]:
|
||||
"""
|
||||
get package logs
|
||||
|
||||
Args:
|
||||
package_base(str): package base
|
||||
version(str | None, optional): package version to search (Default value = None)
|
||||
process_id(str | None, optional): process identifier to search (Default value = None)
|
||||
limit(int, optional): limit records to the specified count, -1 means unlimited (Default value = -1)
|
||||
offset(int, optional): records offset (Default value = 0)
|
||||
|
||||
@ -342,10 +339,6 @@ class WebClient(Client, SyncAhrimanClient):
|
||||
list[LogRecord]: package logs
|
||||
"""
|
||||
query = self.repository_id.query() + [("limit", str(limit)), ("offset", str(offset))]
|
||||
if version is not None:
|
||||
query.append(("version", version))
|
||||
if process_id is not None:
|
||||
query.append(("process_id", process_id))
|
||||
|
||||
with contextlib.suppress(Exception):
|
||||
response = self.make_request("GET", self._logs_url(package_base), params=query)
|
||||
|
||||
@ -25,7 +25,7 @@ from dataclasses import dataclass, field, fields
|
||||
from pyalpm import Package # type: ignore[import-not-found]
|
||||
from typing import Any, Self
|
||||
|
||||
from ahriman.core.utils import filter_json, full_version
|
||||
from ahriman.core.utils import filter_json, full_version, trim_package
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
@ -103,6 +103,17 @@ class AURPackage:
|
||||
keywords: list[str] = field(default_factory=list)
|
||||
groups: list[str] = field(default_factory=list)
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""
|
||||
update packages lists accordingly
|
||||
"""
|
||||
object.__setattr__(self, "depends", [trim_package(package) for package in self.depends])
|
||||
object.__setattr__(self, "make_depends", [trim_package(package) for package in self.make_depends])
|
||||
object.__setattr__(self, "opt_depends", [trim_package(package) for package in self.opt_depends])
|
||||
object.__setattr__(self, "check_depends", [trim_package(package) for package in self.check_depends])
|
||||
object.__setattr__(self, "conflicts", [trim_package(package) for package in self.conflicts])
|
||||
object.__setattr__(self, "provides", [trim_package(package) for package in self.provides])
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, dump: dict[str, Any]) -> Self:
|
||||
"""
|
||||
|
||||
@ -83,12 +83,13 @@ class PackageDescription:
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""
|
||||
update dependencies list accordingly
|
||||
update packages lists accordingly
|
||||
"""
|
||||
self.depends = [trim_package(package) for package in self.depends]
|
||||
self.opt_depends = [trim_package(package) for package in self.opt_depends]
|
||||
self.make_depends = [trim_package(package) for package in self.make_depends]
|
||||
self.opt_depends = [trim_package(package) for package in self.opt_depends]
|
||||
self.check_depends = [trim_package(package) for package in self.check_depends]
|
||||
self.provides = [trim_package(package) for package in self.provides]
|
||||
|
||||
@property
|
||||
def filepath(self) -> Path | None:
|
||||
|
||||
@ -34,7 +34,6 @@ from ahriman.web.schemas.log_schema import LogSchema
|
||||
from ahriman.web.schemas.login_schema import LoginSchema
|
||||
from ahriman.web.schemas.logs_rotate_schema import LogsRotateSchema
|
||||
from ahriman.web.schemas.logs_schema import LogsSchema
|
||||
from ahriman.web.schemas.logs_search_schema import LogsSearchSchema
|
||||
from ahriman.web.schemas.oauth2_schema import OAuth2Schema
|
||||
from ahriman.web.schemas.package_name_schema import PackageNameSchema
|
||||
from ahriman.web.schemas.package_names_schema import PackageNamesSchema
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 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/>.
|
||||
#
|
||||
from ahriman import __version__
|
||||
from ahriman.web.apispec import fields
|
||||
from ahriman.web.schemas.pagination_schema import PaginationSchema
|
||||
|
||||
|
||||
class LogsSearchSchema(PaginationSchema):
|
||||
"""
|
||||
request log search schema
|
||||
"""
|
||||
|
||||
version = fields.String(metadata={
|
||||
"description": "Package version to search",
|
||||
"example": __version__,
|
||||
})
|
||||
process_id = fields.String(metadata={
|
||||
"description": "Process unique identifier to search",
|
||||
})
|
||||
@ -90,7 +90,7 @@ class LogsView(StatusViewGuard, BaseView):
|
||||
|
||||
try:
|
||||
_, status = self.service().package_get(package_base)
|
||||
logs = self.service(package_base=package_base).package_logs_get(package_base, None, None, -1, 0)
|
||||
logs = self.service(package_base=package_base).package_logs_get(package_base, -1, 0)
|
||||
except UnknownPackageError:
|
||||
raise HTTPNotFound(reason=f"Package {package_base} is unknown")
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ from typing import ClassVar
|
||||
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.apispec.decorators import apidocs
|
||||
from ahriman.web.schemas import LogSchema, LogsSearchSchema, PackageNameSchema
|
||||
from ahriman.web.schemas import LogSchema, PackageNameSchema, PaginationSchema
|
||||
from ahriman.web.views.base import BaseView
|
||||
from ahriman.web.views.status_view_guard import StatusViewGuard
|
||||
|
||||
@ -47,7 +47,7 @@ class LogsView(StatusViewGuard, BaseView):
|
||||
error_404_description="Package base and/or repository are unknown",
|
||||
schema=LogSchema(many=True),
|
||||
match_schema=PackageNameSchema,
|
||||
query_schema=LogsSearchSchema,
|
||||
query_schema=PaginationSchema,
|
||||
)
|
||||
async def get(self) -> Response:
|
||||
"""
|
||||
@ -61,10 +61,8 @@ class LogsView(StatusViewGuard, BaseView):
|
||||
"""
|
||||
package_base = self.request.match_info["package"]
|
||||
limit, offset = self.page()
|
||||
version = self.request.query.get("version", None)
|
||||
process = self.request.query.get("process_id", None)
|
||||
|
||||
logs = self.service(package_base=package_base).package_logs_get(package_base, version, process, limit, offset)
|
||||
logs = self.service(package_base=package_base).package_logs_get(package_base, limit, offset)
|
||||
|
||||
response = [log_record.view() for log_record in logs]
|
||||
return json_response(response)
|
||||
|
||||
@ -289,3 +289,4 @@ def test_package_provided_by(pacman: Pacman) -> None:
|
||||
must search through the provides lists
|
||||
"""
|
||||
assert list(pacman.provided_by("sh"))
|
||||
assert list(pacman.provided_by("libacl.so")) # case with exact version
|
||||
|
||||
@ -6,6 +6,7 @@ from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database.migrations.m011_repository_name import migrate_data, migrate_package_repository, steps
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
def test_migration_repository_name() -> None:
|
||||
@ -37,3 +38,13 @@ def test_migrate_package_repository(connection: Connection, configuration: Confi
|
||||
MockCall(pytest.helpers.anyvar(str, strict=True), {"repository": configuration.repository_id.id}),
|
||||
MockCall(pytest.helpers.anyvar(str, strict=True), {"repository": configuration.repository_id.id}),
|
||||
])
|
||||
|
||||
|
||||
def test_migrate_package_repository_empty_id(connection: Connection, configuration: Configuration,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must do nothing on empty repository id
|
||||
"""
|
||||
mocker.patch("ahriman.core.configuration.Configuration.check_loaded", return_value=("", RepositoryId("", "")))
|
||||
migrate_package_repository(connection, configuration)
|
||||
connection.execute.assert_not_called()
|
||||
|
||||
@ -71,35 +71,11 @@ def test_logs_insert_get_pagination(database: SQLite, package_ahriman: Package)
|
||||
"""
|
||||
database.logs_insert(LogRecord(LogRecordId(package_ahriman.base, "1"), 42.0, "message 1"))
|
||||
database.logs_insert(LogRecord(LogRecordId(package_ahriman.base, "1"), 43.0, "message 2"))
|
||||
assert database.logs_get(package_ahriman.base, None, None, 1, 1) == [
|
||||
assert database.logs_get(package_ahriman.base, 1, 1) == [
|
||||
LogRecord(LogRecordId(package_ahriman.base, "1"), 42.0, "message 1"),
|
||||
]
|
||||
|
||||
|
||||
def test_logs_insert_get_filter_by_version(database: SQLite, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must insert and get package logs with pagination
|
||||
"""
|
||||
database.logs_insert(LogRecord(LogRecordId(package_ahriman.base, "1", "p1"), 42.0, "message 1"))
|
||||
database.logs_insert(LogRecord(LogRecordId(package_ahriman.base, "1", "p2"), 43.0, "message 2"))
|
||||
database.logs_insert(LogRecord(LogRecordId(package_ahriman.base, "2", "p1"), 44.0, "message 3"))
|
||||
|
||||
assert database.logs_get(package_ahriman.base, "1", None) == [
|
||||
LogRecord(LogRecordId(package_ahriman.base, "1", "p1"), 42.0, "message 1"),
|
||||
LogRecord(LogRecordId(package_ahriman.base, "1", "p2"), 43.0, "message 2"),
|
||||
]
|
||||
assert database.logs_get(package_ahriman.base, "2", None) == [
|
||||
LogRecord(LogRecordId(package_ahriman.base, "2", "p1"), 44.0, "message 3"),
|
||||
]
|
||||
assert database.logs_get(package_ahriman.base, None, "p1") == [
|
||||
LogRecord(LogRecordId(package_ahriman.base, "1", "p1"), 42.0, "message 1"),
|
||||
LogRecord(LogRecordId(package_ahriman.base, "2", "p1"), 44.0, "message 3"),
|
||||
]
|
||||
assert database.logs_get(package_ahriman.base, "1", "p1") == [
|
||||
LogRecord(LogRecordId(package_ahriman.base, "1", "p1"), 42.0, "message 1"),
|
||||
]
|
||||
|
||||
|
||||
def test_logs_insert_get_multi(database: SQLite, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must insert and get package logs for multiple repositories
|
||||
|
||||
@ -124,9 +124,8 @@ def test_package_logs_get(local_client: LocalClient, package_ahriman: Package, m
|
||||
must retrieve package logs
|
||||
"""
|
||||
logs_mock = mocker.patch("ahriman.core.database.SQLite.logs_get")
|
||||
local_client.package_logs_get(package_ahriman.base, package_ahriman.version, "process", 1, 2)
|
||||
logs_mock.assert_called_once_with(package_ahriman.base, package_ahriman.version, "process", 1, 2,
|
||||
local_client.repository_id)
|
||||
local_client.package_logs_get(package_ahriman.base, 1, 2)
|
||||
logs_mock.assert_called_once_with(package_ahriman.base, 1, 2, local_client.repository_id)
|
||||
|
||||
|
||||
def test_package_logs_remove(local_client: LocalClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
|
||||
@ -658,7 +658,7 @@ def test_package_logs_get(web_client: WebClient, package_ahriman: Package, mocke
|
||||
|
||||
requests_mock = mocker.patch("ahriman.core.status.web_client.WebClient.make_request", return_value=response_obj)
|
||||
|
||||
result = web_client.package_logs_get(package_ahriman.base, None, None, 1, 2)
|
||||
result = web_client.package_logs_get(package_ahriman.base, 1, 2)
|
||||
requests_mock.assert_called_once_with("GET", pytest.helpers.anyvar(str, True),
|
||||
params=web_client.repository_id.query() + [("limit", "1"), ("offset", "2")])
|
||||
assert result == [
|
||||
@ -666,21 +666,6 @@ def test_package_logs_get(web_client: WebClient, package_ahriman: Package, mocke
|
||||
]
|
||||
|
||||
|
||||
def test_package_logs_get_filter(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must get logs with version and process id filter
|
||||
"""
|
||||
requests_mock = mocker.patch("ahriman.core.status.web_client.WebClient.make_request")
|
||||
web_client.package_logs_get(package_ahriman.base, package_ahriman.version, LogRecordId.DEFAULT_PROCESS_ID, 1, 2)
|
||||
requests_mock.assert_called_once_with("GET", pytest.helpers.anyvar(str, True),
|
||||
params=web_client.repository_id.query() + [
|
||||
("limit", "1"),
|
||||
("offset", "2"),
|
||||
("version", package_ahriman.version),
|
||||
("process_id", LogRecordId.DEFAULT_PROCESS_ID),
|
||||
])
|
||||
|
||||
|
||||
def test_package_logs_get_failed(web_client: WebClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must suppress any exception happened during logs fetch
|
||||
|
||||
@ -2,7 +2,7 @@ import datetime
|
||||
import json
|
||||
import pyalpm # typing: ignore
|
||||
|
||||
from dataclasses import asdict, fields
|
||||
from dataclasses import asdict, fields, replace
|
||||
from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from typing import Any
|
||||
@ -38,6 +38,25 @@ def _get_official_data(resource_path_root: Path) -> dict[str, Any]:
|
||||
return json.loads(response)["results"][0]
|
||||
|
||||
|
||||
def test_post_init(aur_package_ahriman: AURPackage) -> None:
|
||||
"""
|
||||
must trim versions and descriptions from packages list
|
||||
"""
|
||||
package = replace(
|
||||
aur_package_ahriman,
|
||||
depends=["a=1"],
|
||||
make_depends=["b>=3"],
|
||||
opt_depends=["c: a description"],
|
||||
check_depends=["d=4"],
|
||||
provides=["e=5"],
|
||||
)
|
||||
assert package.depends == ["a"]
|
||||
assert package.make_depends == ["b"]
|
||||
assert package.opt_depends == ["c"]
|
||||
assert package.check_depends == ["d"]
|
||||
assert package.provides == ["e"]
|
||||
|
||||
|
||||
def test_from_json(aur_package_ahriman: AURPackage, resource_path_root: Path) -> None:
|
||||
"""
|
||||
must load package from json
|
||||
|
||||
@ -6,10 +6,15 @@ from ahriman.models.package_description import PackageDescription
|
||||
|
||||
def test_post_init() -> None:
|
||||
"""
|
||||
must trim versions and descriptions from dependencies list
|
||||
must trim versions and descriptions from packages list
|
||||
"""
|
||||
assert PackageDescription(depends=["a=1"], make_depends=["b>=3"], opt_depends=["c: a description"]) == \
|
||||
PackageDescription(depends=["a"], make_depends=["b"], opt_depends=["c"])
|
||||
assert PackageDescription(
|
||||
depends=["a=1"],
|
||||
make_depends=["b>=3"],
|
||||
opt_depends=["c: a description"],
|
||||
check_depends=["d=4"],
|
||||
provides=["e=5"]
|
||||
) == PackageDescription(depends=["a"], make_depends=["b"], opt_depends=["c"], check_depends=["d"], provides=["e"])
|
||||
|
||||
|
||||
def test_filepath(package_description_ahriman: PackageDescription) -> None:
|
||||
|
||||
@ -1 +0,0 @@
|
||||
# schema testing goes in view class tests
|
||||
@ -86,31 +86,6 @@ async def test_get_with_pagination(client: TestClient, package_ahriman: Package)
|
||||
]
|
||||
|
||||
|
||||
async def test_get_with_filter(client: TestClient, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must get logs with filter by version and process identifier
|
||||
"""
|
||||
await client.post(f"/api/v1/packages/{package_ahriman.base}",
|
||||
json={"status": BuildStatusEnum.Success.value, "package": package_ahriman.view()})
|
||||
await client.post(f"/api/v1/packages/{package_ahriman.base}/logs",
|
||||
json={"created": 42.0, "message": "message 1", "version": "42"})
|
||||
await client.post(f"/api/v1/packages/{package_ahriman.base}/logs",
|
||||
json={"created": 43.0, "message": "message 2", "version": "43"})
|
||||
request_schema = pytest.helpers.schema_request(LogsView.get, location="querystring")
|
||||
response_schema = pytest.helpers.schema_response(LogsView.get)
|
||||
|
||||
payload = {"version": "42", "process_id": LogRecordId.DEFAULT_PROCESS_ID}
|
||||
assert not request_schema.validate(payload)
|
||||
response = await client.get(f"/api/v2/packages/{package_ahriman.base}/logs", params=payload)
|
||||
assert response.status == 200
|
||||
|
||||
logs = await response.json()
|
||||
assert not response_schema.validate(logs)
|
||||
assert logs == [
|
||||
{"created": 42.0, "message": "message 1", "version": "42", "process_id": LogRecordId.DEFAULT_PROCESS_ID},
|
||||
]
|
||||
|
||||
|
||||
async def test_get_bad_request(client: TestClient, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must return bad request for invalid query parameters
|
||||
|
||||
Reference in New Issue
Block a user