style: fix some typos and warnings

This commit is contained in:
Evgenii Alekseev 2024-11-11 18:07:13 +02:00
parent 4b5a645f8d
commit 20e7ba3b1d
20 changed files with 32 additions and 30 deletions

View File

@ -44,7 +44,7 @@ The main functionality of the class is already described, but command is still n
arguments = set_parser arguments = set_parser
In addition, ``ahriman.application.handlers.handler.Handler.ALLOW_MULTI_ARCHITECTURE_RUN`` can be set to ``False`` in order to disable multiprocess run (e.g. in case if there are conflicting operations, like writting to stdout). In addition, ``ahriman.application.handlers.handler.Handler.ALLOW_MULTI_ARCHITECTURE_RUN`` can be set to ``False`` in order to disable multiprocess run (e.g. in case if there are conflicting operations, like writing to stdout).
Save the file above as ``/usr/lib/python3.12/site-packages/ahriman/application/handlers/help_web.py`` (replace ``python3.12`` with actual python version) and you are set. Save the file above as ``/usr/lib/python3.12/site-packages/ahriman/application/handlers/help_web.py`` (replace ``python3.12`` with actual python version) and you are set.

View File

@ -394,7 +394,7 @@ All extracted fields are packed as ``ahriman.models.pkgbuild_patch.PkgbuildPatch
The PKGBUILD class also provides some additional functions on top of that: The PKGBUILD class also provides some additional functions on top of that:
* Ability to extract fields defined inside ``package*()`` functions, which are in particular used for the multipackages. * Ability to extract fields defined inside ``package*()`` functions, which are in particular used for the multi-packages.
* Shell substitution, which supports constructions ``$var`` (including ``${var}``), ``${var#(#)pattern}``, ``${var%(%)pattern}`` and ``${var/(/)pattern/replacement}`` (including ``#pattern`` and ``%pattern``). * Shell substitution, which supports constructions ``$var`` (including ``${var}``), ``${var#(#)pattern}``, ``${var%(%)pattern}`` and ``${var/(/)pattern/replacement}`` (including ``#pattern`` and ``%pattern``).
Additional features Additional features

View File

@ -97,7 +97,7 @@ Otherwise, you would need to pass ``AHRIMAN_PORT`` and mount container network t
Simple server with authentication can be found in `examples <https://github.com/arcan1s/ahriman/tree/master/recipes/web>`__ too. Simple server with authentication can be found in `examples <https://github.com/arcan1s/ahriman/tree/master/recipes/web>`__ too.
Mutli-repository web service Multi-repository web service
"""""""""""""""""""""""""""" """"""""""""""""""""""""""""
Idea is pretty same as to just run web service. However, it is required to run setup commands for each repository, except for one which is specified by ``AHRIMAN_REPOSITORY`` and ``AHRIMAN_ARCHITECTURE`` variables. Idea is pretty same as to just run web service. However, it is required to run setup commands for each repository, except for one which is specified by ``AHRIMAN_REPOSITORY`` and ``AHRIMAN_ARCHITECTURE`` variables.

View File

@ -3,7 +3,7 @@ To 2.16.0
This release replaces ``passlib`` dependency with ``bcrypt``. This release replaces ``passlib`` dependency with ``bcrypt``.
The reason behind this change is that python developers have deprecated and scheduled for removal ``crypt`` module, which is used by ``passlib``. (By the way, they recommend to use ``passlib`` as a replacement.) Unfortunately, it appears that ``passlib`` is unmaintained (see `the issue <https://foss.heptapod.net/python-libs/passlib/-/issues/187>`__), so the only solution is to migrate to anoher library. The reason behind this change is that python developers have deprecated and scheduled for removal ``crypt`` module, which is used by ``passlib``. (By the way, they recommend to use ``passlib`` as a replacement.) Unfortunately, it appears that ``passlib`` is unmaintained (see `the issue <https://foss.heptapod.net/python-libs/passlib/-/issues/187>`__), so the only solution is to migrate to another library.
Because passwords are stored as hashes, it is near to impossible to shadow change passwords in database, the manual intervention is required if: Because passwords are stored as hashes, it is near to impossible to shadow change passwords in database, the manual intervention is required if:

View File

@ -21,7 +21,7 @@ import argparse
from pathlib import Path from pathlib import Path
from pwd import getpwuid from pwd import getpwuid
from urllib.parse import quote_plus as urlencode from urllib.parse import quote_plus as url_encode
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers.handler import Handler, SubParserAction from ahriman.application.handlers.handler import Handler, SubParserAction
@ -174,7 +174,7 @@ class Setup(Handler):
if args.web_unix_socket is not None: if args.web_unix_socket is not None:
unix_socket = str(args.web_unix_socket) unix_socket = str(args.web_unix_socket)
configuration.set_option("web", "unix_socket", unix_socket) configuration.set_option("web", "unix_socket", unix_socket)
configuration.set_option("status", "address", f"http+unix://{urlencode(unix_socket)}") configuration.set_option("status", "address", f"http+unix://{url_encode(unix_socket)}")
if args.generate_salt: if args.generate_salt:
configuration.set_option("auth", "salt", User.generate_password(20)) configuration.set_option("auth", "salt", User.generate_password(20))

View File

@ -146,7 +146,7 @@ class PkgbuildParser(shlex.shlex):
# reset state # reset state
buffer, prefix = [], None buffer, prefix = [], None
# we have already prefix string, so we are in progress of expansion # we have already got prefix string, so we are in progress of expansion
# we always operate the last element, so this matches ",", "next" # we always operate the last element, so this matches ",", "next"
case (PkgbuildToken.Comma, _) if prefix is not None: case (PkgbuildToken.Comma, _) if prefix is not None:
buffer.append(f"{prefix}{second}") buffer.append(f"{prefix}{second}")
@ -168,7 +168,7 @@ class PkgbuildParser(shlex.shlex):
def _is_escaped(self) -> bool: def _is_escaped(self) -> bool:
""" """
check if the last element was quoted. ``shlex.shlex`` parser doesn't provide information about was the token check if the last element was quoted. ``shlex.shlex`` parser doesn't provide information about was the token
quoted or not, thus there is no difference between "'#'" (diez in quotes) and "#" (diez without quotes). This quoted or not, thus there is no difference between "'#'" (sharp in quotes) and "#" (sharp without quotes). This
method simply rolls back to the last non-space character and check if it is a quotation mark method simply rolls back to the last non-space character and check if it is a quotation mark
Returns: Returns:

View File

@ -58,8 +58,8 @@ class EventStatsPrinter(StringPrinter):
mean = statistics.mean(self.events) mean = statistics.mean(self.events)
if len(self.events) > 1: if len(self.events) > 1:
stdev = statistics.stdev(self.events) st_dev = statistics.stdev(self.events)
average = f"{mean:.3f} ± {stdev:.3f}" average = f"{mean:.3f} ± {st_dev:.3f}"
else: else:
average = f"{mean:.3f}" average = f"{mean:.3f}"

View File

@ -19,7 +19,7 @@
# #
import contextlib import contextlib
from urllib.parse import quote_plus as urlencode from urllib.parse import quote_plus as url_encode
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.http import SyncAhrimanClient from ahriman.core.http import SyncAhrimanClient
@ -75,7 +75,7 @@ class WebClient(Client, SyncAhrimanClient):
# legacy-style section # legacy-style section
if (unix_socket := configuration.get("web", "unix_socket", fallback=None)) is not None: if (unix_socket := configuration.get("web", "unix_socket", fallback=None)) is not None:
# special pseudo-protocol which is used for unix sockets # special pseudo-protocol which is used for unix sockets
return "web", f"http+unix://{urlencode(unix_socket)}" return "web", f"http+unix://{url_encode(unix_socket)}"
address = configuration.get("web", "address", fallback=None) address = configuration.get("web", "address", fallback=None)
if not address: if not address:
# build address from host and port directly # build address from host and port directly
@ -94,7 +94,7 @@ class WebClient(Client, SyncAhrimanClient):
Returns: Returns:
str: full url for web service for changes str: full url for web service for changes
""" """
return f"{self.address}/api/v1/packages/{urlencode(package_base)}/changes" return f"{self.address}/api/v1/packages/{url_encode(package_base)}/changes"
def _dependencies_url(self, package_base: str) -> str: def _dependencies_url(self, package_base: str) -> str:
""" """
@ -106,7 +106,7 @@ class WebClient(Client, SyncAhrimanClient):
Returns: Returns:
str: full url for web service for dependencies str: full url for web service for dependencies
""" """
return f"{self.address}/api/v1/packages/{urlencode(package_base)}/dependencies" return f"{self.address}/api/v1/packages/{url_encode(package_base)}/dependencies"
def _events_url(self) -> str: def _events_url(self) -> str:
""" """
@ -127,7 +127,7 @@ class WebClient(Client, SyncAhrimanClient):
Returns: Returns:
str: full url for web service for logs str: full url for web service for logs
""" """
return f"{self.address}/api/v1/packages/{urlencode(package_base)}/logs" return f"{self.address}/api/v1/packages/{url_encode(package_base)}/logs"
def _package_url(self, package_base: str = "") -> str: def _package_url(self, package_base: str = "") -> str:
""" """
@ -139,7 +139,7 @@ class WebClient(Client, SyncAhrimanClient):
Returns: Returns:
str: full url of web service for specific package base str: full url of web service for specific package base
""" """
suffix = f"/{urlencode(package_base)}" if package_base else "" suffix = f"/{url_encode(package_base)}" if package_base else ""
return f"{self.address}/api/v1/packages{suffix}" return f"{self.address}/api/v1/packages{suffix}"
def _patches_url(self, package_base: str, variable: str = "") -> str: def _patches_url(self, package_base: str, variable: str = "") -> str:
@ -153,8 +153,8 @@ class WebClient(Client, SyncAhrimanClient):
Returns: Returns:
str: full url of web service for the package patch str: full url of web service for the package patch
""" """
suffix = f"/{urlencode(variable)}" if variable else "" suffix = f"/{url_encode(variable)}" if variable else ""
return f"{self.address}/api/v1/packages/{urlencode(package_base)}/patches{suffix}" return f"{self.address}/api/v1/packages/{url_encode(package_base)}/patches{suffix}"
def _status_url(self) -> str: def _status_url(self) -> str:
""" """

View File

@ -107,8 +107,8 @@ class Pkgbuild(Mapping[str, Any]):
def __getitem__(self, item: str) -> Any: def __getitem__(self, item: str) -> Any:
""" """
get the field of the PKGBUILD. This method tries to get exact key value if possible; if none found, it tries to get the field of the PKGBUILD. This method tries to get exact key value if possible; if none was found,
fetch function with the same name it tries to fetch function with the same name
Args: Args:
item(str): key name item(str): key name

View File

@ -53,7 +53,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
def test_run_remove(args: argparse.Namespace, configuration: Configuration, repository: Repository, def test_run_remove(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None: package_ahriman: Package, mocker: MockerFixture) -> None:
""" """
must run command and remove packages afterwards must run command and remove packages afterward
""" """
args = _default_args(args) args = _default_args(args)
args.remove = True args.remove = True

View File

@ -191,7 +191,7 @@ def test_extract_packages_by_status(application: Application, mocker: MockerFixt
def test_extract_packages_from_database(application: Application, mocker: MockerFixture) -> None: def test_extract_packages_from_database(application: Application, mocker: MockerFixture) -> None:
""" """
must extract packages from database from database must extract packages from database
""" """
packages_mock = mocker.patch("ahriman.core.database.SQLite.packages_get") packages_mock = mocker.patch("ahriman.core.database.SQLite.packages_get")
Rebuild.extract_packages(application, None, from_database=True) Rebuild.extract_packages(application, None, from_database=True)

View File

@ -5,7 +5,7 @@ from pathlib import Path
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
from typing import Any from typing import Any
from unittest.mock import call as MockCall from unittest.mock import call as MockCall
from urllib.parse import quote_plus as urlencode from urllib.parse import quote_plus as url_encode
from ahriman.application.handlers.setup import Setup from ahriman.application.handlers.setup import Setup
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
@ -148,7 +148,7 @@ def test_configuration_create_ahriman(args: argparse.Namespace, configuration: C
MockCall("web", "port", str(args.web_port)), MockCall("web", "port", str(args.web_port)),
MockCall("status", "address", f"http://127.0.0.1:{str(args.web_port)}"), MockCall("status", "address", f"http://127.0.0.1:{str(args.web_port)}"),
MockCall("web", "unix_socket", str(args.web_unix_socket)), MockCall("web", "unix_socket", str(args.web_unix_socket)),
MockCall("status", "address", f"http+unix://{urlencode(str(args.web_unix_socket))}"), MockCall("status", "address", f"http+unix://{url_encode(str(args.web_unix_socket))}"),
MockCall("auth", "salt", pytest.helpers.anyvar(str, strict=True)), MockCall("auth", "salt", pytest.helpers.anyvar(str, strict=True)),
]) ])
write_mock.assert_called_once_with(pytest.helpers.anyvar(int)) write_mock.assert_called_once_with(pytest.helpers.anyvar(int))

