small improvements on code smell

* fix some grammar/typo errors
* change some statements to be more clear
* use pattern matching for enum processing
This commit is contained in:
Evgenii Alekseev 2023-08-23 18:02:45 +03:00
parent 477c473187
commit f6081507c0
32 changed files with 204 additions and 174 deletions

View File

@ -86,7 +86,7 @@ def _parser() -> argparse.ArgumentParser:
action="store_true") action="store_true")
parser.add_argument("--wait-timeout", help="wait for lock to be free. Negative value will lead to " parser.add_argument("--wait-timeout", help="wait for lock to be free. Negative value will lead to "
"immediate application run even if there is lock file. " "immediate application run even if there is lock file. "
"In case of zero value, tthe application will wait infinitely", "In case of zero value, the application will wait infinitely",
type=int, default=-1) type=int, default=-1)
parser.add_argument("-V", "--version", action="version", version=__version__) parser.add_argument("-V", "--version", action="version", version=__version__)

View File

@ -117,7 +117,6 @@ class ApplicationPackages(ApplicationProperties):
Raises: Raises:
UnknownPackageError: if specified package is unknown or doesn't exist UnknownPackageError: if specified package is unknown or doesn't exist
""" """
dst = self.repository.paths.packages / Path(source).name # URL is path, is not it?
# timeout=None to suppress pylint warns. Also suppress bandit warnings # timeout=None to suppress pylint warns. Also suppress bandit warnings
try: try:
response = requests.get(source, stream=True, timeout=None) # nosec response = requests.get(source, stream=True, timeout=None) # nosec
@ -125,6 +124,7 @@ class ApplicationPackages(ApplicationProperties):
except Exception: except Exception:
raise UnknownPackageError(source) raise UnknownPackageError(source)
dst = self.repository.paths.packages / Path(source).name # URL is path, is not it?
with dst.open("wb") as local_file: with dst.open("wb") as local_file:
for chunk in response.iter_content(chunk_size=1024): for chunk in response.iter_content(chunk_size=1024):
local_file.write(chunk) local_file.write(chunk)

View File

@ -94,10 +94,13 @@ class Handler:
""" """
try: try:
configuration = Configuration.from_path(args.configuration, architecture) configuration = Configuration.from_path(args.configuration, architecture)
log_handler = Log.handler(args.log_handler) log_handler = Log.handler(args.log_handler)
Log.load(configuration, log_handler, quiet=args.quiet, report=args.report) Log.load(configuration, log_handler, quiet=args.quiet, report=args.report)
with Lock(args, architecture, configuration): with Lock(args, architecture, configuration):
cls.run(args, architecture, configuration, report=args.report) cls.run(args, architecture, configuration, report=args.report)
return True return True
except ExitCode: except ExitCode:
return False return False
@ -128,8 +131,7 @@ class Handler:
raise MultipleArchitecturesError(args.command) raise MultipleArchitecturesError(args.command)
with Pool(len(architectures)) as pool: with Pool(len(architectures)) as pool:
result = pool.starmap( result = pool.starmap(cls.call, [(args, architecture) for architecture in architectures])
cls.call, [(args, architecture) for architecture in architectures])
else: else:
result = [cls.call(args, architectures.pop())] result = [cls.call(args, architectures.pop())]

View File

@ -51,16 +51,17 @@ class Patch(Handler):
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report)
application.on_start() application.on_start()
if args.action == Action.Update and args.variable is not None: match args.action:
patch = Patch.patch_create_from_function(args.variable, args.patch) case Action.Update if args.variable is not None:
Patch.patch_set_create(application, args.package, patch) patch = Patch.patch_create_from_function(args.variable, args.patch)
elif args.action == Action.Update and args.variable is None: Patch.patch_set_create(application, args.package, patch)
package_base, patch = Patch.patch_create_from_diff(args.package, architecture, args.track) case Action.Update:
Patch.patch_set_create(application, package_base, patch) package_base, patch = Patch.patch_create_from_diff(args.package, architecture, args.track)
elif args.action == Action.List: Patch.patch_set_create(application, package_base, patch)
Patch.patch_set_list(application, args.package, args.variable, args.exit_code) case Action.List:
elif args.action == Action.Remove: Patch.patch_set_list(application, args.package, args.variable, args.exit_code)
Patch.patch_set_remove(application, args.package, args.variable) case Action.Remove:
Patch.patch_set_remove(application, args.package, args.variable)
@staticmethod @staticmethod
def patch_create_from_diff(sources_dir: Path, architecture: str, track: list[str]) -> tuple[str, PkgbuildPatch]: def patch_create_from_diff(sources_dir: Path, architecture: str, track: list[str]) -> tuple[str, PkgbuildPatch]:

View File

@ -48,7 +48,7 @@ class ServiceUpdates(Handler):
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report)
remote = Package.from_aur("ahriman", application.repository.pacman, None) remote = Package.from_aur("ahriman", application.repository.pacman, None)
release = remote.version.rsplit("-", 1)[-1] # we don't store pkgrel locally, so we just append it _, release = remote.version.rsplit("-", 1) # we don't store pkgrel locally, so we just append it
local_version = f"{__version__}-{release}" local_version = f"{__version__}-{release}"
# technically we would like to compare versions, but it is fine to raise an exception in case if locally # technically we would like to compare versions, but it is fine to raise an exception in case if locally

View File

@ -46,13 +46,14 @@ class StatusUpdate(Handler):
# we are using reporter here # we are using reporter here
client = Application(architecture, configuration, report=True).repository.reporter client = Application(architecture, configuration, report=True).repository.reporter
if args.action == Action.Update and args.package: match args.action:
# update packages statuses case Action.Update if args.package:
for package in args.package: # update packages statuses
client.package_update(package, args.status) for package in args.package:
elif args.action == Action.Update: client.package_update(package, args.status)
# update service status case Action.Update:
client.status_update(args.status) # update service status
elif args.action == Action.Remove: client.status_update(args.status)
for package in args.package: case Action.Remove:
client.package_remove(package) for package in args.package:
client.package_remove(package)

View File

@ -49,18 +49,19 @@ class Users(Handler):
""" """
database = SQLite.load(configuration) database = SQLite.load(configuration)
if args.action == Action.Update: match args.action:
user = Users.user_create(args) case Action.Update:
# if password is left blank we are not going to require salt to be set user = Users.user_create(args)
salt = configuration.get("auth", "salt", fallback="") if user.password else "" # if password is left blank we are not going to require salt to be set
database.user_update(user.hash_password(salt)) salt = configuration.get("auth", "salt", fallback="") if user.password else ""
elif args.action == Action.List: database.user_update(user.hash_password(salt))
users = database.user_list(args.username, args.role) case Action.List:
Users.check_if_empty(args.exit_code, not users) users = database.user_list(args.username, args.role)
for user in users: Users.check_if_empty(args.exit_code, not users)
UserPrinter(user).print(verbose=True) for user in users:
elif args.action == Action.Remove: UserPrinter(user).print(verbose=True)
database.user_remove(args.username) case Action.Remove:
database.user_remove(args.username)
@staticmethod @staticmethod
def user_create(args: argparse.Namespace) -> User: def user_create(args: argparse.Namespace) -> User:

View File