View File

@ -392,7 +392,7 @@ def test_subparsers_package_status_update(parser: argparse.ArgumentParser) -> No
def test_subparsers_package_status_update_option_status(parser: argparse.ArgumentParser) -> None: def test_subparsers_package_status_update_option_status(parser: argparse.ArgumentParser) -> None:
""" """
package-status-update command must convert status option to buildstatusenum instance package-status-update command must convert status option to BuildStatusEnum instance
""" """
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"]) args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"])
assert isinstance(args.status, BuildStatusEnum) assert isinstance(args.status, BuildStatusEnum)

View File

@ -115,7 +115,7 @@ def test_write_skip(lock: Lock) -> None:
def test_write_locked(lock: Lock, mocker: MockerFixture) -> None: def test_write_locked(lock: Lock, mocker: MockerFixture) -> None:
""" """
must raise DuplicateRunError if cannot lock file must raise DuplicateRunError if it cannot lock file
""" """
mocker.patch("ahriman.application.lock.Lock.perform_lock", return_value=False) mocker.patch("ahriman.application.lock.Lock.perform_lock", return_value=False)
with pytest.raises(DuplicateRunError): with pytest.raises(DuplicateRunError):

View File

@ -287,6 +287,7 @@ def local_client(database: SQLite, configuration: Configuration) -> Client:
Args: Args:
database(SQLite): database fixture database(SQLite): database fixture
configuration(Configuration): configuration fixture
Returns: Returns:
Client: local status client test instance Client: local status client test instance