@ -49,6 +49,16 @@ class Pacman(LazyLogging):
self.__create_handle_fn: Callable[[], Handle] = lambda: self.__create_handle( self.__create_handle_fn: Callable[[], Handle] = lambda: self.__create_handle(
architecture, configuration, refresh_database=refresh_database) architecture, configuration, refresh_database=refresh_database)
@cached_property
def handle(self) -> Handle:
"""
pyalpm handle
Returns:
Handle: generated pyalpm handle instance
"""
return self.__create_handle_fn()
def __create_handle(self, architecture: str, configuration: Configuration, *, def __create_handle(self, architecture: str, configuration: Configuration, *,
refresh_database: PacmanSynchronization) -> Handle: refresh_database: PacmanSynchronization) -> Handle:
""" """
@ -79,16 +89,6 @@ class Pacman(LazyLogging):
return handle return handle
@cached_property
def handle(self) -> Handle:
"""
pyalpm handle
Returns:
Handle: generated pyalpm handle instance
"""
return self.__create_handle_fn()
def database_copy(self, handle: Handle, database: DB, pacman_root: Path, paths: RepositoryPaths, *, def database_copy(self, handle: Handle, database: DB, pacman_root: Path, paths: RepositoryPaths, *,
use_ahriman_cache: bool) -> None: use_ahriman_cache: bool) -> None:
""" """
@ -116,7 +116,7 @@ class Pacman(LazyLogging):
src = repository_database(pacman_root) src = repository_database(pacman_root)
if not src.is_file(): if not src.is_file():
self.logger.warning("repository %s is set to be used, however, no working copy was found", database.name) self.logger.warning("repository %s is set to be used, however, no working copy was found", database.name)
return # database for some reasons deos not exist return # database for some reason deos not exist
self.logger.info("copy pacman database from operating system root to ahriman's home") self.logger.info("copy pacman database from operating system root to ahriman's home")
shutil.copy(src, dst) shutil.copy(src, dst)
paths.chown(dst) paths.chown(dst)

View File

@ -74,14 +74,15 @@ class Auth(LazyLogging):
Returns: Returns:
Auth: authorization module according to current settings Auth: authorization module according to current settings
""" """
provider = AuthSettings.from_option(configuration.get("auth", "target", fallback="disabled")) match AuthSettings.from_option(configuration.get("auth", "target", fallback="disabled")):
if provider == AuthSettings.Configuration: case AuthSettings.Configuration:
from ahriman.core.auth.mapping import Mapping from ahriman.core.auth.mapping import Mapping
return Mapping(configuration, database) return Mapping(configuration, database)
if provider == AuthSettings.OAuth: case AuthSettings.OAuth:
from ahriman.core.auth.oauth import OAuth from ahriman.core.auth.oauth import OAuth
return OAuth(configuration, database) return OAuth(configuration, database)
return Auth(configuration) case _:
return Auth(configuration)
async def check_credentials(self, username: str | None, password: str | None) -> bool: async def check_credentials(self, username: str | None, password: str | None) -> bool:
""" """

View File

@ -28,8 +28,8 @@ from ahriman.models.auth_settings import AuthSettings
class OAuth(Mapping): class OAuth(Mapping):
""" """
OAuth's user authorization. User authorization implementation via OAuth. It is required to create application first and put application
It is required to create application first and put application credentials. credentials.
Attributes: Attributes:
client_id(str): application client id client_id(str): application client id

View File

@ -266,6 +266,11 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"required": True, "required": True,
"path_exists": True, "path_exists": True,
}, },
"timeout": {
"type": "integer",
"coerce": "integer",
"min": 0,
},
"unix_socket": { "unix_socket": {
"type": "path", "type": "path",
"coerce": "absolute_path", "coerce": "absolute_path",

View File

@ -136,13 +136,13 @@ class Validator(RootValidator):
The rule's arguments are validated against this schema: The rule's arguments are validated against this schema:
{"type": "list", "schema": {"type": "string"}} {"type": "list", "schema": {"type": "string"}}
""" """
url = urlparse(value) # it probably will never rise exceptions on parse match urlparse(value): # it probably will never rise exceptions on parse
if not url.scheme: case url if not url.scheme:
self._error(field, f"Url scheme is not set for {value}") self._error(field, f"Url scheme is not set for {value}")
if not url.netloc and url.scheme not in ("file",): case url if not url.netloc and url.scheme not in ("file",):
self._error(field, f"Location must be set for url {value} of scheme {url.scheme}") self._error(field, f"Location must be set for url {value} of scheme {url.scheme}")
if constraint and url.scheme not in constraint: case url if constraint and url.scheme not in constraint:
self._error(field, f"Url {value} scheme must be one of {constraint}") self._error(field, f"Url {value} scheme must be one of {constraint}")
def _validate_path_exists(self, constraint: bool, field: str, value: Path) -> None: def _validate_path_exists(self, constraint: bool, field: str, value: Path) -> None:
""" """
@ -157,7 +157,8 @@ class Validator(RootValidator):
The rule's arguments are validated against this schema: The rule's arguments are validated against this schema:
{"type": "boolean"} {"type": "boolean"}
""" """
if constraint and not value.exists(): match value.exists():
self._error(field, f"Path {value} must exist") case True if not constraint:
if not constraint and value.exists(): self._error(field, f"Path {value} must not exist")
self._error(field, f"Path {value} must not exist") case False if constraint:
self._error(field, f"Path {value} must exist")

View File

@ -80,23 +80,24 @@ class Report(LazyLogging):
Report: client according to current settings Report: client according to current settings
""" """
section, provider_name = configuration.gettype(target, architecture) section, provider_name = configuration.gettype(target, architecture)
provider = ReportSettings.from_option(provider_name) match ReportSettings.from_option(provider_name):
if provider == ReportSettings.HTML: case ReportSettings.HTML:
from ahriman.core.report.html import HTML from ahriman.core.report.html import HTML
return HTML(architecture, configuration, section) return HTML(architecture, configuration, section)
if provider == ReportSettings.Email: case ReportSettings.Email:
from ahriman.core.report.email import Email from ahriman.core.report.email import Email
return Email(architecture, configuration, section) return Email(architecture, configuration, section)
if provider == ReportSettings.Console: case ReportSettings.Console:
from ahriman.core.report.console import Console from ahriman.core.report.console import Console
return Console(architecture, configuration, section) return Console(architecture, configuration, section)
if provider == ReportSettings.Telegram: case ReportSettings.Telegram:
from ahriman.core.report.telegram import Telegram from ahriman.core.report.telegram import Telegram
return Telegram(architecture, configuration, section) return Telegram(architecture, configuration, section)
if provider == ReportSettings.RemoteCall: case ReportSettings.RemoteCall:
from ahriman.core.report.remote_call import RemoteCall from ahriman.core.report.remote_call import RemoteCall
return RemoteCall(architecture, configuration, section) return RemoteCall(architecture, configuration, section)
return Report(architecture, configuration) # should never happen case _:
return Report(architecture, configuration) # should never happen
def generate(self, packages: list[Package], result: Result) -> None: def generate(self, packages: list[Package], result: Result) -> None:
""" """

View File

@ -40,7 +40,7 @@ class Repository(Executor, UpdateHandler):
Examples: Examples:
This class along with traits provides access to local repository actions, e.g. remove packages, update packages, This class along with traits provides access to local repository actions, e.g. remove packages, update packages,
sync local repository to remote, generate report, etc:: sync local repository to remote, generate report, etc.::
>>> from ahriman.core.configuration import Configuration >>> from ahriman.core.configuration import Configuration
>>> from ahriman.core.database import SQLite >>> from ahriman.core.database import SQLite

View File

@ -33,7 +33,7 @@ class GPG(SyncHttpClient):
Attributes: Attributes:
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
default_key(str | None): default PGP key ID to use default_key(str | None): default PGP key ID to use
targets(set[SignSettings]): list of targets to sign (repository, package etc) targets(set[SignSettings]): list of targets to sign (repository, package etc.)
""" """
_check_output = check_output _check_output = check_output
@ -116,7 +116,7 @@ class GPG(SyncHttpClient):
download key from public PGP server download key from public PGP server
Args: Args:
server(str): public PGP server which will be used to download the key server(str): public PGP server which will be used to download data
key(str): key ID to download key(str): key ID to download
Returns: Returns:
@ -163,7 +163,7 @@ class GPG(SyncHttpClient):
import key to current user and sign it locally import key to current user and sign it locally
Args: Args:
server(str): public PGP server which will be used to download the key server(str): public PGP server which will be used to download data
key(str): key ID to import key(str): key ID to import
""" """
key_body = self.key_download(server, key) key_body = self.key_download(server, key)

View File

@ -113,7 +113,7 @@ class Watcher(LazyLogging):
Args: Args:
log_record_id(LogRecordId): log record id log_record_id(LogRecordId): log record id
created(float): log created record created(float): log created timestamp
record(str): log record record(str): log record
""" """
if self._last_log_record_id != log_record_id: if self._last_log_record_id != log_record_id:

View File

@ -92,7 +92,7 @@ class Tree:
dependency tree implementation dependency tree implementation
Attributes: Attributes:
leaves[list[Leaf]): list of tree leaves leaves(list[Leaf]): list of tree leaves
Examples: Examples:
The most important feature here is to generate tree levels one by one which can be achieved by using class The most important feature here is to generate tree levels one by one which can be achieved by using class

View File

@ -31,11 +31,11 @@ from ahriman.models.package import Package
class Github(HttpUpload): class Github(HttpUpload):
""" """
upload files to github releases upload files to GitHub releases
Attributes: Attributes:
github_owner(str): github repository owner github_owner(str): GitHub repository owner
github_repository(str): github repository name github_repository(str): GitHub repository name
""" """
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None: def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
@ -100,7 +100,7 @@ class Github(HttpUpload):
def files_remove(self, release: dict[str, Any], local_files: dict[Path, str], remote_files: dict[str, str]) -> None: def files_remove(self, release: dict[str, Any], local_files: dict[Path, str], remote_files: dict[str, str]) -> None:
""" """
remove files from github remove files from GitHub
Args: Args:
release(dict[str, Any]): release object release(dict[str, Any]): release object
@ -115,7 +115,7 @@ class Github(HttpUpload):
def files_upload(self, release: dict[str, Any], local_files: dict[Path, str], remote_files: dict[str, str]) -> None: def files_upload(self, release: dict[str, Any], local_files: dict[Path, str], remote_files: dict[str, str]) -> None:
""" """
upload files to github upload files to GitHub
Args: Args:
release(dict[str, Any]): release object release(dict[str, Any]): release object
@ -133,7 +133,7 @@ class Github(HttpUpload):
create empty release create empty release
Returns: Returns:
dict[str, Any]: github API release object for the new release dict[str, Any]: GitHub API release object for the new release
""" """
url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases" url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases"
response = self.make_request("POST", url, json={"tag_name": self.architecture, "name": self.architecture}) response = self.make_request("POST", url, json={"tag_name": self.architecture, "name": self.architecture})
@ -145,7 +145,7 @@ class Github(HttpUpload):
get release object if any get release object if any
Returns: Returns:
dict[str, Any] | None: github API release object if release found and None otherwise dict[str, Any] | None: GitHub API release object if release found and None otherwise
""" """
url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases/tags/{self.architecture}" url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases/tags/{self.architecture}"
try: try:

View File

@ -80,20 +80,21 @@ class Upload(LazyLogging):
Upload: client according to current settings Upload: client according to current settings
""" """
section, provider_name = configuration.gettype(target, architecture) section, provider_name = configuration.gettype(target, architecture)
provider = UploadSettings.from_option(provider_name) match UploadSettings.from_option(provider_name):
if provider == UploadSettings.Rsync: case UploadSettings.Rsync:
from ahriman.core.upload.rsync import Rsync from ahriman.core.upload.rsync import Rsync
return Rsync(architecture, configuration, section) return Rsync(architecture, configuration, section)
if provider == UploadSettings.S3: case UploadSettings.S3:
from ahriman.core.upload.s3 import S3 from ahriman.core.upload.s3 import S3
return S3(architecture, configuration, section) return S3(architecture, configuration, section)
if provider == UploadSettings.Github: case UploadSettings.GitHub:
from ahriman.core.upload.github import Github from ahriman.core.upload.github import Github
return Github(architecture, configuration, section) return Github(architecture, configuration, section)
if provider == UploadSettings.RemoteService: case UploadSettings.RemoteService:
from ahriman.core.upload.remote_service import RemoteService from ahriman.core.upload.remote_service import RemoteService
return RemoteService(architecture, configuration, section) return RemoteService(architecture, configuration, section)
return Upload(architecture, configuration) # should never happen case _:
return Upload(architecture, configuration) # should never happen
def run(self, path: Path, built_packages: list[Package]) -> None: def run(self, path: Path, built_packages: list[Package]) -> None:
""" """

View File

@ -99,6 +99,11 @@ class UploadTrigger(Trigger):
"type": "string", "type": "string",
"allowed": ["ahriman", "remote-service"], "allowed": ["ahriman", "remote-service"],
}, },
"timeout": {
"type": "integer",
"coerce": "integer",
"min": 0,
},
}, },
}, },
"s3": { "s3": {

View File

@ -334,7 +334,7 @@ def pretty_size(size: float | None, level: int = 0) -> str:
Args: Args:
size(float | None): size to convert size(float | None): size to convert
level(int, optional): represents current units, 0 is B, 1 is KiB, etc (Default value = 0) level(int, optional): represents current units, 0 is B, 1 is KiB, etc. (Default value = 0)
Returns: Returns:
str: pretty printable size as string str: pretty printable size as string
@ -343,15 +343,17 @@ def pretty_size(size: float | None, level: int = 0) -> str:
OptionError: if size is more than 1TiB OptionError: if size is more than 1TiB
""" """
def str_level() -> str: def str_level() -> str:
if level == 0: match level:
return "B" case 0:
if level == 1: return "B"
return "KiB" case 1:
if level == 2: return "KiB"
return "MiB" case 2:
if level == 3: return "MiB"
return "GiB" case 3:
raise OptionError(level) # must never happen actually return "GiB"
case _:
raise OptionError(level) # must never happen actually
if size is None: if size is None:
return "" return ""
@ -389,7 +391,7 @@ def srcinfo_property(key: str, srcinfo: dict[str, Any], package_srcinfo: dict[st
returned returned
Args: Args:
key(str): key to extract from srcinfo key(str): key to extract
srcinfo(dict[str, Any]): root structure of SRCINFO srcinfo(dict[str, Any]): root structure of SRCINFO
package_srcinfo(dict[str, Any]): package specific SRCINFO package_srcinfo(dict[str, Any]): package specific SRCINFO
default(Any, optional): the default value for the specified key (Default value = None) default(Any, optional): the default value for the specified key (Default value = None)
@ -408,7 +410,7 @@ def srcinfo_property_list(key: str, srcinfo: dict[str, Any], package_srcinfo: di
append it at the end of result append it at the end of result
Args: Args:
key(str): key to extract from srcinfo key(str): key to extract
srcinfo(dict[str, Any]): root structure of SRCINFO srcinfo(dict[str, Any]): root structure of SRCINFO
package_srcinfo(dict[str, Any]): package specific SRCINFO package_srcinfo(dict[str, Any]): package specific SRCINFO
architecture(str | None, optional): package architecture if set (Default value = None) architecture(str | None, optional): package architecture if set (Default value = None)
@ -424,9 +426,9 @@ def srcinfo_property_list(key: str, srcinfo: dict[str, Any], package_srcinfo: di
def trim_package(package_name: str) -> str: def trim_package(package_name: str) -> str:
""" """
remove version bound and description from package name. Pacman allows to specify version bound (=, <=, >= etc) for remove version bound and description from package name. Pacman allows to specify version bound (=, <=, >= etc.) for
packages in dependencies and also allows to specify description (via :); this function removes trailing parts and packages in dependencies and also allows to specify description (via ``:``); this function removes trailing parts
return exact package name and return exact package name
Args: Args:
package_name(str): source package name package_name(str): source package name

View File

@ -44,9 +44,7 @@ class AuthSettings(str, Enum):
Returns: Returns:
bool: False in case if authorization is disabled and True otherwise bool: False in case if authorization is disabled and True otherwise
""" """
if self == AuthSettings.Disabled: return self != AuthSettings.Disabled
return False
return True
@staticmethod @staticmethod
def from_option(value: str) -> AuthSettings: def from_option(value: str) -> AuthSettings:
@ -59,8 +57,10 @@ class AuthSettings(str, Enum):
Returns: Returns:
AuthSettings: parsed value AuthSettings: parsed value
""" """
if value.lower() in ("configuration", "mapping"): match value.lower():
return AuthSettings.Configuration case "configuration" | "mapping":
if value.lower() in ("oauth", "oauth2"): return AuthSettings.Configuration
return AuthSettings.OAuth case "oauth" | "oauth2":
return AuthSettings.Disabled return AuthSettings.OAuth
case _:
return AuthSettings.Disabled

View File

@ -64,7 +64,7 @@ class RemoteSource:
@property @property
def pkgbuild_dir(self) -> Path | None: def pkgbuild_dir(self) -> Path | None:
""" """
get path to directory with package sources (PKGBUILD etc) get path to directory with package sources (PKGBUILD etc.)
Returns: Returns:
Path | None: path to directory with package sources based on settings if available Path | None: path to directory with package sources based on settings if available

View File

@ -53,14 +53,16 @@ class ReportSettings(str, Enum):
Returns: Returns:
ReportSettings: parsed value ReportSettings: parsed value
""" """
if value.lower() in ("html",): match value.lower():
return ReportSettings.HTML case "html":
if value.lower() in ("email",): return ReportSettings.HTML
return ReportSettings.Email case "email":
if value.lower() in ("console",): return ReportSettings.Email
return ReportSettings.Console case "console":
if value.lower() in ("telegram",): return ReportSettings.Console
return ReportSettings.Telegram case "telegram":
if value.lower() in ("ahriman", "remote-call",): return ReportSettings.Telegram
return ReportSettings.RemoteCall case "ahriman" | "remote-call":
return ReportSettings.Disabled return ReportSettings.RemoteCall
case _:
return ReportSettings.Disabled

View File

@ -32,8 +32,8 @@ class RepositoryPaths:
repository paths holder. For the most operations with paths you want to use this object repository paths holder. For the most operations with paths you want to use this object
Attributes: Attributes:
root(Path): repository root (i.e. ahriman home)
architecture(str): repository architecture architecture(str): repository architecture
root(Path): repository root (i.e. ahriman home)
Examples: Examples:
This class can be used in order to access the repository tree structure:: This class can be used in order to access the repository tree structure::

View File

@ -47,8 +47,10 @@ class SignSettings(str, Enum):
Returns: Returns:
SignSettings: parsed value SignSettings: parsed value
""" """
if value.lower() in ("package", "packages", "sign-package"): match value.lower():
return SignSettings.Packages case "package" | "packages" | "sign-package":
if value.lower() in ("repository", "sign-repository"): return SignSettings.Packages
return SignSettings.Repository case "repository" | "sign-repository":
return SignSettings.Disabled return SignSettings.Repository
case _:
return SignSettings.Disabled

View File

@ -47,8 +47,10 @@ class SmtpSSLSettings(str, Enum):
Returns: Returns:
SmtpSSLSettings: parsed value SmtpSSLSettings: parsed value
""" """
if value.lower() in ("ssl", "ssl/tls"): match value.lower():
return SmtpSSLSettings.SSL case "ssl" | "ssl/tls":
if value.lower() in ("starttls",): return SmtpSSLSettings.SSL
return SmtpSSLSettings.STARTTLS case "starttls":
return SmtpSSLSettings.Disabled return SmtpSSLSettings.STARTTLS
case _:
return SmtpSSLSettings.Disabled

View File

@ -30,14 +30,14 @@ class UploadSettings(str, Enum):
Disabled(UploadSettings): (class attribute) no sync will be performed, required for testing purpose Disabled(UploadSettings): (class attribute) no sync will be performed, required for testing purpose
Rsync(UploadSettings): (class attribute) sync via rsync Rsync(UploadSettings): (class attribute) sync via rsync
S3(UploadSettings): (class attribute) sync to Amazon S3 S3(UploadSettings): (class attribute) sync to Amazon S3
Github(UploadSettings): (class attribute) sync to github releases page GitHub(UploadSettings): (class attribute) sync to GitHub releases page
RemoteService(UploadSettings): (class attribute) sync to another ahriman instance RemoteService(UploadSettings): (class attribute) sync to another ahriman instance
""" """
Disabled = "disabled" # for testing purpose Disabled = "disabled" # for testing purpose
Rsync = "rsync" Rsync = "rsync"
S3 = "s3" S3 = "s3"
Github = "github" GitHub = "github"
RemoteService = "remote-service" RemoteService = "remote-service"
@staticmethod @staticmethod
@ -51,12 +51,14 @@ class UploadSettings(str, Enum):
Returns: Returns:
UploadSettings: parsed value UploadSettings: parsed value
""" """
if value.lower() in ("rsync",): match value.lower():
return UploadSettings.Rsync case "rsync":
if value.lower() in ("s3",): return UploadSettings.Rsync
return UploadSettings.S3 case "s3":
if value.lower() in ("github",): return UploadSettings.S3
return UploadSettings.Github case "github":
if value.lower() in ("ahriman", "remote-service",): return UploadSettings.GitHub
return UploadSettings.RemoteService case "ahriman" | "remote-service":
return UploadSettings.Disabled return UploadSettings.RemoteService
case _:
return UploadSettings.Disabled

View File

@ -102,6 +102,7 @@ def _auth_handler(allow_read_only: bool) -> MiddlewareType:
permission = UserAccess.Unauthorized if isinstance(handler_instance, StaticResource) else UserAccess.Full permission = UserAccess.Unauthorized if isinstance(handler_instance, StaticResource) else UserAccess.Full
else: else:
permission = UserAccess.Full permission = UserAccess.Full
if permission == UserAccess.Unauthorized: # explicit if elif else for better code coverage if permission == UserAccess.Unauthorized: # explicit if elif else for better code coverage
pass pass
elif allow_read_only and UserAccess.Read.permits(permission): elif allow_read_only and UserAccess.Read.permits(permission):

View File

@ -107,7 +107,7 @@ class BaseView(View, CorsViewMixin):
get non-empty value from request parameters get non-empty value from request parameters
Args: Args:
extractor(Callable[[str], T | None]): function to get value by the specified key extractor(Callable[[str], T | None]): function to get value
key(str): key to extract value key(str): key to extract value
Returns: Returns:

View File

@ -28,7 +28,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
""" """
must run command must run command
""" """
package_ahriman.version = "0.0.0" package_ahriman.version = "0.0.0-1"
args = _default_args(args) args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
package_mock = mocker.patch("ahriman.models.package.Package.from_aur", return_value=package_ahriman) package_mock = mocker.patch("ahriman.models.package.Package.from_aur", return_value=package_ahriman)

View File

@ -18,8 +18,8 @@ def test_from_option_valid() -> None:
assert UploadSettings.from_option("s3") == UploadSettings.S3 assert UploadSettings.from_option("s3") == UploadSettings.S3
assert UploadSettings.from_option("S3") == UploadSettings.S3 assert UploadSettings.from_option("S3") == UploadSettings.S3
assert UploadSettings.from_option("github") == UploadSettings.Github assert UploadSettings.from_option("github") == UploadSettings.GitHub
assert UploadSettings.from_option("GitHub") == UploadSettings.Github assert UploadSettings.from_option("GitHub") == UploadSettings.GitHub
assert UploadSettings.from_option("remote-service") == UploadSettings.RemoteService assert UploadSettings.from_option("remote-service") == UploadSettings.RemoteService
assert UploadSettings.from_option("Remote-Service") == UploadSettings.RemoteService assert UploadSettings.from_option("Remote-Service") == UploadSettings.RemoteService