View File

@ -32,6 +32,7 @@ def test_process_build(executor: Executor, package_ahriman: Package, passwd: Any
executor.process_build([package_ahriman], Packagers("packager"), bump_pkgrel=False) executor.process_build([package_ahriman], Packagers("packager"), bump_pkgrel=False)
init_mock.assert_called_once_with(pytest.helpers.anyvar(int), pytest.helpers.anyvar(int), None) init_mock.assert_called_once_with(pytest.helpers.anyvar(int), pytest.helpers.anyvar(int), None)
changes_mock.assert_called_once_with(package_ahriman.base)
depends_on_mock.assert_called_once_with() depends_on_mock.assert_called_once_with()
dependencies_mock.assert_called_once_with(package_ahriman.base, Dependencies()) dependencies_mock.assert_called_once_with(package_ahriman.base, Dependencies())
# must move files (once) # must move files (once)

View File

@ -136,7 +136,7 @@ def test_event_add_failed_http_error(web_client: WebClient, mocker: MockerFixtur
def test_event_add_failed_suppress(web_client: WebClient, mocker: MockerFixture) -> None: def test_event_add_failed_suppress(web_client: WebClient, mocker: MockerFixture) -> None:
""" """
must suppress any exception happened during events creaton and don't log must suppress any exception happened during events creation and don't log
""" """
web_client.suppress_errors = True web_client.suppress_errors = True
mocker.patch("requests.Session.request", side_effect=Exception()) mocker.patch("requests.Session.request", side_effect=Exception())

View File

@ -5,7 +5,7 @@ from ahriman.models.scan_paths import ScanPaths
def test_is_allowed() -> None: def test_is_allowed() -> None:
""" """
must check if path is subpath of one in allowed list must check if path is sub-path of one in allowed list
""" """
assert ScanPaths(["usr"]).is_allowed(Path("usr")) assert ScanPaths(["usr"]).is_allowed(Path("usr"))
assert ScanPaths(["usr"]).is_allowed(Path("usr") / "lib") assert ScanPaths(["usr"]).is_allowed(Path("usr") / "lib")

View File

@ -252,6 +252,6 @@ async def test_username_request(base: BaseView) -> None:
async def test_username_request_exception(base: BaseView) -> None: async def test_username_request_exception(base: BaseView) -> None:
""" """
must not fail in case if cannot read request must not fail in case if it cannot read request
""" """
assert await base.username() is None assert await base.username() is None