Compare commits

...

2 Commits

Author SHA1 Message Date
2414686f3c review fixes 2022-04-17 17:59:39 +03:00
60bb880f9f make identation a bit more readable 2022-04-17 17:27:38 +03:00
168 changed files with 1553 additions and 1558 deletions

View File

@ -45,10 +45,10 @@ def _formatter(prog: str) -> argparse.HelpFormatter:
formatter for the help message
Args:
prog(str): application name
prog(str): application name
Returns:
argparse.HelpFormatter: formatter used by default
argparse.HelpFormatter: formatter used by default
"""
return argparse.ArgumentDefaultsHelpFormatter(prog, width=120)
@ -58,7 +58,7 @@ def _parser() -> argparse.ArgumentParser:
command line parser generator
Returns:
argparse.ArgumentParser: command line parser for the application
argparse.ArgumentParser: command line parser for the application
"""
parser = argparse.ArgumentParser(prog="ahriman", description="ArcH Linux ReposItory MANager",
epilog="Argument list can also be read from file by using @ prefix.",
@ -115,10 +115,10 @@ def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for AUR search subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("aur-search", aliases=["search"], help="search for package",
description="search for package in AUR using API", formatter_class=_formatter)
@ -138,10 +138,10 @@ def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for listing help subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("help", help="show help message",
description="show help message for application or command and exit",
@ -157,10 +157,10 @@ def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.Argument
add parser for listing unsafe commands
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("help-commands-unsafe", help="list unsafe commands",
description="list unsafe commands as defined in default args", formatter_class=_formatter)
@ -176,10 +176,10 @@ def _set_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for key import subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("key-import", help="import PGP key",
description="import PGP key from public sources to the repository user",
@ -199,10 +199,10 @@ def _set_package_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for package addition subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("package-add", aliases=["add", "package-update"], help="add package",
description="add existing or new package to the build queue",
@ -232,10 +232,10 @@ def _set_package_remove_parser(root: SubParserAction) -> argparse.ArgumentParser
add parser for package removal subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("package-remove", aliases=["remove"], help="remove package",
description="remove package from the repository", formatter_class=_formatter)
@ -249,10 +249,10 @@ def _set_package_status_parser(root: SubParserAction) -> argparse.ArgumentParser
add parser for package status subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("package-status", aliases=["status"], help="get package status",
description="request status of the package",
@ -273,10 +273,10 @@ def _set_package_status_remove_parser(root: SubParserAction) -> argparse.Argumen
add parser for package status remove subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("package-status-remove", help="remove package status",
description="remove the package from the status page",
@ -294,10 +294,10 @@ def _set_package_status_update_parser(root: SubParserAction) -> argparse.Argumen
add parser for package status update subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("package-status-update", aliases=["status-update"], help="update package status",
description="update package status on the status page", formatter_class=_formatter)
@ -316,10 +316,10 @@ def _set_patch_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for new patch subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("patch-add", help="add patch set", description="create or update source patches",
epilog="In order to add a patch set for the package you will need to clone "
@ -340,10 +340,10 @@ def _set_patch_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for list patches subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("patch-list", help="list patch sets",
description="list available patches for the package", formatter_class=_formatter)
@ -358,10 +358,10 @@ def _set_patch_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for remove patches subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("patch-remove", help="remove patch set", description="remove patches for the package",
formatter_class=_formatter)
@ -375,10 +375,10 @@ def _set_repo_backup_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for repository backup subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-backup", help="backup repository data",
description="backup settings and database", formatter_class=_formatter)
@ -392,10 +392,10 @@ def _set_repo_check_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for repository check subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-check", aliases=["check"], help="check for updates",
description="check for packages updates. Same as update --dry-run --no-manual",
@ -412,10 +412,10 @@ def _set_repo_clean_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for repository clean subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-clean", aliases=["clean"], help="clean local caches",
description="remove local caches",
@ -436,10 +436,10 @@ def _set_repo_config_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for config subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-config", aliases=["config"], help="dump configuration",
description="dump configuration for the specified architecture",
@ -453,10 +453,10 @@ def _set_repo_rebuild_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for repository rebuild subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-rebuild", aliases=["rebuild"], help="rebuild repository",
description="force rebuild whole repository", formatter_class=_formatter)
@ -479,10 +479,10 @@ def _set_repo_remove_unknown_parser(root: SubParserAction) -> argparse.ArgumentP
add parser for remove unknown packages subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-remove-unknown", aliases=["remove-unknown"], help="remove unknown packages",
description="remove packages which are missing in AUR and do not have local PKGBUILDs",
@ -498,10 +498,10 @@ def _set_repo_report_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for report subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-report", aliases=["report"], help="generate report",
description="generate repository report according to current settings",
@ -517,10 +517,10 @@ def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for repository restore subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-restore", help="restore repository data",
description="restore settings and database", formatter_class=_formatter)
@ -535,10 +535,10 @@ def _set_repo_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for setup subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-setup", aliases=["init", "repo-init", "setup"], help="initial service configuration",
description="create initial service configuration, requires root",
@ -564,10 +564,10 @@ def _set_repo_sign_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for sign subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-sign", aliases=["sign"], help="sign packages",
description="(re-)sign packages and repository database according to current settings",
@ -583,10 +583,10 @@ def _set_repo_status_update_parser(root: SubParserAction) -> argparse.ArgumentPa
add parser for repository status update subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-status-update", help="update repository status",
description="update repository status on the status page", formatter_class=_formatter)
@ -602,10 +602,10 @@ def _set_repo_sync_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for repository sync subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-sync", aliases=["sync"], help="sync repository",
description="sync repository files to remote server according to current settings",
@ -621,10 +621,10 @@ def _set_repo_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for repository update subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-update", aliases=["update"], help="update packages",
description="check for packages updates and run build process if requested",
@ -645,10 +645,10 @@ def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for create user subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("user-add", help="create or update user",
description="update user for web services with the given password and role. "
@ -671,10 +671,10 @@ def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for user list subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("user-list", help="user known users and their access",
description="list users from the user mapping and their roles",
@ -692,10 +692,10 @@ def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for user removal subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("user-remove", help="remove user",
description="remove user from the user mapping and update the configuration",
@ -712,10 +712,10 @@ def _set_web_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for web subcommand
Args:
root(SubParserAction): subparsers for the commands
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("web", help="web server", description="start web server", formatter_class=_formatter)
parser.set_defaults(handler=handlers.Web, lock=None, no_report=True, parser=_parser)

View File

@ -34,7 +34,7 @@ class Application(Packages, Repository):
generate report and sync to remote server
Args:
result(Result): build result
result(Result): build result
"""
self.report([], result)
self.sync([], result.success)
@ -44,7 +44,7 @@ class Application(Packages, Repository):
load packages from repository and pacman repositories
Returns:
Set[str]: list of known packages
Set[str]: list of known packages
"""
known_packages: Set[str] = set()
# local set

View File

@ -41,10 +41,10 @@ class Packages(Properties):
generate report and sync to remote server
Args:
result(Result): build result
result(Result): build result
Raises:
NotImplementedError: not implemented method
NotImplementedError: not implemented method
"""
raise NotImplementedError
@ -53,10 +53,10 @@ class Packages(Properties):
load packages from repository and pacman repositories
Returns:
Set[str]: list of known packages
Set[str]: list of known packages
Raises:
NotImplementedError: not implemented method
NotImplementedError: not implemented method
"""
raise NotImplementedError
@ -65,7 +65,7 @@ class Packages(Properties):
add package from archive
Args:
source(str): path to package archive
source(str): path to package archive
"""
local_path = Path(source)
dst = self.repository.paths.packages / local_path.name
@ -76,9 +76,9 @@ class Packages(Properties):
add package from AUR
Args:
source(str): package base name
known_packages(Set[str]): list of packages which are known by the service
without_dependencies(bool): if set, dependency check will be disabled
source(str): package base name
known_packages(Set[str]): list of packages which are known by the service
without_dependencies(bool): if set, dependency check will be disabled
"""
package = Package.load(source, PackageSource.AUR, self.repository.pacman, self.repository.aur_url)
@ -93,7 +93,7 @@ class Packages(Properties):
add packages from directory
Args:
source(str): path to local directory
source(str): path to local directory
"""
local_path = Path(source)
for full_path in filter(package_like, local_path.iterdir()):
@ -104,9 +104,9 @@ class Packages(Properties):
add package from local PKGBUILDs
Args:
source(str): path to directory with local source files
known_packages(Set[str]): list of packages which are known by the service
without_dependencies(bool): if set, dependency check will be disabled
source(str): path to directory with local source files
known_packages(Set[str]): list of packages which are known by the service
without_dependencies(bool): if set, dependency check will be disabled
"""
package = Package.load(source, PackageSource.Local, self.repository.pacman, self.repository.aur_url)
cache_dir = self.repository.paths.cache_for(package.base)
@ -122,7 +122,7 @@ class Packages(Properties):
add package from remote sources (e.g. HTTP)
Args:
source(str): remote URL of the package archive
source(str): remote URL of the package archive
"""
dst = self.repository.paths.packages / Path(source).name # URL is path, is not it?
response = requests.get(source, stream=True)
@ -137,9 +137,9 @@ class Packages(Properties):
process package dependencies
Args:
local_path(Path): path to local package sources (i.e. cloned AUR repository)
known_packages(Set[str]): list of packages which are known by the service
without_dependencies(bool): if set, dependency check will be disabled
local_path(Path): path to local package sources (i.e. cloned AUR repository)
known_packages(Set[str]): list of packages which are known by the service
without_dependencies(bool): if set, dependency check will be disabled
"""
if without_dependencies:
return
@ -152,9 +152,9 @@ class Packages(Properties):
add packages for the next build
Args:
names(Iterable[str]): list of package bases to add
source(PackageSource): package source to add
without_dependencies(bool): if set, dependency check will be disabled
names(Iterable[str]): list of package bases to add
source(PackageSource): package source to add
without_dependencies(bool): if set, dependency check will be disabled
"""
known_packages = self._known_packages() # speedup dependencies processing
@ -168,7 +168,7 @@ class Packages(Properties):
remove packages from repository
Args:
names(Iterable[str]): list of packages (either base or name) to remove
names(Iterable[str]): list of packages (either base or name) to remove
"""
self.repository.process_remove(names)
self._finalize(Result())

View File

@ -29,11 +29,11 @@ class Properties:
application base properties class
Attributes:
architecture(str): repository architecture
configuration(Configuration): configuration instance
database(SQLite): database instance
logger(logging.Logger): application logger
repository(Repository): repository instance
architecture(str): repository architecture
configuration(Configuration): configuration instance
database(SQLite): database instance
logger(logging.Logger): application logger
repository(Repository): repository instance
"""
def __init__(self, architecture: str, configuration: Configuration, no_report: bool, unsafe: bool) -> None:
@ -41,10 +41,10 @@ class Properties:
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
self.logger = logging.getLogger("root")
self.configuration = configuration

View File

@ -40,10 +40,10 @@ class Repository(Properties):
generate report and sync to remote server
Args:
result(Result): build result
result(Result): build result
Raises:
NotImplementedError: not implemented method
NotImplementedError: not implemented method
"""
raise NotImplementedError
@ -52,10 +52,10 @@ class Repository(Properties):
run all clean methods. Warning: some functions might not be available under non-root
Args:
cache(bool): clear directory with package caches
chroot(bool): clear build chroot
manual(bool): clear directory with manually added packages
packages(bool): clear directory with built packages
cache(bool): clear directory with package caches
chroot(bool): clear build chroot
manual(bool): clear directory with manually added packages
packages(bool): clear directory with built packages
"""
if cache:
self.repository.clear_cache()
@ -71,8 +71,8 @@ class Repository(Properties):
generate report
Args:
target(Iterable[str]): list of targets to run (e.g. html)
result(Result): build result
target(Iterable[str]): list of targets to run (e.g. html)
result(Result): build result
"""
targets = target or None
self.repository.process_report(targets, result)
@ -82,7 +82,7 @@ class Repository(Properties):
sign packages and repository
Args:
packages(Iterable[str]): only sign specified packages
packages(Iterable[str]): only sign specified packages
"""
# copy to prebuilt directory
for package in self.repository.packages():
@ -107,8 +107,8 @@ class Repository(Properties):
sync to remote server
Args:
target(Iterable[str]): list of targets to run (e.g. s3)
built_packages(Iterable[Package]): list of packages which has just been built
target(Iterable[str]): list of targets to run (e.g. s3)
built_packages(Iterable[Package]): list of packages which has just been built
"""
targets = target or None
self.repository.process_sync(targets, built_packages)
@ -118,7 +118,7 @@ class Repository(Properties):
get packages which were not found in AUR
Returns:
List[str]: unknown package archive list
List[str]: unknown package archive list
"""
def has_local(probe: Package) -> bool:
cache_dir = self.repository.paths.cache_for(probe.base)
@ -152,10 +152,10 @@ class Repository(Properties):
run package updates
Args:
updates(Iterable[Package]): list of packages to update
updates(Iterable[Package]): list of packages to update
Returns:
Result: update result
Result: update result
"""
def process_update(paths: Iterable[Path], result: Result) -> None:
if not paths:
@ -184,16 +184,15 @@ class Repository(Properties):
get list of packages to run update process
Args:
filter_packages(Iterable[str]): do not check every package just specified in the list
no_aur(bool): do not check for aur updates
no_local(bool): do not check local packages for updates
no_manual(bool): do not check for manual updates
no_vcs(bool): do not check VCS packages
log_fn(Callable[[str]): logger function to log updates
None]:
filter_packages(Iterable[str]): do not check every package just specified in the list
no_aur(bool): do not check for aur updates
no_local(bool): do not check local packages for updates
no_manual(bool): do not check for manual updates
no_vcs(bool): do not check VCS packages
log_fn(Callable[[str], None]): logger function to log updates
Returns:
List[Package]: list of out-of-dated packages
List[Package]: list of out-of-dated packages
"""
updates = {}

View File

@ -38,11 +38,11 @@ class Add(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
application = Application(architecture, configuration, no_report, unsafe)
application.add(args.package, args.source, args.without_dependencies)

View File

@ -43,11 +43,11 @@ class Backup(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
backup_paths = Backup.get_paths(configuration)
with TarFile(args.path, mode="w") as archive: # well we don't actually use compression
@ -60,10 +60,10 @@ class Backup(Handler):
extract paths to backup
Args:
configuration(Configuration): configuration instance
configuration(Configuration): configuration instance
Returns:
Set[Path]: map of the filesystem paths
Set[Path]: map of the filesystem paths
"""
paths = set(configuration.include.glob("*.ini"))

View File

@ -38,11 +38,11 @@ class Clean(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
Application(architecture, configuration, no_report, unsafe).clean(
args.cache, args.chroot, args.manual, args.packages)

View File

@ -40,11 +40,11 @@ class Dump(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
dump = configuration.dump()
for section, values in sorted(dump.items()):

View File

@ -36,8 +36,8 @@ class Handler:
base handler class for command callbacks
Attributes:
ALLOW_AUTO_ARCHITECTURE_RUN(bool): (class attribute) allow defining architecture from existing repositories
ALLOW_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
ALLOW_AUTO_ARCHITECTURE_RUN(bool): (class attribute) allow defining architecture from existing repositories
ALLOW_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
"""
ALLOW_AUTO_ARCHITECTURE_RUN = True
@ -49,13 +49,13 @@ class Handler:
get known architectures
Args:
args(argparse.Namespace): command line args
args(argparse.Namespace): command line args
Returns:
List[str]: list of architectures for which tree is created
List[str]: list of architectures for which tree is created
Raises:
MissingArchitecture: if no architecture set and automatic detection is not allowed or failed
MissingArchitecture: if no architecture set and automatic detection is not allowed or failed
"""
if not cls.ALLOW_AUTO_ARCHITECTURE_RUN and args.architecture is None:
# for some parsers (e.g. config) we need to run with specific architecture
@ -80,11 +80,11 @@ class Handler:
additional function to wrap all calls for multiprocessing library
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
args(argparse.Namespace): command line args
architecture(str): repository architecture
Returns:
bool: True on success, False otherwise
bool: True on success, False otherwise
"""
try:
configuration = Configuration.from_path(args.configuration, architecture, args.quiet)
@ -104,13 +104,13 @@ class Handler:
execute function for all aru
Args:
args(argparse.Namespace): command line args
args(argparse.Namespace): command line args
Returns:
int: 0 on success, 1 otherwise
int: 0 on success, 1 otherwise
Raises:
MultipleArchitectures: if more than one architecture supplied and no multi architecture supported
MultipleArchitectures: if more than one architecture supplied and no multi architecture supported
"""
architectures = cls.architectures_extract(args)
@ -134,14 +134,14 @@ class Handler:
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
Raises:
NotImplementedError: not implemented method
NotImplementedError: not implemented method
"""
raise NotImplementedError
@ -151,11 +151,11 @@ class Handler:
check condition and flag and raise ExitCode exception in case if it is enabled and condition match
Args:
enabled(bool): if False no check will be performed
predicate(bool): indicates condition on which exception should be thrown
enabled(bool): if False no check will be performed
predicate(bool): indicates condition on which exception should be thrown
Raises:
ExitCode: if result is empty and check is enabled
ExitCode: if result is empty and check is enabled
"""
if enabled and predicate:
raise ExitCode()

View File

@ -39,11 +39,11 @@ class Help(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
parser: argparse.ArgumentParser = args.parser()
if args.command is None:

View File

@ -40,11 +40,11 @@ class KeyImport(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
Application(architecture, configuration, no_report, unsafe).repository.sign.key_import(
args.key_server, args.key)

View File

@ -44,11 +44,11 @@ class Patch(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
application = Application(architecture, configuration, no_report, unsafe)
@ -65,9 +65,9 @@ class Patch(Handler):
create patch set for the package base
Args:
application(Application): application instance
sources_dir(str): path to directory with the package sources
track(List[str]): track files which match the glob before creating the patch
application(Application): application instance
sources_dir(str): path to directory with the package sources
track(List[str]): track files which match the glob before creating the patch
"""
package = Package.load(sources_dir, PackageSource.Local, application.repository.pacman,
application.repository.aur_url)
@ -80,9 +80,9 @@ class Patch(Handler):
list patches available for the package base
Args:
application(Application): application instance
package_base(Optional[str]): package base
exit_code(bool): exit with error on empty search result
application(Application): application instance
package_base(Optional[str]): package base
exit_code(bool): exit with error on empty search result
"""
patches = application.database.patches_list(package_base)
Patch.check_if_empty(exit_code, not patches)
@ -97,7 +97,7 @@ class Patch(Handler):
remove patch set for the package base
Args:
application(Application): application instance
package_base(str): package base
application(Application): application instance
package_base(str): package base
"""
application.database.patches_remove(package_base)

View File

@ -40,11 +40,11 @@ class Rebuild(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
depends_on = set(args.depends_on) if args.depends_on else None
@ -69,9 +69,9 @@ class Rebuild(Handler):
extract packages from database file
Args:
application(Application): application instance
application(Application): application instance
Returns:
List[Package]: list of packages which were stored in database
List[Package]: list of packages which were stored in database
"""
return [package for (package, _) in application.database.packages_get()]

View File

@ -38,10 +38,10 @@ class Remove(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
Application(architecture, configuration, no_report, unsafe).remove(args.package)

View File

@ -39,11 +39,11 @@ class RemoveUnknown(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
application = Application(architecture, configuration, no_report, unsafe)
unknown_packages = application.unknown()

View File

@ -39,10 +39,10 @@ class Report(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
Application(architecture, configuration, no_report, unsafe).report(args.target, Result())

View File

@ -40,11 +40,11 @@ class Restore(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
with TarFile(args.path) as archive:
archive.extractall(path=args.output)

View File

@ -36,7 +36,7 @@ class Search(Handler):
packages search handler
Attributes:
SORT_FIELDS(Set[str]): (class attribute) allowed fields to sort the package list
SORT_FIELDS(Set[str]): (class attribute) allowed fields to sort the package list
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
@ -49,11 +49,11 @@ class Search(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
official_packages_list = Official.multisearch(*args.search)
aur_packages_list = AUR.multisearch(*args.search)
@ -70,14 +70,14 @@ class Search(Handler):
sort package list by specified field
Args:
packages(Iterable[AURPackage]): packages list to sort
sort_by(str): AUR package field name to sort by
packages(Iterable[AURPackage]): packages list to sort
sort_by(str): AUR package field name to sort by
Returns:
List[AURPackage]: sorted list for packages
List[AURPackage]: sorted list for packages
Raises:
InvalidOption: if search fields is not in list of allowed ones
InvalidOption: if search fields is not in list of allowed ones
"""
if sort_by not in Search.SORT_FIELDS:
raise InvalidOption(sort_by)

View File

@ -33,10 +33,10 @@ class Setup(Handler):
setup handler
Attributes:
ARCHBUILD_COMMAND_PATH(Path): (class attribute) default devtools command
BIN_DIR_PATH(Path): (class attribute) directory for custom binaries
MIRRORLIST_PATH(Path): (class attribute) path to pacman default mirrorlist (used by multilib repository)
SUDOERS_PATH(Path): (class attribute) path to sudoers.d include configuration
ARCHBUILD_COMMAND_PATH(Path): (class attribute) default devtools command
BIN_DIR_PATH(Path): (class attribute) directory for custom binaries
MIRRORLIST_PATH(Path): (class attribute) path to pacman default mirrorlist (used by multilib repository)
SUDOERS_PATH(Path): (class attribute) path to sudoers.d include configuration
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False
@ -53,11 +53,11 @@ class Setup(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
Setup.configuration_create_ahriman(args, architecture, args.repository, configuration.include)
configuration.reload()
@ -78,11 +78,11 @@ class Setup(Handler):
generate build command name
Args:
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
Returns:
Path: valid devtools command name
Path: valid devtools command name
"""
return Setup.BIN_DIR_PATH / f"{prefix}-{architecture}-build"
@ -93,10 +93,10 @@ class Setup(Handler):
create service specific configuration
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
repository(str): repository name
include_path(Path): path to directory with configuration includes
args(argparse.Namespace): command line args
architecture(str): repository architecture
repository(str): repository name
include_path(Path): path to directory with configuration includes
"""
configuration = Configuration()
@ -126,12 +126,12 @@ class Setup(Handler):
create configuration for devtools based on `source` configuration
Args:
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
source(Path): path to source configuration file
no_multilib(bool): do not add multilib repository
repository(str): repository name
paths(RepositoryPaths): repository paths instance
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
source(Path): path to source configuration file
no_multilib(bool): do not add multilib repository
repository(str): repository name
paths(RepositoryPaths): repository paths instance
"""
configuration = Configuration()
# preserve case
@ -163,8 +163,8 @@ class Setup(Handler):
create configuration for makepkg
Args:
packager(str): packager identifier (e.g. name, email)
paths(RepositoryPaths): repository paths instance
packager(str): packager identifier (e.g. name, email)
paths(RepositoryPaths): repository paths instance
"""
(paths.root / ".makepkg.conf").write_text(f"PACKAGER='{packager}'\n", encoding="utf8")
@ -174,8 +174,8 @@ class Setup(Handler):
create configuration to run build command with sudo without password
Args:
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
"""
command = Setup.build_command(prefix, architecture)
Setup.SUDOERS_PATH.write_text(f"ahriman ALL=(ALL) NOPASSWD: {command} *\n", encoding="utf8")
@ -187,8 +187,8 @@ class Setup(Handler):
create executable for the service
Args:
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
"""
command = Setup.build_command(prefix, architecture)
command.unlink(missing_ok=True)

View File

@ -38,10 +38,10 @@ class Sign(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
Application(architecture, configuration, no_report, unsafe).sign(args.package)

View File

@ -44,11 +44,11 @@ class Status(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
# we are using reporter here
client = Application(architecture, configuration, no_report=False, unsafe=unsafe).repository.reporter

View File

@ -41,11 +41,11 @@ class StatusUpdate(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
# we are using reporter here
client = Application(architecture, configuration, no_report=False, unsafe=unsafe).repository.reporter

View File

@ -38,10 +38,10 @@ class Sync(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
Application(architecture, configuration, no_report, unsafe).sync(args.target, [])

View File

@ -41,11 +41,11 @@ class UnsafeCommands(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
parser = args.parser()
unsafe_commands = UnsafeCommands.get_unsafe_commands(parser)
@ -61,9 +61,9 @@ class UnsafeCommands(Handler):
check if command is unsafe
Args:
command(str): command to check
unsafe_commands(List[str]): list of unsafe commands
parser(argparse.ArgumentParser): generated argument parser
command(str): command to check
unsafe_commands(List[str]): list of unsafe commands
parser(argparse.ArgumentParser): generated argument parser
"""
args = parser.parse_args(shlex.split(command))
UnsafeCommands.check_if_empty(True, args.command in unsafe_commands)
@ -74,10 +74,10 @@ class UnsafeCommands(Handler):
extract unsafe commands from argument parser
Args:
parser(argparse.ArgumentParser): generated argument parser
parser(argparse.ArgumentParser): generated argument parser
Returns:
List[str]: list of commands with default unsafe flag
List[str]: list of commands with default unsafe flag
"""
# pylint: disable=protected-access
subparser = next(action for action in parser._actions if isinstance(action, argparse._SubParsersAction))

View File

@ -38,11 +38,11 @@ class Update(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
application = Application(architecture, configuration, no_report, unsafe)
packages = application.updates(args.package, args.no_aur, args.no_local, args.no_manual, args.no_vcs,
@ -60,11 +60,11 @@ class Update(Handler):
package updates log function
Args:
application(Application): application instance
dry_run(bool): do not perform update itself
application(Application): application instance
dry_run(bool): do not perform update itself
Returns:
Callable[[str],None]: in case if dry_run is set it will return print, logger otherwise
Callable[[str], None]: in case if dry_run is set it will return print, logger otherwise
"""
def inner(line: str) -> None:
return print(line) if dry_run else application.logger.info(line)

View File

@ -45,11 +45,11 @@ class User(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
database = SQLite.load(configuration)
@ -76,11 +76,11 @@ class User(Handler):
enable configuration if it has been disabled
Args:
configuration(Configuration): configuration instance
user(MUser): user descriptor
salt(str): password hash salt
as_service_user(bool): add user as service user, also set password and user to configuration
secure(bool): if true then set file permissions to 0o600
configuration(Configuration): configuration instance
user(MUser): user descriptor
salt(str): password hash salt
as_service_user(bool): add user as service user, also set password and user to configuration
secure(bool): if true then set file permissions to 0o600
"""
configuration.set_option("auth", "salt", salt)
if as_service_user:
@ -94,10 +94,10 @@ class User(Handler):
create configuration instance
Args:
include_path(Path): path to directory with configuration includes
include_path(Path): path to directory with configuration includes
Returns:
Configuration: configuration instance. In case if there are local settings they will be loaded
Configuration: configuration instance. In case if there are local settings they will be loaded
"""
target = include_path / "auth.ini"
configuration = Configuration()
@ -113,8 +113,8 @@ class User(Handler):
write configuration file
Args:
configuration(Configuration): configuration instance
secure(bool): if true then set file permissions to 0o600
configuration(Configuration): configuration instance
secure(bool): if true then set file permissions to 0o600
"""
path, _ = configuration.check_loaded()
with path.open("w") as ahriman_configuration:
@ -128,11 +128,11 @@ class User(Handler):
get salt from configuration or create new string
Args:
configuration(Configuration): configuration instance
salt_length(int, optional): salt length (Default value = 20)
configuration(Configuration): configuration instance
salt_length(int, optional): salt length (Default value = 20)
Returns:
str: current salt
str: current salt
"""
if salt := configuration.get("auth", "salt", fallback=None):
return salt
@ -144,10 +144,10 @@ class User(Handler):
create user descriptor from arguments
Args:
args(argparse.Namespace): command line args
args(argparse.Namespace): command line args
Returns:
MUser: built user descriptor
MUser: built user descriptor
"""
user = MUser(args.username, args.password, args.role)
if user.password is None:

View File

@ -41,11 +41,11 @@ class Web(Handler):
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
# we are using local import for optional dependencies
from ahriman.web.web import run_server, setup_service

View File

@ -39,11 +39,11 @@ class Lock:
wrapper for application lock file
Attributes:
force(bool): remove lock file on start if any
path(Path): path to lock file if any
reporter(Client): build status reporter instance
paths(RepositoryPaths): repository paths instance
unsafe(bool): skip user check
force(bool): remove lock file on start if any
path(Path): path to lock file if any
reporter(Client): build status reporter instance
paths(RepositoryPaths): repository paths instance
unsafe(bool): skip user check
"""
def __init__(self, args: argparse.Namespace, architecture: str, configuration: Configuration) -> None:
@ -51,9 +51,9 @@ class Lock:
default constructor
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
"""
self.path = Path(f"{args.lock}_{architecture}") if args.lock is not None else None
self.force = args.force
@ -66,11 +66,11 @@ class Lock:
"""
default workflow is the following:
check user UID
check if there is lock file
check web status watcher status
create lock file
report to status page if enabled
1. Check user UID
2. Check if there is lock file
3. Check web status watcher status
4. Create lock file
5. Report to status page if enabled
"""
self.check_user()
self.check_version()
@ -84,12 +84,12 @@ class Lock:
remove lock file when done
Args:
exc_type(Optional[Type[Exception]]): exception type name if any
exc_val(Optional[Exception]): exception raised if any
exc_tb(TracebackType): exception traceback if any
exc_type(Optional[Type[Exception]]): exception type name if any
exc_val(Optional[Exception]): exception raised if any
exc_tb(TracebackType): exception traceback if any
Returns:
Literal[False]: always False (do not suppress any exception)
Literal[False]: always False (do not suppress any exception)
"""
self.clear()
status = BuildStatusEnum.Success if exc_val is None else BuildStatusEnum.Failed
@ -126,7 +126,7 @@ class Lock:
create lock file
Raises:
DuplicateRun: if lock exists and no force flag supplied
DuplicateRun: if lock exists and no force flag supplied
"""
if self.path is None:
return

View File

@ -28,7 +28,7 @@ class Pacman:
alpm wrapper
Attributes:
handle(Handle): pyalpm root `Handle`
handle(Handle): pyalpm root `Handle`
"""
def __init__(self, configuration: Configuration) -> None:
@ -36,7 +36,7 @@ class Pacman:
default constructor
Args:
configuration(Configuration): configuration instance
configuration(Configuration): configuration instance
"""
root = configuration.get("alpm", "root")
pacman_root = configuration.getpath("alpm", "database")
@ -49,7 +49,7 @@ class Pacman:
get list of packages known for alpm
Returns:
Set[str]: list of package names
Set[str]: list of package names
"""
result: Set[str] = set()
for database in self.handle.get_syncdbs():

View File

@ -32,10 +32,10 @@ class AUR(Remote):
AUR RPC wrapper
Attributes:
DEFAULT_RPC_URL(str): (class attribute) default AUR RPC url
DEFAULT_RPC_VERSION(str): (class attribute) default AUR RPC version
rpc_url(str): AUR RPC url
rpc_version(str): AUR RPC version
DEFAULT_RPC_URL(str): (class attribute) default AUR RPC url
DEFAULT_RPC_VERSION(str): (class attribute) default AUR RPC version
rpc_url(str): AUR RPC url
rpc_version(str): AUR RPC version
"""
DEFAULT_RPC_URL = "https://aur.archlinux.org/rpc"
@ -46,8 +46,8 @@ class AUR(Remote):
default constructor
Args:
rpc_url(Optional[str], optional): AUR RPC url (Default value = None)
rpc_version(Optional[str], optional): AUR RPC version (Default value = None)
rpc_url(Optional[str], optional): AUR RPC url (Default value = None)
rpc_version(Optional[str], optional): AUR RPC version (Default value = None)
"""
Remote.__init__(self)
self.rpc_url = rpc_url or self.DEFAULT_RPC_URL
@ -59,13 +59,13 @@ class AUR(Remote):
parse RPC response to package list
Args:
response(Dict[str, Any]): RPC response json
response(Dict[str, Any]): RPC response json
Returns:
List[AURPackage]: list of parsed packages
List[AURPackage]: list of parsed packages
Raises:
InvalidPackageInfo: for error API response
InvalidPackageInfo: for error API response
"""
response_type = response["type"]
if response_type == "error":
@ -78,12 +78,12 @@ class AUR(Remote):
perform request to AUR RPC
Args:
request_type(str): AUR request type, e.g. search, info
*args(str): list of arguments to be passed as args query parameter
**kwargs(str): list of additional named parameters like by
request_type(str): AUR request type, e.g. search, info
*args(str): list of arguments to be passed as args query parameter
**kwargs(str): list of additional named parameters like by
Returns:
List[AURPackage]: response parsed to package list
List[AURPackage]: response parsed to package list
"""
query: Dict[str, Any] = {
"type": request_type,
@ -115,10 +115,10 @@ class AUR(Remote):
get package info by its name
Args:
package_name(str): package name to search
package_name(str): package name to search
Returns:
AURPackage: package which match the package name
AURPackage: package which match the package name
"""
packages = self.make_request("info", package_name)
return next(package for package in packages if package.name == package_name)
@ -128,9 +128,9 @@ class AUR(Remote):
search package in AUR web
Args:
*keywords(str): keywords to search
*keywords(str): keywords to search
Returns:
List[AURPackage]: list of packages which match the criteria
List[AURPackage]: list of packages which match the criteria
"""
return self.make_request("search", *keywords, by="name-desc")

View File

@ -32,8 +32,8 @@ class Official(Remote):
official repository RPC wrapper
Attributes:
DEFAULT_RPC_URL(str): (class attribute) default AUR RPC url
rpc_url(str): AUR RPC url
DEFAULT_RPC_URL(str): (class attribute) default AUR RPC url
rpc_url(str): AUR RPC url
"""
DEFAULT_RPC_URL = "https://archlinux.org/packages/search/json"
@ -43,7 +43,7 @@ class Official(Remote):
default constructor
Args:
rpc_url(Optional[str], optional): AUR RPC url (Default value = None)
rpc_url(Optional[str], optional): AUR RPC url (Default value = None)
"""
Remote.__init__(self)
self.rpc_url = rpc_url or self.DEFAULT_RPC_URL
@ -54,13 +54,13 @@ class Official(Remote):
parse RPC response to package list
Args:
response(Dict[str, Any]): RPC response json
response(Dict[str, Any]): RPC response json
Returns:
List[AURPackage]: list of parsed packages
List[AURPackage]: list of parsed packages
Raises:
InvalidPackageInfo: for error API response
InvalidPackageInfo: for error API response
"""
if not response["valid"]:
raise InvalidPackageInfo("API validation error")
@ -71,11 +71,11 @@ class Official(Remote):
perform request to official repositories RPC
Args:
*args(str): list of arguments to be passed as args query parameter
by(str): search by the field
*args(str): list of arguments to be passed as args query parameter
by(str): search by the field
Returns:
List[AURPackage]: response parsed to package list
List[AURPackage]: response parsed to package list
"""
try:
response = requests.get(self.rpc_url, params={by: args})
@ -93,10 +93,10 @@ class Official(Remote):
get package info by its name
Args:
package_name(str): package name to search
package_name(str): package name to search
Returns:
AURPackage: package which match the package name
AURPackage: package which match the package name
"""
packages = self.make_request(package_name, by="name")
return next(package for package in packages if package.name == package_name)
@ -106,9 +106,9 @@ class Official(Remote):
search package in AUR web
Args:
*keywords(str): keywords to search
*keywords(str): keywords to search
Returns:
List[AURPackage]: list of packages which match the criteria
List[AURPackage]: list of packages which match the criteria
"""
return self.make_request(*keywords, by="q")

View File

@ -31,7 +31,7 @@ class Remote:
base class for remote package search
Attributes:
logger(logging.Logger): class logger
logger(logging.Logger): class logger
"""
def __init__(self) -> None:
@ -46,10 +46,10 @@ class Remote:
get package info by its name
Args:
package_name(str): package name to search
package_name(str): package name to search
Returns:
AURPackage: package which match the package name
AURPackage: package which match the package name
"""
return cls().package_info(package_name)
@ -60,10 +60,10 @@ class Remote:
https://bugs.archlinux.org/task/49133. In addition, short words will be dropped
Args:
*keywords(str): search terms, e.g. "ahriman", "is", "cool"
*keywords(str): search terms, e.g. "ahriman", "is", "cool"
Returns:
List[AURPackage]: list of packages each of them matches all search terms
List[AURPackage]: list of packages each of them matches all search terms
"""
instance = cls()
packages: Dict[str, AURPackage] = {}
@ -82,10 +82,10 @@ class Remote:
search package in AUR web
Args:
*keywords(str): search terms, e.g. "ahriman", "is", "cool"
*keywords(str): search terms, e.g. "ahriman", "is", "cool"
Returns:
List[AURPackage]: list of packages which match the criteria
List[AURPackage]: list of packages which match the criteria
"""
return cls().package_search(*keywords)
@ -94,13 +94,13 @@ class Remote:
get package info by its name
Args:
package_name(str): package name to search
package_name(str): package name to search
Returns:
AURPackage: package which match the package name
AURPackage: package which match the package name
Raises:
NotImplementedError: not implemented method
NotImplementedError: not implemented method
"""
raise NotImplementedError
@ -109,12 +109,12 @@ class Remote:
search package in AUR web
Args:
*keywords(str): keywords to search
*keywords(str): keywords to search
Returns:
List[AURPackage]: list of packages which match the criteria
List[AURPackage]: list of packages which match the criteria
Raises:
NotImplementedError: not implemented method
NotImplementedError: not implemented method
"""
raise NotImplementedError

View File

@ -32,11 +32,11 @@ class Repo:
repo-add and repo-remove wrapper
Attributes:
logger(logging.Logger): class logger
name(str): repository name
paths(RepositoryPaths): repository paths instance
sign_args(List[str]): additional args which have to be used to sign repository archive
uid(int): uid of the repository owner user
logger(logging.Logger): class logger
name(str): repository name
paths(RepositoryPaths): repository paths instance
sign_args(List[str]): additional args which have to be used to sign repository archive
uid(int): uid of the repository owner user
"""
_check_output = check_output
@ -46,9 +46,9 @@ class Repo:
default constructor
Args:
name(str): repository name
paths(RepositoryPaths): repository paths instance
sign_args(List[str]): additional args which have to be used to sign repository archive
name(str): repository name
paths(RepositoryPaths): repository paths instance
sign_args(List[str]): additional args which have to be used to sign repository archive
"""
self.logger = logging.getLogger("build_details")
self.name = name
@ -60,7 +60,7 @@ class Repo:
def repo_path(self) -> Path:
"""
Returns:
Path: path to repository database
Path: path to repository database
"""
return self.paths.repository / f"{self.name}.db.tar.gz"
@ -69,7 +69,7 @@ class Repo:
add new package to repository
Args:
path(Path): path to archive to add
path(Path): path to archive to add
"""
Repo._check_output(
"repo-add", *self.sign_args, "-R", str(self.repo_path), str(path),
@ -94,8 +94,8 @@ class Repo:
remove package from repository
Args:
package(str): package name to remove
filename(Path): package filename to remove
package(str): package name to remove
filename(Path): package filename to remove
"""
# remove package and signature (if any) from filesystem
for full_path in self.paths.repository.glob(f"{filename}*"):

View File

@ -34,10 +34,10 @@ class Auth:
helper to deal with user authorization
Attributes:
enabled(bool): indicates if authorization is enabled
logger(logging.Logger): class logger
max_age(int): session age in seconds. It will be used for both client side and server side checks
safe_build_status(bool): allow read only access to the index page
enabled(bool): indicates if authorization is enabled
logger(logging.Logger): class logger
max_age(int): session age in seconds. It will be used for both client side and server side checks
safe_build_status(bool): allow read only access to the index page
"""
def __init__(self, configuration: Configuration, provider: AuthSettings = AuthSettings.Disabled) -> None:
@ -45,8 +45,8 @@ class Auth:
default constructor
Args:
configuration(Configuration): configuration instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Disabled)
configuration(Configuration): configuration instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Disabled)
"""
self.logger = logging.getLogger("http")
@ -64,7 +64,7 @@ class Auth:
request to external resource
Returns:
str: login control as html code to insert
str: login control as html code to insert
"""
return """<button type="button" class="btn btn-link" data-bs-toggle="modal" data-bs-target="#loginForm" style="text-decoration: none">login</button>"""
@ -74,11 +74,11 @@ class Auth:
load authorization module from settings
Args:
configuration(Configuration): configuration instance
database(SQLite): database instance
configuration(Configuration): configuration instance
database(SQLite): database instance
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"))
if provider == AuthSettings.Configuration:
@ -94,11 +94,11 @@ class Auth:
validate user password
Args:
username(Optional[str]): username
password(Optional[str]): entered password
username(Optional[str]): username
password(Optional[str]): entered password
Returns:
bool: True in case if password matches, False otherwise
bool: True in case if password matches, False otherwise
"""
del username, password
return True
@ -108,10 +108,10 @@ class Auth:
check if user is known
Args:
username(Optional[str]): username
username(Optional[str]): username
Returns:
bool: True in case if user is known and can be authorized and False otherwise
bool: True in case if user is known and can be authorized and False otherwise
"""
del username
return True
@ -121,12 +121,12 @@ class Auth:
validate if user has access to requested resource
Args:
username(str): username
required(UserAccess): required access level
context(Optional[str]): URI request path
username(str): username
required(UserAccess): required access level
context(Optional[str]): URI request path
Returns:
bool: True in case if user is allowed to do this request and False otherwise
bool: True in case if user is allowed to do this request and False otherwise
"""
del username, required, context
return True

View File

@ -31,10 +31,10 @@ async def authorized_userid(*args: Any) -> Any:
handle aiohttp security methods
Args:
*args(Any): argument list as provided by authorized_userid function
*args(Any): argument list as provided by authorized_userid function
Returns:
Any: None in case if no aiohttp_security module found and function call otherwise
Any: None in case if no aiohttp_security module found and function call otherwise
"""
if _has_aiohttp_security:
return await aiohttp_security.authorized_userid(*args) # pylint: disable=no-value-for-parameter
@ -46,10 +46,10 @@ async def check_authorized(*args: Any) -> Any:
handle aiohttp security methods
Args:
*args(Any): argument list as provided by check_authorized function
*args(Any): argument list as provided by check_authorized function
Returns:
Any: None in case if no aiohttp_security module found and function call otherwise
Any: None in case if no aiohttp_security module found and function call otherwise
"""
if _has_aiohttp_security:
return await aiohttp_security.check_authorized(*args) # pylint: disable=no-value-for-parameter
@ -61,10 +61,10 @@ async def forget(*args: Any) -> Any:
handle aiohttp security methods
Args:
*args(Any): argument list as provided by forget function
*args(Any): argument list as provided by forget function
Returns:
Any: None in case if no aiohttp_security module found and function call otherwise
Any: None in case if no aiohttp_security module found and function call otherwise
"""
if _has_aiohttp_security:
return await aiohttp_security.forget(*args) # pylint: disable=no-value-for-parameter
@ -76,10 +76,10 @@ async def remember(*args: Any) -> Any:
handle disabled auth
Args:
*args(Any): argument list as provided by remember function
*args(Any): argument list as provided by remember function
Returns:
Any: None in case if no aiohttp_security module found and function call otherwise
Any: None in case if no aiohttp_security module found and function call otherwise
"""
if _has_aiohttp_security:
return await aiohttp_security.remember(*args) # pylint: disable=no-value-for-parameter

View File

@ -33,8 +33,8 @@ class Mapping(Auth):
user authorization based on mapping from configuration file
Attributes:
salt(str): random generated string to salt passwords
database(SQLite): database instance
salt(str): random generated string to salt passwords
database(SQLite): database instance
"""
def __init__(self, configuration: Configuration, database: SQLite,
@ -43,9 +43,9 @@ class Mapping(Auth):
default constructor
Args:
configuration(Configuration): configuration instance
database(SQLite): database instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Configuration)
configuration(Configuration): configuration instance
database(SQLite): database instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Configuration)
"""
Auth.__init__(self, configuration, provider)
self.database = database
@ -56,11 +56,11 @@ class Mapping(Auth):
validate user password
Args:
username(Optional[str]): username
password(Optional[str]): entered password
username(Optional[str]): username
password(Optional[str]): entered password
Returns:
bool: True in case if password matches, False otherwise
bool: True in case if password matches, False otherwise
"""
if username is None or password is None:
return False # invalid data supplied
@ -72,10 +72,10 @@ class Mapping(Auth):
retrieve user from in-memory mapping
Args:
username(str): username
username(str): username
Returns:
Optional[User]: user descriptor if username is known and None otherwise
Optional[User]: user descriptor if username is known and None otherwise
"""
return self.database.user_get(username)
@ -84,10 +84,10 @@ class Mapping(Auth):
check if user is known
Args:
username(Optional[str]): username
username(Optional[str]): username
Returns:
bool: True in case if user is known and can be authorized and False otherwise
bool: True in case if user is known and can be authorized and False otherwise
"""
return username is not None and self.get_user(username) is not None
@ -96,12 +96,12 @@ class Mapping(Auth):
validate if user has access to requested resource
Args:
username(str): username
required(UserAccess): required access level
context(Optional[str]): URI request path
username(str): username
required(UserAccess): required access level
context(Optional[str]): URI request path
Returns:
bool: True in case if user is allowed to do this request and False otherwise
bool: True in case if user is allowed to do this request and False otherwise
"""
user = self.get_user(username)
return user is not None and user.verify_access(required)

View File

@ -34,11 +34,11 @@ class OAuth(Mapping):
It is required to create application first and put application credentials.
Attributes:
client_id(str): application client id
client_secret(str): application client secret key
provider(aioauth_client.OAuth2Client): provider class, should be one of aiohttp-client provided classes
redirect_uri(str): redirect URI registered in provider
scopes(str): list of scopes required by the application
client_id(str): application client id
client_secret(str): application client secret key
provider(aioauth_client.OAuth2Client): provider class, should be one of aiohttp-client provided classes
redirect_uri(str): redirect URI registered in provider
scopes(str): list of scopes required by the application
"""
def __init__(self, configuration: Configuration, database: SQLite,
@ -47,9 +47,9 @@ class OAuth(Mapping):
default constructor
Args:
configuration(Configuration): configuration instance
database(SQLite): database instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.OAuth)
configuration(Configuration): configuration instance
database(SQLite): database instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.OAuth)
"""
Mapping.__init__(self, configuration, database, provider)
self.client_id = configuration.get("auth", "client_id")
@ -65,7 +65,7 @@ class OAuth(Mapping):
def auth_control(self) -> str:
"""
Returns:
str: login control as html code to insert
str: login control as html code to insert
"""
return """<a class="nav-link" href="/user-api/v1/login" title="login via OAuth2">login</a>"""
@ -75,13 +75,13 @@ class OAuth(Mapping):
load OAuth2 provider by name
Args:
name(str): name of the provider. Must be valid class defined in aioauth-client library
name(str): name of the provider. Must be valid class defined in aioauth-client library
Returns:
Type[aioauth_client.OAuth2Client]: loaded provider type
Type[aioauth_client.OAuth2Client]: loaded provider type
Raises:
InvalidOption: in case if invalid OAuth provider name supplied
InvalidOption: in case if invalid OAuth provider name supplied
"""
provider: Type[aioauth_client.OAuth2Client] = getattr(aioauth_client, name)
try:
@ -97,7 +97,7 @@ class OAuth(Mapping):
load client from parameters
Returns:
aioauth_client.OAuth2Client: generated client according to current settings
aioauth_client.OAuth2Client: generated client according to current settings
"""
return self.provider(client_id=self.client_id, client_secret=self.client_secret)
@ -106,7 +106,7 @@ class OAuth(Mapping):
get authorization URI for the specified settings
Returns:
str: authorization URI as a string
str: authorization URI as a string
"""
client = self.get_client()
uri: str = client.get_authorize_url(scope=self.scopes, redirect_uri=self.redirect_uri)
@ -117,10 +117,10 @@ class OAuth(Mapping):
extract OAuth username from remote
Args:
code(str): authorization code provided by external service
code(str): authorization code provided by external service
Returns:
Optional[str]: username as is in OAuth provider
Optional[str]: username as is in OAuth provider
"""
try:
client = self.get_client()

View File

@ -30,7 +30,7 @@ class Sources:
helper to download package sources (PKGBUILD etc)
Attributes:
logger(logging.Logger): (class attribute) class logger
logger(logging.Logger): (class attribute) class logger
"""
logger = logging.getLogger("build_details")
@ -44,8 +44,8 @@ class Sources:
track found files via git
Args:
sources_dir(Path): local path to git repository
*pattern(str): glob patterns
sources_dir(Path): local path to git repository
*pattern(str): glob patterns
"""
# glob directory to find files which match the specified patterns
found_files: List[Path] = []
@ -65,10 +65,10 @@ class Sources:
generate diff from the current version and write it to the output file
Args:
sources_dir(Path): local path to git repository
sources_dir(Path): local path to git repository
Returns:
str: patch as plain string
str: patch as plain string
"""
return Sources._check_output("git", "diff", exception=None, cwd=sources_dir, logger=Sources.logger)
@ -78,8 +78,8 @@ class Sources:
either clone repository or update it to origin/`branch`
Args:
sources_dir(Path): local path to fetch
remote(Optional[str]): remote target (from where to fetch)
sources_dir(Path): local path to fetch
remote(Optional[str]): remote target (from where to fetch)
"""
# local directory exists and there is .git directory
is_initialized_git = (sources_dir / ".git").is_dir()
@ -110,10 +110,10 @@ class Sources:
check if there are remotes for the repository
Args:
sources_dir(Path): local path to git repository
sources_dir(Path): local path to git repository
Returns:
bool: True in case if there is any remote and false otherwise
bool: True in case if there is any remote and false otherwise
"""
remotes = Sources._check_output("git", "remote", exception=None, cwd=sources_dir, logger=Sources.logger)
return bool(remotes)
@ -124,7 +124,7 @@ class Sources:
create empty git repository at the specified path
Args:
sources_dir(Path): local path to sources
sources_dir(Path): local path to sources
"""
Sources._check_output("git", "init", "--initial-branch", Sources._branch,
exception=None, cwd=sources_dir, logger=Sources.logger)
@ -135,9 +135,9 @@ class Sources:
fetch sources from remote and apply patches
Args:
sources_dir(Path): local path to fetch
remote(str): remote target (from where to fetch)
patch(Optional[str]): optional patch to be applied
sources_dir(Path): local path to fetch
remote(str): remote target (from where to fetch)
patch(Optional[str]): optional patch to be applied
"""
Sources.fetch(sources_dir, remote)
if patch is None:
@ -151,8 +151,8 @@ class Sources:
apply patches if any
Args:
sources_dir(Path): local path to directory with git sources
patch(str): patch to be applied
sources_dir(Path): local path to directory with git sources
patch(str): patch to be applied
"""
# create patch
Sources.logger.info("apply patch from database")
@ -165,11 +165,11 @@ class Sources:
create patch set for the specified local path
Args:
sources_dir(Path): local path to git repository
*pattern(str): glob patterns
sources_dir(Path): local path to git repository
*pattern(str): glob patterns
Returns:
str: patch as plain text
str: patch as plain text
"""
Sources.add(sources_dir, *pattern)
diff = Sources.diff(sources_dir)

View File

@ -37,11 +37,11 @@ class Task:
base package build task
Attributes:
build_logger(logging.Logger): logger for build process
logger(logging.Logger): class logger
package(Package): package definitions
paths(RepositoryPaths): repository paths instance
uid(int): uid of the repository owner user
build_logger(logging.Logger): logger for build process
logger(logging.Logger): class logger
package(Package): package definitions
paths(RepositoryPaths): repository paths instance
uid(int): uid of the repository owner user
"""
_check_output = check_output
@ -51,9 +51,9 @@ class Task:
default constructor
Args:
package(Package): package definitions
configuration(Configuration): configuration instance
paths(RepositoryPaths): repository paths instance
package(Package): package definitions
configuration(Configuration): configuration instance
paths(RepositoryPaths): repository paths instance
"""
self.logger = logging.getLogger("root")
self.build_logger = logging.getLogger("build_details")
@ -71,10 +71,10 @@ class Task:
run package build
Args:
sources_path(Path): path to where sources are
sources_path(Path): path to where sources are
Returns:
List[Path]: paths of produced packages
List[Path]: paths of produced packages
"""
command = [self.build_command, "-r", str(self.paths.chroot)]
command.extend(self.archbuild_flags)
@ -101,8 +101,8 @@ class Task:
fetch package from git
Args:
path(Path): local path to fetch
database(SQLite): database instance
path(Path): local path to fetch
database(SQLite): database instance
"""
if self.paths.cache_for(self.package.base).is_dir():
# no need to clone whole repository, just copy from cache first

View File

@ -36,12 +36,13 @@ class Configuration(configparser.RawConfigParser):
extension for built-in configuration parser
Attributes:
ARCHITECTURE_SPECIFIC_SECTIONS(List[str]): (class attribute) known sections which can be architecture specific (required by dump)
DEFAULT_LOG_FORMAT(str): (class attribute) default log format (in case of fallback)
DEFAULT_LOG_LEVEL(int): (class attribute) default log level (in case of fallback)
SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package
architecture(Optional[str]): repository architecture
path(Optional[Path]): path to root configuration file
ARCHITECTURE_SPECIFIC_SECTIONS(List[str]): (class attribute) known sections which can be architecture specific.
Required by dump and merging functions
DEFAULT_LOG_FORMAT(str): (class attribute) default log format (in case of fallback)
DEFAULT_LOG_LEVEL(int): (class attribute) default log level (in case of fallback)
SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package
architecture(Optional[str]): repository architecture
path(Optional[Path]): path to root configuration file
"""
DEFAULT_LOG_FORMAT = "[%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s"
@ -65,7 +66,7 @@ class Configuration(configparser.RawConfigParser):
def include(self) -> Path:
"""
Returns:
Path: path to directory with configuration includes
Path: path to directory with configuration includes
"""
return self.getpath("settings", "include")
@ -73,7 +74,7 @@ class Configuration(configparser.RawConfigParser):
def logging_path(self) -> Path:
"""
Returns:
Path: path to logging configuration
Path: path to logging configuration
"""
return self.getpath("settings", "logging")
@ -81,7 +82,7 @@ class Configuration(configparser.RawConfigParser):
def repository_paths(self) -> RepositoryPaths:
"""
Returns:
RepositoryPaths: repository paths instance
RepositoryPaths: repository paths instance
"""
_, architecture = self.check_loaded()
return RepositoryPaths(self.getpath("repository", "root"), architecture)
@ -92,12 +93,12 @@ class Configuration(configparser.RawConfigParser):
constructor with full object initialization
Args:
path(Path): path to root configuration file
architecture(str): repository architecture
quiet(bool): force disable any log messages
path(Path): path to root configuration file
architecture(str): repository architecture
quiet(bool): force disable any log messages
Returns:
Configuration: configuration instance
Configuration: configuration instance
"""
config = cls()
config.load(path)
@ -111,13 +112,13 @@ class Configuration(configparser.RawConfigParser):
convert string value to list of strings
Args:
value(str): string configuration value
value(str): string configuration value
Returns:
List[str]: list of string from the parsed string
List[str]: list of string from the parsed string
Raises:
ValueError: in case if option value contains unclosed quotes
ValueError: in case if option value contains unclosed quotes
"""
def generator() -> Generator[str, None, None]:
quote_mark = None
@ -127,7 +128,7 @@ class Configuration(configparser.RawConfigParser):
quote_mark = char
elif char == quote_mark: # quoted part ended, reset quotation
quote_mark = None
elif char == " " and quote_mark is None: # found space outside of the quotation, yield the word
elif char == " " and quote_mark is None: # found space outside the quotation, yield the word
yield word
word = ""
else: # append character to the buffer
@ -144,11 +145,11 @@ class Configuration(configparser.RawConfigParser):
generate section name for sections which depends on context
Args:
section(str): section name
suffix(str): session suffix, e.g. repository architecture
section(str): section name
suffix(str): session suffix, e.g. repository architecture
Returns:
str: correct section name for repository specific section
str: correct section name for repository specific section
"""
return f"{section}:{suffix}"
@ -157,10 +158,10 @@ class Configuration(configparser.RawConfigParser):
convert string value to path object
Args:
value(str): string configuration value
value(str): string configuration value
Returns:
Path: path object which represents the configuration value
Path: path object which represents the configuration value
"""
path = Path(value)
if self.path is None or path.is_absolute():
@ -172,10 +173,10 @@ class Configuration(configparser.RawConfigParser):
check if service was actually loaded
Returns:
Tuple[Path, str]: configuration root path and architecture if loaded
Tuple[Path, str]: configuration root path and architecture if loaded
Raises:
InitializeException: in case if architecture and/or path are not set
InitializeException: in case if architecture and/or path are not set
"""
if self.path is None or self.architecture is None:
raise InitializeException("Configuration path and/or architecture are not set")
@ -186,7 +187,7 @@ class Configuration(configparser.RawConfigParser):
dump configuration to dictionary
Returns:
Dict[str, Dict[str, str]]: configuration dump for specific architecture
Dict[str, Dict[str, str]]: configuration dump for specific architecture
"""
return {
section: dict(self[section])
@ -205,14 +206,14 @@ class Configuration(configparser.RawConfigParser):
Despite the fact that it has same semantics as other get* methods, but it has different argument list
Args:
section(str): section name
architecture(str): repository architecture
section(str): section name
architecture(str): repository architecture
Returns:
Tuple[str, str]: section name and found type name
Tuple[str, str]: section name and found type name
Raises:
configparser.NoSectionError: in case if no section found
configparser.NoSectionError: in case if no section found
"""
group_type = self.get(section, "type", fallback=None) # new-style logic
if group_type is not None:
@ -231,7 +232,7 @@ class Configuration(configparser.RawConfigParser):
fully load configuration
Args:
path(Path): path to root configuration file
path(Path): path to root configuration file
"""
if not path.is_file(): # fallback to the system file
path = self.SYSTEM_CONFIGURATION_PATH
@ -256,7 +257,7 @@ class Configuration(configparser.RawConfigParser):
setup logging settings from configuration
Args:
quiet(bool): force disable any log messages
quiet(bool): force disable any log messages
"""
try:
path = self.logging_path
@ -273,7 +274,7 @@ class Configuration(configparser.RawConfigParser):
merge architecture specific sections into main configuration
Args:
architecture(str): repository architecture
architecture(str): repository architecture
"""
self.architecture = architecture
for section in self.ARCHITECTURE_SPECIFIC_SECTIONS:
@ -306,9 +307,9 @@ class Configuration(configparser.RawConfigParser):
set option. Unlike default `configparser.RawConfigParser.set` it also creates section if it does not exist
Args:
section(str): section name
option(str): option name
value(Optional[str]): option value as string in parsable format
section(str): section name
option(str): option name
value(Optional[str]): option value as string in parsable format
"""
if not self.has_section(section):
self.add_section(section)

View File

@ -33,10 +33,10 @@ def migrate_data(result: MigrationResult, connection: Connection,
perform data migration
Args:
result(MigrationResult): result of the schema migration
connection(Connection): database connection
configuration(Configuration): configuration instance
paths(RepositoryPaths): repository paths instance
result(MigrationResult): result of the schema migration
connection(Connection): database connection
configuration(Configuration): configuration instance
paths(RepositoryPaths): repository paths instance
"""
# initial data migration
if result.old_version <= 0:

View File

@ -31,8 +31,8 @@ def migrate_package_statuses(connection: Connection, paths: RepositoryPaths) ->
perform migration for package statuses
Args:
connection(Connection): database connection
paths(RepositoryPaths): repository paths instance
connection(Connection): database connection
paths(RepositoryPaths): repository paths instance
"""
def insert_base(metadata: Package, last_status: BuildStatus) -> None:
connection.execute(

View File

@ -27,8 +27,8 @@ def migrate_patches(connection: Connection, paths: RepositoryPaths) -> None:
perform migration for patches
Args:
connection(Connection): database connection
paths(RepositoryPaths): repository paths instance
connection(Connection): database connection
paths(RepositoryPaths): repository paths instance
"""
root = paths.root / "patches"
if not root.is_dir():

View File

@ -27,8 +27,8 @@ def migrate_users_data(connection: Connection, configuration: Configuration) ->
perform migration for users
Args:
connection(Connection): database connection
configuration(Configuration): configuration instance
connection(Connection): database connection
configuration(Configuration): configuration instance
"""
for section in configuration.sections():
for option, value in configuration[section].items():

View File

@ -37,8 +37,8 @@ class Migrations:
idea comes from https://www.ash.dev/blog/simple-migration-system-in-sqlite/
Attributes:
connection(Connection): database connection
logger(logging.Logger): class logger
connection(Connection): database connection
logger(logging.Logger): class logger
"""
def __init__(self, connection: Connection) -> None:
@ -46,7 +46,7 @@ class Migrations:
default constructor
Args:
connection(Connection): database connection
connection(Connection): database connection
"""
self.connection = connection
self.logger = logging.getLogger("database")
@ -57,10 +57,10 @@ class Migrations:
perform migrations implicitly
Args:
connection(Connection): database connection
connection(Connection): database connection
Returns:
MigrationResult: current schema version
MigrationResult: current schema version
"""
return cls(connection).run()
@ -70,7 +70,7 @@ class Migrations:
idea comes from https://julienharbulot.com/python-dynamical-import.html
Returns:
List[Migration]: list of found migrations
List[Migration]: list of found migrations
"""
migrations: List[Migration] = []
package_dir = Path(__file__).resolve().parent
@ -89,7 +89,7 @@ class Migrations:
perform migrations
Return:
MigrationResult: current schema version
MigrationResult: current schema version
"""
migrations = self.migrations()
current_version = self.user_version()
@ -132,7 +132,7 @@ class Migrations:
get schema version from sqlite database
Returns:
int: current schema version
int: current schema version
"""
cursor = self.connection.execute("pragma user_version")
current_version: int = cursor.fetchone()["user_version"]

View File

@ -35,10 +35,10 @@ class AuthOperations(Operations):
get user by username
Args:
username(str): username
username(str): username
Returns:
Optional[User]: user if it was found
Optional[User]: user if it was found
"""
return next(iter(self.user_list(username, None)), None)
@ -47,11 +47,11 @@ class AuthOperations(Operations):
get users by filter
Args:
username(Optional[str]): optional filter by username
access(Optional[UserAccess]): optional filter by role
username(Optional[str]): optional filter by username
access(Optional[UserAccess]): optional filter by role
Returns:
List[User]: list of users who match criteria
List[User]: list of users who match criteria
"""
username_filter = username.lower() if username is not None else username
access_filter = access.value if access is not None else access
@ -74,7 +74,7 @@ class AuthOperations(Operations):
remove user from storage
Args:
username(str): username
username(str): username
"""
def run(connection: Connection) -> None:
connection.execute("""delete from users where username = :username""", {"username": username.lower()})
@ -86,7 +86,7 @@ class AuthOperations(Operations):
update user by username
Args:
user(User): user descriptor
user(User): user descriptor
"""
def run(connection: Connection) -> None:
connection.execute(

View File

@ -34,7 +34,7 @@ class BuildOperations(Operations):
remove packages from build queue
Args:
package_base(Optional[str]): optional filter by package base
package_base(Optional[str]): optional filter by package base
"""
def run(connection: Connection) -> None:
connection.execute(
@ -51,7 +51,7 @@ class BuildOperations(Operations):
retrieve packages from build queue
Return:
List[Package]: list of packages to be built
List[Package]: list of packages to be built
"""
def run(connection: Connection) -> List[Package]:
return [
@ -66,7 +66,7 @@ class BuildOperations(Operations):
insert packages to build queue
Args:
package(Package): package to be inserted
package(Package): package to be inserted
"""
def run(connection: Connection) -> None:
connection.execute(

View File

@ -33,8 +33,8 @@ class Operations:
base operation class
Attributes:
logger(logging.Logger): class logger
path(Path): path to the database file
logger(logging.Logger): class logger
path(Path): path to the database file
"""
def __init__(self, path: Path) -> None:
@ -42,7 +42,7 @@ class Operations:
default constructor
Args:
path(Path): path to the database file
path(Path): path to the database file
"""
self.path = path
self.logger = logging.getLogger("database")
@ -53,11 +53,11 @@ class Operations:
dictionary factory based on official documentation
Args:
cursor(Cursor): cursor descriptor
row(Tuple[Any, ...]): fetched row
cursor(Cursor): cursor descriptor
row(Tuple[Any, ...]): fetched row
Returns:
Dict[str, Any]: row converted to dictionary
Dict[str, Any]: row converted to dictionary
"""
result = {}
for index, column in enumerate(cursor.description):
@ -69,11 +69,11 @@ class Operations:
perform operation in connection
Args:
query(Callable[[Connection], T]): function to be called with connection
commit(bool, optional): if True commit() will be called on success (Default value = False)
query(Callable[[Connection], T]): function to be called with connection
commit(bool, optional): if True commit() will be called on success (Default value = False)
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:
connection.row_factory = self.factory

View File

@ -37,8 +37,8 @@ class PackageOperations(Operations):
remove package base information
Args:
connection(Connection): database connection
package_base(str): package base name
connection(Connection): database connection
package_base(str): package base name
"""
connection.execute("""delete from package_statuses where package_base = :package_base""",
{"package_base": package_base})
@ -51,9 +51,9 @@ class PackageOperations(Operations):
remove packages belong to the package base
Args:
connection(Connection): database connection
package_base(str): package base name
current_packages(Iterable[str]): current packages list which has to be left in database
connection(Connection): database connection
package_base(str): package base name
current_packages(Iterable[str]): current packages list which has to be left in database
"""
packages = [
package
@ -69,8 +69,8 @@ class PackageOperations(Operations):
insert base package into table
Args:
connection(Connection): database connection
package(Package): package properties
connection(Connection): database connection
package(Package): package properties
"""
connection.execute(
"""
@ -89,8 +89,8 @@ class PackageOperations(Operations):
insert packages into table
Args:
connection(Connection): database connection
package(Package): package properties
connection(Connection): database connection
package(Package): package properties
"""
package_list = []
for name, description in package.packages.items():
@ -118,9 +118,9 @@ class PackageOperations(Operations):
insert base package status into table
Args:
connection(Connection): database connection
package_base(str): package base name
status(BuildStatus): new build status
connection(Connection): database connection
package_base(str): package base name
status(BuildStatus): new build status
"""
connection.execute(
"""
@ -138,10 +138,10 @@ class PackageOperations(Operations):
select package bases from the table
Args:
connection(Connection): database connection
connection(Connection): database connection
Returns:
Dict[str, Package]: map of the package base to its descriptor (without packages themselves)
Dict[str, Package]: map of the package base to its descriptor (without packages themselves)
"""
return {
row["package_base"]: Package(row["package_base"], row["version"], row["aur_url"], {})
@ -154,11 +154,11 @@ class PackageOperations(Operations):
select packages from the table
Args:
connection(Connection): database connection
packages(Dict[str, Package]): packages descriptor map
connection(Connection): database connection
packages(Dict[str, Package]): packages descriptor map
Returns:
Dict[str, Package]: map of the package base to its descriptor including individual packages
Dict[str, Package]: map of the package base to its descriptor including individual packages
"""
for row in connection.execute("""select * from packages"""):
if row["package_base"] not in packages:
@ -172,10 +172,10 @@ class PackageOperations(Operations):
select package build statuses from the table
Args:
connection(Connection): database connection
connection(Connection): database connection
Returns:
Dict[str, BuildStatus]: map of the package base to its status
Dict[str, BuildStatus]: map of the package base to its status
"""
return {
row["package_base"]: BuildStatus.from_json({"status": row["status"], "timestamp": row["last_updated"]})
@ -187,7 +187,7 @@ class PackageOperations(Operations):
remove package from database
Args:
package_base(str): package base name
package_base(str): package base name
"""
def run(connection: Connection) -> None:
self._package_remove_packages(connection, package_base, [])
@ -200,8 +200,8 @@ class PackageOperations(Operations):
update package status
Args:
package(Package): package properties
status(BuildStatus): new build status
package(Package): package properties
status(BuildStatus): new build status
"""
def run(connection: Connection) -> None:
self._package_update_insert_base(connection, package)
@ -216,7 +216,7 @@ class PackageOperations(Operations):
get package list and their build statuses from database
Return:
List[Tuple[Package, BuildStatus]]: list of package properties and their statuses
List[Tuple[Package, BuildStatus]]: list of package properties and their statuses
"""
def run(connection: Connection) -> Generator[Tuple[Package, BuildStatus], None, None]:
packages = self._packages_get_select_package_bases(connection)

View File

@ -33,10 +33,10 @@ class PatchOperations(Operations):
retrieve patches for the package
Args:
package_base(str): package base to search for patches
package_base(str): package base to search for patches
Returns:
Optional[str]: plain text patch for the package
Optional[str]: plain text patch for the package
"""
return self.patches_list(package_base).get(package_base)
@ -45,8 +45,8 @@ class PatchOperations(Operations):
insert or update patch in database
Args:
package_base(str): package base to insert
patch(str): patch content
package_base(str): package base to insert
patch(str): patch content
"""
def run(connection: Connection) -> None:
connection.execute(
@ -67,10 +67,10 @@ class PatchOperations(Operations):
extract all patches
Args:
package_base(Optional[str]): optional filter by package base
package_base(Optional[str]): optional filter by package base
Returns:
Dict[str, str]: map of package base to patch content
Dict[str, str]: map of package base to patch content
"""
def run(connection: Connection) -> Dict[str, str]:
return {
@ -87,7 +87,7 @@ class PatchOperations(Operations):
remove patch set
Args:
package_base(str): package base to clear patches
package_base(str): package base to clear patches
"""
def run(connection: Connection) -> None:
connection.execute(

View File

@ -46,10 +46,10 @@ class SQLite(AuthOperations, BuildOperations, PackageOperations, PatchOperations
construct instance from configuration
Args:
configuration(Configuration): configuration instance
configuration(Configuration): configuration instance
Returns:
SQLite: fully initialized instance of the database
SQLite: fully initialized instance of the database
"""
path = cls.database_path(configuration)
database = cls(path)
@ -62,10 +62,10 @@ class SQLite(AuthOperations, BuildOperations, PackageOperations, PatchOperations
read database from configuration
Args:
configuration(Configuration): configuration instance
configuration(Configuration): configuration instance
Returns:
Path: database path according to the configuration
Path: database path according to the configuration
"""
return configuration.getpath("settings", "database")
@ -74,7 +74,7 @@ class SQLite(AuthOperations, BuildOperations, PackageOperations, PatchOperations
perform database migrations
Args:
configuration(Configuration): configuration instance
configuration(Configuration): configuration instance
"""
# custom types support
sqlite3.register_adapter(dict, json.dumps)

View File

@ -31,7 +31,7 @@ class BuildFailed(RuntimeError):
default constructor
Args:
package_base(str): package base raised exception
package_base(str): package base raised exception
"""
RuntimeError.__init__(self, f"Package {package_base} build failed, check logs for details")
@ -65,7 +65,7 @@ class InitializeException(RuntimeError):
default constructor
Args:
details(str): details of the exception
details(str): details of the exception
"""
RuntimeError.__init__(self, f"Could not load service: {details}")
@ -80,7 +80,7 @@ class InvalidOption(ValueError):
default constructor
Args:
value(Any): option value
value(Any): option value
"""
ValueError.__init__(self, f"Invalid or unknown option value `{value}`")
@ -95,8 +95,8 @@ class InvalidPath(ValueError):
default constructor
Args:
path(Path): path which raised an exception
root(Path): repository root (i.e. ahriman home)
path(Path): path which raised an exception
root(Path): repository root (i.e. ahriman home)
"""
ValueError.__init__(self, f"Path `{path}` does not belong to repository root `{root}`")
@ -111,7 +111,7 @@ class InvalidPackageInfo(RuntimeError):
default constructor
Args:
details(Any): error details
details(Any): error details
"""
RuntimeError.__init__(self, f"There are errors during reading package information: `{details}`")
@ -126,7 +126,7 @@ class MigrationError(RuntimeError):
default constructor
Args:
details(str): error details
details(str): error details
"""
RuntimeError.__init__(self, details)
@ -141,7 +141,7 @@ class MissingArchitecture(ValueError):
default constructor
Args:
command(str): command name which throws exception
command(str): command name which throws exception
"""
ValueError.__init__(self, f"Architecture required for subcommand {command}, but missing")
@ -156,7 +156,7 @@ class MultipleArchitectures(ValueError):
default constructor
Args:
command(str): command name which throws exception
command(str): command name which throws exception
"""
ValueError.__init__(self, f"Multiple architectures are not supported by subcommand {command}")
@ -183,7 +183,7 @@ class SuccessFailed(ValueError):
default constructor
Args:
package_base(str): package base name
package_base(str): package base name
"""
ValueError.__init__(self, f"Package base {package_base} had status failed, but new status is success")
@ -210,7 +210,7 @@ class UnknownPackage(ValueError):
default constructor
Args:
package_base(str): package base name
package_base(str): package base name
"""
ValueError.__init__(self, f"Package base {package_base} is unknown")
@ -225,8 +225,8 @@ class UnsafeRun(RuntimeError):
default constructor
Args:
current_uid(int): current user ID
root_uid(int): ID of the owner of root directory
current_uid(int): current user ID
root_uid(int): ID of the owner of root directory
"""
RuntimeError.__init__(self, f"Current UID {current_uid} differs from root owner {root_uid}. "
f"Note that for the most actions it is unsafe to run application as different user."

View File

@ -30,7 +30,7 @@ class AurPrinter(StringPrinter):
print content of the AUR package
Attributes:
package(AURPackage): AUR package description
package(AURPackage): AUR package description
"""
def __init__(self, package: AURPackage) -> None:
@ -38,7 +38,7 @@ class AurPrinter(StringPrinter):
default constructor
Args:
package(AURPackage): AUR package description
package(AURPackage): AUR package description
"""
StringPrinter.__init__(self, f"{package.name} {package.version} ({package.num_votes})")
self.package = package
@ -48,7 +48,7 @@ class AurPrinter(StringPrinter):
convert content into printable data
Returns:
List[Property]: list of content properties
List[Property]: list of content properties
"""
return [
Property("Package base", self.package.package_base),

View File

@ -31,9 +31,9 @@ class BuildPrinter(StringPrinter):
default constructor
Args:
package(Package): built package
is_success(bool): True in case if build has success status and False otherwise
use_utf(bool): use utf instead of normal symbols
package(Package): built package
is_success(bool): True in case if build has success status and False otherwise
use_utf(bool): use utf instead of normal symbols
"""
StringPrinter.__init__(self, f"{self.sign(is_success, use_utf)} {package.base}")
@ -43,11 +43,11 @@ class BuildPrinter(StringPrinter):
generate sign according to settings
Args:
is_success(bool): True in case if build has success status and False otherwise
use_utf(bool): use utf instead of normal symbols
is_success(bool): True in case if build has success status and False otherwise
use_utf(bool): use utf instead of normal symbols
Returns:
str: sign symbol according to current settings
str: sign symbol according to current settings
"""
if is_success:
return "[✔]" if use_utf else "[x]"

View File

@ -28,7 +28,7 @@ class ConfigurationPrinter(StringPrinter):
print content of the configuration section
Attributes:
values(Dict[str, str]): configuration values dictionary
values(Dict[str, str]): configuration values dictionary
"""
def __init__(self, section: str, values: Dict[str, str]) -> None:
@ -36,8 +36,8 @@ class ConfigurationPrinter(StringPrinter):
default constructor
Args:
section(str): section name
values(Dict[str, str]): configuration values dictionary
section(str): section name
values(Dict[str, str]): configuration values dictionary
"""
StringPrinter.__init__(self, f"[{section}]")
self.values = values
@ -47,7 +47,7 @@ class ConfigurationPrinter(StringPrinter):
convert content into printable data
Returns:
List[Property]: list of content properties
List[Property]: list of content properties
"""
return [
Property(key, value, is_required=True)

View File

@ -30,8 +30,8 @@ class PackagePrinter(StringPrinter):
print content of the internal package object
Attributes:
package(Package): package description
status(BuildStatus): build status
package(Package): package description
status(BuildStatus): build status
"""
def __init__(self, package: Package, status: BuildStatus) -> None:
@ -39,8 +39,8 @@ class PackagePrinter(StringPrinter):
default constructor
Args:
package(Package): package description
status(BuildStatus): build status
package(Package): package description
status(BuildStatus): build status
"""
StringPrinter.__init__(self, package.pretty_print())
self.package = package
@ -51,7 +51,7 @@ class PackagePrinter(StringPrinter):
convert content into printable data
Returns:
List[Property]: list of content properties
List[Property]: list of content properties
"""
return [
Property("Version", self.package.version, is_required=True),

View File

@ -32,10 +32,10 @@ class Printer:
print content
Args:
verbose(bool): print all fields
log_fn(Callable[[str]): logger function to log data
None]: (Default value = print)
separator(str, optional): separator for property name and property value (Default value = ": ")
verbose(bool): print all fields
log_fn(Callable[[str]): logger function to log data
None]: (Default value = print)
separator(str, optional): separator for property name and property value (Default value = ": ")
"""
if (title := self.title()) is not None:
log_fn(title)
@ -49,7 +49,7 @@ class Printer:
convert content into printable data
Returns:
List[Property]: list of content properties
List[Property]: list of content properties
"""
return []
@ -58,5 +58,5 @@ class Printer:
generate entry title from content
Returns:
Optional[str]: content title if it can be generated and None otherwise
Optional[str]: content title if it can be generated and None otherwise
"""

View File

@ -31,6 +31,6 @@ class StatusPrinter(StringPrinter):
default constructor
Args:
status(BuildStatus): build status
status(BuildStatus): build status
"""
StringPrinter.__init__(self, status.pretty_print())

View File

@ -32,7 +32,7 @@ class StringPrinter(Printer):
default constructor
Args:
content(str): any content string
content(str): any content string
"""
self.content = content
@ -41,6 +41,6 @@ class StringPrinter(Printer):
generate entry title from content
Returns:
Optional[str]: content title if it can be generated and None otherwise
Optional[str]: content title if it can be generated and None otherwise
"""
return self.content

View File

@ -29,8 +29,8 @@ class UpdatePrinter(StringPrinter):
print content of the package update
Attributes:
package(Package): remote (new) package object
local_version(Optional[str]): local version of the package if any
package(Package): remote (new) package object
local_version(Optional[str]): local version of the package if any
"""
def __init__(self, remote: Package, local_version: Optional[str]) -> None:
@ -38,8 +38,8 @@ class UpdatePrinter(StringPrinter):
default constructor
Args:
remote(Package): remote (new) package object
local_version(Optional[str]): local version of the package if any
remote(Package): remote (new) package object
local_version(Optional[str]): local version of the package if any
"""
StringPrinter.__init__(self, remote.base)
self.package = remote
@ -50,6 +50,6 @@ class UpdatePrinter(StringPrinter):
convert content into printable data
Returns:
List[Property]: list of content properties
List[Property]: list of content properties
"""
return [Property(self.local_version, self.package.version, is_required=True)]

View File

@ -29,7 +29,7 @@ class UserPrinter(StringPrinter):
print properties of user
Attributes:
user(User): stored user
user(User): stored user
"""
def __init__(self, user: User) -> None:
@ -37,7 +37,7 @@ class UserPrinter(StringPrinter):
default constructor
Args:
user(User): user to print
user(User): user to print
"""
StringPrinter.__init__(self, user.username)
self.user = user
@ -47,6 +47,6 @@ class UserPrinter(StringPrinter):
convert content into printable data
Returns:
List[Property]: list of content properties
List[Property]: list of content properties
"""
return [Property("role", self.user.access.value, is_required=True)]

View File

@ -31,7 +31,7 @@ class Console(Report):
html report generator
Attributes:
use_utf(bool): print utf8 symbols instead of ASCII
use_utf(bool): print utf8 symbols instead of ASCII
"""
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
@ -39,9 +39,9 @@ class Console(Report):
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
"""
Report.__init__(self, architecture, configuration)
self.use_utf = configuration.getboolean(section, "use_utf", fallback=True)
@ -51,8 +51,8 @@ class Console(Report):
generate report for the specified packages
Args:
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
"""
for package in result.success:
BuildPrinter(package, is_success=True, use_utf=self.use_utf).print(verbose=True)

View File

@ -38,16 +38,16 @@ class Email(Report, JinjaTemplate):
email report generator
Attributes:
full_template_path(Path): path to template for full package list
host(str): SMTP host to connect
no_empty_report(bool): skip empty report generation
password(Optional[str]): password to authenticate via SMTP
port(int): SMTP port to connect
receivers(List[str]): list of receivers emails
sender(str): sender email address
ssl(SmtpSSLSettings): SSL mode for SMTP connection
template_path(Path): path to template for built packages
user(Optional[str]): username to authenticate via SMTP
full_template_path(Path): path to template for full package list
host(str): SMTP host to connect
no_empty_report(bool): skip empty report generation
password(Optional[str]): password to authenticate via SMTP
port(int): SMTP port to connect
receivers(List[str]): list of receivers emails
sender(str): sender email address
ssl(SmtpSSLSettings): SSL mode for SMTP connection
template_path(Path): path to template for built packages
user(Optional[str]): username to authenticate via SMTP
"""
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
@ -55,9 +55,9 @@ class Email(Report, JinjaTemplate):
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
"""
Report.__init__(self, architecture, configuration)
JinjaTemplate.__init__(self, section, configuration)
@ -80,8 +80,8 @@ class Email(Report, JinjaTemplate):
send email callback
Args:
text(str): email body text
attachment(Dict[str, str]): map of attachment filename to attachment content
text(str): email body text
attachment(Dict[str, str]): map of attachment filename to attachment content
"""
message = MIMEMultipart()
message["From"] = self.sender
@ -110,8 +110,8 @@ class Email(Report, JinjaTemplate):
generate report for the specified packages
Args:
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
"""
if self.no_empty_report and not result.success:
return

View File

@ -31,8 +31,8 @@ class HTML(Report, JinjaTemplate):
html report generator
Attributes:
report_path(Path): output path to html report
template_path(Path): path to template for full package list
report_path(Path): output path to html report
template_path(Path): path to template for full package list
"""
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
@ -40,9 +40,9 @@ class HTML(Report, JinjaTemplate):
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
"""
Report.__init__(self, architecture, configuration)
JinjaTemplate.__init__(self, section, configuration)
@ -55,8 +55,8 @@ class HTML(Report, JinjaTemplate):
generate report for the specified packages
Args:
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
"""
html = self.make_html(Result(success=packages), self.template_path)
self.report_path.write_text(html)

View File

@ -56,11 +56,11 @@ class JinjaTemplate:
* repository - repository name, string, required
Attributes:
homepage(Optional[str]): homepage link if any (for footer)
link_path(str): prefix fo packages to download
name(str): repository name
default_pgp_key(Optional[str]): default PGP key
sign_targets(Set[SignSettings]): targets to sign enabled in configuration
homepage(Optional[str]): homepage link if any (for footer)
link_path(str): prefix fo packages to download
name(str): repository name
default_pgp_key(Optional[str]): default PGP key
sign_targets(Set[SignSettings]): targets to sign enabled in configuration
"""
def __init__(self, section: str, configuration: Configuration) -> None:
@ -68,8 +68,8 @@ class JinjaTemplate:
default constructor
Args:
section(str): settings section name
configuration(Configuration): configuration instance
section(str): settings section name
configuration(Configuration): configuration instance
"""
self.link_path = configuration.get(section, "link_path")
@ -84,8 +84,8 @@ class JinjaTemplate:
generate report for the specified packages
Args:
result(Result): build result
template_path(Path): path to jinja template
result(Result): build result
template_path(Path): path to jinja template
"""
# idea comes from https://stackoverflow.com/a/38642558
loader = jinja2.FileSystemLoader(searchpath=template_path.parent)

View File

@ -35,9 +35,9 @@ class Report:
base report generator
Attributes:
architecture(str): repository architecture
configuration(Configuration): configuration instance
logger(logging.Logger): class logger
architecture(str): repository architecture
configuration(Configuration): configuration instance
logger(logging.Logger): class logger
"""
def __init__(self, architecture: str, configuration: Configuration) -> None:
@ -45,8 +45,8 @@ class Report:
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
architecture(str): repository architecture
configuration(Configuration): configuration instance
"""
self.logger = logging.getLogger("root")
self.architecture = architecture
@ -58,12 +58,12 @@ class Report:
load client from settings
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
target(str): target to generate report aka section name (e.g. html)
architecture(str): repository architecture
configuration(Configuration): configuration instance
target(str): target to generate report aka section name (e.g. html)
Returns:
Report: client according to current settings
Report: client according to current settings
"""
section, provider_name = configuration.gettype(target, architecture)
provider = ReportSettings.from_option(provider_name)
@ -86,8 +86,8 @@ class Report:
generate report for the specified packages
Args:
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
"""
def run(self, packages: Iterable[Package], result: Result) -> None:
@ -95,11 +95,11 @@ class Report:
run report generation
Args:
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
Raises:
ReportFailed: in case of any report unmatched exception
ReportFailed: in case of any report unmatched exception
"""
try:
self.generate(packages, result)

View File

@ -35,12 +35,12 @@ class Telegram(Report, JinjaTemplate):
telegram report generator
Attributes:
TELEGRAM_API_URL(str): (class attribute) telegram api base url
TELEGRAM_MAX_CONTENT_LENGTH(int): (class attribute) max content length of the message
api_key(str): bot api key
chat_id(str): chat id to post message, either string with @ or integer
template_path(Path): path to template for built packages
template_type(str): template message type to be used in parse mode, one of MarkdownV2, HTML, Markdown
TELEGRAM_API_URL(str): (class attribute) telegram api base url
TELEGRAM_MAX_CONTENT_LENGTH(int): (class attribute) max content length of the message
api_key(str): bot api key
chat_id(str): chat id to post message, either string with @ or integer
template_path(Path): path to template for built packages
template_type(str): template message type to be used in parse mode, one of MarkdownV2, HTML, Markdown
"""
TELEGRAM_API_URL = "https://api.telegram.org"
@ -51,9 +51,9 @@ class Telegram(Report, JinjaTemplate):
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
"""
Report.__init__(self, architecture, configuration)
JinjaTemplate.__init__(self, section, configuration)
@ -68,7 +68,7 @@ class Telegram(Report, JinjaTemplate):
send message to telegram channel
Args:
text(str): message body text
text(str): message body text
"""
try:
response = requests.post(
@ -87,8 +87,8 @@ class Telegram(Report, JinjaTemplate):
generate report for the specified packages
Args:
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
"""
if not result.success:
return

View File

@ -35,10 +35,10 @@ class Cleaner(Properties):
get list of files in built packages directory
Returns:
List[Path]: list of filenames from the directory
List[Path]: list of filenames from the directory
Raises:
NotImplementedError: not implemented method
NotImplementedError: not implemented method
"""
raise NotImplementedError

View File

@ -41,13 +41,13 @@ class Executor(Cleaner):
load packages from list of archives
Args:
packages(Iterable[Path]): paths to package archives
packages(Iterable[Path]): paths to package archives
Returns:
List[Package]: list of read packages
List[Package]: list of read packages
Raises:
NotImplementedError: not implemented method
NotImplementedError: not implemented method
"""
raise NotImplementedError
@ -56,10 +56,10 @@ class Executor(Cleaner):
generate list of repository packages
Returns:
List[Package]: list of packages properties
List[Package]: list of packages properties
Raises:
NotImplementedError: not implemented method
NotImplementedError: not implemented method
"""
raise NotImplementedError
@ -68,10 +68,10 @@ class Executor(Cleaner):
build packages
Args:
updates(Iterable[Package]): list of packages properties to build
updates(Iterable[Package]): list of packages properties to build
Returns:
Result: build result
Result: build result
"""
def build_single(package: Package, local_path: Path) -> None:
self.reporter.set_building(package.base)
@ -100,10 +100,10 @@ class Executor(Cleaner):
remove packages from list
Args:
packages(Iterable[str]): list of package names or bases to remove
packages(Iterable[str]): list of package names or bases to remove
Returns:
Path: path to repository database
Path: path to repository database
"""
def remove_base(package_base: str) -> None:
try:
@ -148,8 +148,9 @@ class Executor(Cleaner):
generate reports
Args:
targets(Optional[Iterable[str]]): list of targets to generate reports. Configuration option will be used if it is not set
result(Result): build result
targets(Optional[Iterable[str]]): list of targets to generate reports. Configuration option will be used
if it is not set
result(Result): build result
"""
if targets is None:
targets = self.configuration.getlist("report", "target")
@ -162,8 +163,9 @@ class Executor(Cleaner):
process synchronization to remote servers
Args:
targets(Optional[Iterable[str]]): list of targets to sync. Configuration option will be used if it is not set
built_packages(Iterable[Package]): list of packages which has just been built
targets(Optional[Iterable[str]]): list of targets to sync. Configuration option will be used
if it is not set
built_packages(Iterable[Package]): list of packages which has just been built
"""
if targets is None:
targets = self.configuration.getlist("upload", "target")
@ -176,10 +178,10 @@ class Executor(Cleaner):
sign packages, add them to repository and update repository database
Args:
packages(Iterable[Path]): list of filenames to run
packages(Iterable[Path]): list of filenames to run
Returns:
Result: path to repository database
Result: path to repository database
"""
def update_single(name: Optional[str], base: str) -> None:
if name is None:

View File

@ -34,18 +34,18 @@ class Properties:
repository internal objects holder
Attributes:
architecture(str): repository architecture
aur_url(str): base AUR url
configuration(Configuration): configuration instance
database(SQLite): database instance
ignore_list(List[str]): package bases which will be ignored during auto updates
logger(logging.Logger): class logger
name(str): repository name
pacman(Pacman): alpm wrapper instance
paths(RepositoryPaths): repository paths instance
repo(Repo): repo commands wrapper instance
reporter(Client): build status reporter instance
sign(GPG): GPG wrapper instance
architecture(str): repository architecture
aur_url(str): base AUR url
configuration(Configuration): configuration instance
database(SQLite): database instance
ignore_list(List[str]): package bases which will be ignored during auto updates
logger(logging.Logger): class logger
name(str): repository name
pacman(Pacman): alpm wrapper instance
paths(RepositoryPaths): repository paths instance
repo(Repo): repo commands wrapper instance
reporter(Client): build status reporter instance
sign(GPG): GPG wrapper instance
"""
def __init__(self, architecture: str, configuration: Configuration, database: SQLite,
@ -54,11 +54,11 @@ class Properties:
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
database(SQLite): database instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
architecture(str): repository architecture
configuration(Configuration): configuration instance
database(SQLite): database instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
self.logger = logging.getLogger("root")
self.architecture = architecture

View File

@ -37,10 +37,10 @@ class Repository(Executor, UpdateHandler):
load packages from list of archives
Args:
packages(Iterable[Path]): paths to package archives
packages(Iterable[Path]): paths to package archives
Returns:
List[Package]: list of read packages
List[Package]: list of read packages
"""
result: Dict[str, Package] = {}
# we are iterating over bases, not single packages
@ -64,7 +64,7 @@ class Repository(Executor, UpdateHandler):
generate list of repository packages
Returns:
List[Package]: list of packages properties
List[Package]: list of packages properties
"""
return self.load_archives(filter(package_like, self.paths.repository.iterdir()))
@ -73,7 +73,7 @@ class Repository(Executor, UpdateHandler):
get list of files in built packages directory
Returns:
List[Path]: list of filenames from the directory
List[Path]: list of filenames from the directory
"""
return list(filter(package_like, self.paths.packages.iterdir()))
@ -82,10 +82,10 @@ class Repository(Executor, UpdateHandler):
extract list of packages which depends on specified package
Args:
depends_on(Optional[Iterable[str]]): dependencies of the packages
depends_on(Optional[Iterable[str]]): dependencies of the packages
Returns:
List[Package]: list of repository packages which depend on specified packages
List[Package]: list of repository packages which depend on specified packages
"""
packages = self.packages()
if depends_on is None:

View File

@ -35,10 +35,10 @@ class UpdateHandler(Cleaner):
generate list of repository packages
Returns:
List[Package]: list of packages properties
List[Package]: list of packages properties
Raises:
NotImplementedError: not implemented method
NotImplementedError: not implemented method
"""
raise NotImplementedError
@ -47,11 +47,11 @@ class UpdateHandler(Cleaner):
check AUR for updates
Args:
filter_packages(Iterable[str]): do not check every package just specified in the list
no_vcs(bool): do not check VCS packages
filter_packages(Iterable[str]): do not check every package just specified in the list
no_vcs(bool): do not check VCS packages
Returns:
List[Package]: list of packages which are out-of-dated
List[Package]: list of packages which are out-of-dated
"""
result: List[Package] = []
@ -81,7 +81,7 @@ class UpdateHandler(Cleaner):
check local packages for updates
Returns:
List[Package]: list of local packages which are out-of-dated
List[Package]: list of local packages which are out-of-dated
"""
result: List[Package] = []
packages = {local.base: local for local in self.packages()}
@ -110,7 +110,7 @@ class UpdateHandler(Cleaner):
check for packages for which manual update has been requested
Returns:
List[Package]: list of packages which are out-of-dated
List[Package]: list of packages which are out-of-dated
"""
result: List[Package] = []
known_bases = {package.base for package in self.packages()}

View File

@ -34,11 +34,11 @@ class GPG:
gnupg wrapper
Attributes:
architecture(str): repository architecture
configuration(Configuration): configuration instance
default_key(Optional[str]): default PGP key ID to use
logger(logging.Logger): class logger
targets(Set[SignSettings]): list of targets to sign (repository, package etc)
architecture(str): repository architecture
configuration(Configuration): configuration instance
default_key(Optional[str]): default PGP key ID to use
logger(logging.Logger): class logger
targets(Set[SignSettings]): list of targets to sign (repository, package etc)
"""
_check_output = check_output
@ -48,8 +48,8 @@ class GPG:
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
architecture(str): repository architecture
configuration(Configuration): configuration instance
"""
self.logger = logging.getLogger("build_details")
self.architecture = architecture
@ -60,7 +60,7 @@ class GPG:
def repository_sign_args(self) -> List[str]:
"""
Returns:
List[str]: command line arguments for repo-add command to sign database
List[str]: command line arguments for repo-add command to sign database
"""
if SignSettings.Repository not in self.targets:
return []
@ -75,11 +75,11 @@ class GPG:
gpg command to run
Args:
path(Path): path to file to sign
key(str): PGP key ID
path(Path): path to file to sign
key(str): PGP key ID
Returns:
List[str]: gpg command with all required arguments
List[str]: gpg command with all required arguments
"""
return ["gpg", "-u", key, "-b", str(path)]
@ -89,10 +89,10 @@ class GPG:
extract default sign options from configuration
Args:
configuration(Configuration): configuration instance
configuration(Configuration): configuration instance
Returns:
Tuple[Set[SignSettings], Optional[str]]: tuple of sign targets and default PGP key
Tuple[Set[SignSettings], Optional[str]]: tuple of sign targets and default PGP key
"""
targets: Set[SignSettings] = set()
for option in configuration.getlist("sign", "target"):
@ -108,11 +108,11 @@ class GPG:
download key from public PGP server
Args:
server(str): public PGP server which will be used to download the key
key(str): key ID to download
server(str): public PGP server which will be used to download the key
key(str): key ID to download
Returns:
str: key as plain text
str: key as plain text
"""
key = key if key.startswith("0x") else f"0x{key}"
try:
@ -132,8 +132,8 @@ class GPG:
import key to current user and sign it locally
Args:
server(str): public PGP server which will be used to download the key
key(str): key ID to import
server(str): public PGP server which will be used to download the key
key(str): key ID to import
"""
key_body = self.key_download(server, key)
GPG._check_output("gpg", "--import", input_data=key_body, exception=None, logger=self.logger)
@ -143,11 +143,11 @@ class GPG:
gpg command wrapper
Args:
path(Path): path to file to sign
key(str): PGP key ID
path(Path): path to file to sign
key(str): PGP key ID
Returns:
List[Path]: list of generated files including original file
List[Path]: list of generated files including original file
"""
GPG._check_output(
*GPG.sign_command(path, key),
@ -160,11 +160,11 @@ class GPG:
sign package if required by configuration
Args:
path(Path): path to file to sign
base(str): package base required to check for key overrides
path(Path): path to file to sign
base(str): package base required to check for key overrides
Returns:
List[Path]: list of generated files including original file
List[Path]: list of generated files including original file
"""
if SignSettings.Packages not in self.targets:
return [path]
@ -180,10 +180,10 @@ class GPG:
:note: more likely you just want to pass `repository_sign_args` to repo wrapper
Args:
path(Path): path to repository database
path(Path): path to repository database
Returns:
List[Path]: list of generated files including original file
List[Path]: list of generated files including original file
"""
if SignSettings.Repository not in self.targets:
return [path]

View File

@ -37,11 +37,11 @@ class Spawn(Thread):
MUST NOT be used directly, the only one usage allowed is to spawn process from web services
Attributes:
active(Dict[str, Process]): map of active child processes required to avoid zombies
architecture(str): repository architecture
configuration(Configuration): configuration instance
logger(logging.Logger): spawner logger
queue(Queue[Tuple[str, bool]]): multiprocessing queue to read updates from processes
active(Dict[str, Process]): map of active child processes required to avoid zombies
architecture(str): repository architecture
configuration(Configuration): configuration instance
logger(logging.Logger): spawner logger
queue(Queue[Tuple[str, bool]]): multiprocessing queue to read updates from processes
"""
def __init__(self, args_parser: argparse.ArgumentParser, architecture: str, configuration: Configuration) -> None:
@ -49,9 +49,9 @@ class Spawn(Thread):
default constructor
Args:
args_parser(argparse.ArgumentParser): command line parser for the application
architecture(str): repository architecture
configuration(Configuration): configuration instance
args_parser(argparse.ArgumentParser): command line parser for the application
architecture(str): repository architecture
configuration(Configuration): configuration instance
"""
Thread.__init__(self, name="spawn")
self.architecture = architecture
@ -71,11 +71,11 @@ class Spawn(Thread):
helper to run external process
Args:
callback(Callable[[argparse.Namespace, str], bool]): application run function (i.e. Handler.run method)
args(argparse.Namespace): command line arguments
architecture(str): repository architecture
process_id(str): process unique identifier
queue(Queue[Tuple[str, bool]]): output queue
callback(Callable[[argparse.Namespace, str], bool]): application run function (i.e. Handler.run method)
args(argparse.Namespace): command line arguments
architecture(str): repository architecture
process_id(str): process unique identifier
queue(Queue[Tuple[str, bool]]): output queue
"""
result = callback(args, architecture)
queue.put((process_id, result))
@ -85,8 +85,8 @@ class Spawn(Thread):
add packages
Args:
packages(Iterable[str]): packages list to add
now(bool): build packages now
packages(Iterable[str]): packages list to add
now(bool): build packages now
"""
kwargs = {"source": PackageSource.AUR.value} # avoid abusing by building non-aur packages
if now:
@ -98,7 +98,7 @@ class Spawn(Thread):
remove packages
Args:
packages(Iterable[str]): packages list to remove
packages(Iterable[str]): packages list to remove
"""
self.spawn_process("remove", *packages)
@ -107,9 +107,9 @@ class Spawn(Thread):
spawn external ahriman process with supplied arguments
Args:
command(str): subcommand to run
*args(str): positional command arguments
**kwargs(str): named command arguments
command(str): subcommand to run
*args(str): positional command arguments
**kwargs(str): named command arguments
"""
# default arguments
arguments = ["--architecture", self.architecture]

View File

@ -38,10 +38,10 @@ class Client:
load client from settings
Args:
configuration(Configuration): configuration instance
configuration(Configuration): configuration instance
Returns:
Client: client according to current settings
Client: client according to current settings
"""
address = configuration.get("web", "address", fallback=None)
host = configuration.get("web", "host", fallback=None)
@ -56,8 +56,8 @@ class Client:
add new package with status
Args:
package(Package): package properties
status(BuildStatusEnum): current package build status
package(Package): package properties
status(BuildStatusEnum): current package build status
"""
def get(self, base: Optional[str]) -> List[Tuple[Package, BuildStatus]]: # pylint: disable=no-self-use
@ -65,10 +65,10 @@ class Client:
get package status
Args:
base(Optional[str]): package base to get
base(Optional[str]): package base to get
Returns:
List[Tuple[Package, BuildStatus]]: list of current package description and status if it has been found
List[Tuple[Package, BuildStatus]]: list of current package description and status if it has been found
"""
del base
return []
@ -78,7 +78,7 @@ class Client:
get internal service status
Returns:
InternalStatus: current internal (web) service status
InternalStatus: current internal (web) service status
"""
return InternalStatus()
@ -87,7 +87,7 @@ class Client:
get ahriman status itself
Returns:
BuildStatus: current ahriman status
BuildStatus: current ahriman status
"""
return BuildStatus()
@ -96,7 +96,7 @@ class Client:
remove packages from watcher
Args:
base(str): package base to remove
base(str): package base to remove
"""
def update(self, base: str, status: BuildStatusEnum) -> None:
@ -104,8 +104,8 @@ class Client:
update package build status. Unlike `add` it does not update package properties
Args:
base(str): package base to update
status(BuildStatusEnum): current package build status
base(str): package base to update
status(BuildStatusEnum): current package build status
"""
def update_self(self, status: BuildStatusEnum) -> None:
@ -113,7 +113,7 @@ class Client:
update ahriman status itself
Args:
status(BuildStatusEnum): current ahriman status
status(BuildStatusEnum): current ahriman status
"""
def set_building(self, base: str) -> None:
@ -121,7 +121,7 @@ class Client:
set package status to building
Args:
base(str): package base to update
base(str): package base to update
"""
return self.update(base, BuildStatusEnum.Building)
@ -130,7 +130,7 @@ class Client:
set package status to failed
Args:
base(str): package base to update
base(str): package base to update
"""
return self.update(base, BuildStatusEnum.Failed)
@ -139,7 +139,7 @@ class Client:
set package status to pending
Args:
base(str): package base to update
base(str): package base to update
"""
return self.update(base, BuildStatusEnum.Pending)
@ -148,7 +148,7 @@ class Client:
set package status to success
Args:
package(Package): current package properties
package(Package): current package properties
"""
return self.add(package, BuildStatusEnum.Success)
@ -157,6 +157,6 @@ class Client:
set package status to unknown
Args:
package(Package): current package properties
package(Package): current package properties
"""
return self.add(package, BuildStatusEnum.Unknown)

View File

@ -34,12 +34,12 @@ class Watcher:
package status watcher
Attributes:
architecture(str): repository architecture
database(SQLite): database instance
known(Dict[str, Tuple[Package, BuildStatus]]): list of known packages. For the most cases `packages` should be used instead
logger(logging.Logger): class logger
repository(Repository): repository object
status(BuildStatus): daemon status
architecture(str): repository architecture
database(SQLite): database instance
known(Dict[str, Tuple[Package, BuildStatus]]): list of known packages. For the most cases `packages` should be used instead
logger(logging.Logger): class logger
repository(Repository): repository object
status(BuildStatus): daemon status
"""
def __init__(self, architecture: str, configuration: Configuration, database: SQLite) -> None:
@ -47,9 +47,9 @@ class Watcher:
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
database(SQLite): database instance
architecture(str): repository architecture
configuration(Configuration): configuration instance
database(SQLite): database instance
"""
self.logger = logging.getLogger("http")
@ -64,7 +64,7 @@ class Watcher:
def packages(self) -> List[Tuple[Package, BuildStatus]]:
"""
Returns:
List[Tuple[Package, BuildStatus]]: list of packages together with their statuses
List[Tuple[Package, BuildStatus]]: list of packages together with their statuses
"""
return list(self.known.values())
@ -73,13 +73,13 @@ class Watcher:
get current package base build status
Args:
base(str): package base
base(str): package base
Returns:
Tuple[Package, BuildStatus]: package and its status
Tuple[Package, BuildStatus]: package and its status
Raises:
UnknownPackage: if no package found
UnknownPackage: if no package found
"""
try:
return self.known[base]
@ -107,7 +107,7 @@ class Watcher:
remove package base from known list if any
Args:
package_base(str): package base
package_base(str): package base
"""
self.known.pop(package_base, None)
self.database.package_remove(package_base)
@ -117,12 +117,12 @@ class Watcher:
update package status and description
Args:
package_base(str): package base to update
status(BuildStatusEnum): new build status
package(Optional[Package]): optional new package description. In case if not set current properties will be used
package_base(str): package base to update
status(BuildStatusEnum): new build status
package(Optional[Package]): optional new package description. In case if not set current properties will be used
Raises:
UnknownPackage: if no package found
UnknownPackage: if no package found
"""
if package is None:
try:
@ -138,6 +138,6 @@ class Watcher:
update service status
Args:
status(BuildStatusEnum): new service status
status(BuildStatusEnum): new service status
"""
self.status = BuildStatus(status)

View File

@ -36,9 +36,9 @@ class WebClient(Client):
build status reporter web client
Attributes:
address(str): address of the web service
logger(logging.Logger): class logger
user(Optional[User]): web service user descriptor
address(str): address of the web service
logger(logging.Logger): class logger
user(Optional[User]): web service user descriptor
"""
def __init__(self, configuration: Configuration) -> None:
@ -46,7 +46,7 @@ class WebClient(Client):
default constructor
Args:
configuration(Configuration): configuration instance
configuration(Configuration): configuration instance
"""
self.logger = logging.getLogger("http")
self.address = self.parse_address(configuration)
@ -61,7 +61,7 @@ class WebClient(Client):
def _ahriman_url(self) -> str:
"""
Returns:
str: full url for web service for ahriman service itself
str: full url for web service for ahriman service itself
"""
return f"{self.address}/status-api/v1/ahriman"
@ -69,7 +69,7 @@ class WebClient(Client):
def _login_url(self) -> str:
"""
Returns:
str: full url for web service to login
str: full url for web service to login
"""
return f"{self.address}/user-api/v1/login"
@ -77,7 +77,7 @@ class WebClient(Client):
def _status_url(self) -> str:
"""
Returns:
str: full url for web service for status
str: full url for web service for status
"""
return f"{self.address}/status-api/v1/status"
@ -87,10 +87,10 @@ class WebClient(Client):
parse address from configuration
Args:
configuration(Configuration): configuration instance
configuration(Configuration): configuration instance
Returns:
str: valid http address
str: valid http address
"""
address = configuration.get("web", "address", fallback=None)
if not address:
@ -125,10 +125,10 @@ class WebClient(Client):
url generator
Args:
base(str, optional): package base to generate url (Default value = "")
base(str, optional): package base to generate url (Default value = "")
Returns:
str: full url of web service for specific package base
str: full url of web service for specific package base
"""
return f"{self.address}/status-api/v1/packages/{base}"
@ -137,8 +137,8 @@ class WebClient(Client):
add new package with status
Args:
package(Package): package properties
status(BuildStatusEnum): current package build status
package(Package): package properties
status(BuildStatusEnum): current package build status
"""
payload = {
"status": status.value,
@ -158,10 +158,10 @@ class WebClient(Client):
get package status
Args:
base(Optional[str]): package base to get
base(Optional[str]): package base to get
Returns:
List[Tuple[Package, BuildStatus]]: list of current package description and status if it has been found
List[Tuple[Package, BuildStatus]]: list of current package description and status if it has been found
"""
try:
response = self.__session.get(self._package_url(base or ""))
@ -183,7 +183,7 @@ class WebClient(Client):
get internal service status
Returns:
InternalStatus: current internal (web) service status
InternalStatus: current internal (web) service status
"""
try:
response = self.__session.get(self._status_url)
@ -202,7 +202,7 @@ class WebClient(Client):
get ahriman status itself
Returns:
BuildStatus: current ahriman status
BuildStatus: current ahriman status
"""
try:
response = self.__session.get(self._ahriman_url)
@ -221,7 +221,7 @@ class WebClient(Client):
remove packages from watcher
Args:
base(str): basename to remove
base(str): basename to remove
"""
try:
response = self.__session.delete(self._package_url(base))
@ -236,8 +236,8 @@ class WebClient(Client):
update package build status. Unlike `add` it does not update package properties
Args:
base(str): package base to update
status(BuildStatusEnum): current package build status
base(str): package base to update
status(BuildStatusEnum): current package build status
"""
payload = {"status": status.value}
@ -254,7 +254,7 @@ class WebClient(Client):
update ahriman status itself
Args:
status(BuildStatusEnum): current ahriman status
status(BuildStatusEnum): current ahriman status
"""
payload = {"status": status.value}

View File

@ -32,8 +32,8 @@ class Leaf:
tree leaf implementation
Attributes:
dependencies(Set[str]): list of package dependencies
package(Package): leaf package properties
dependencies(Set[str]): list of package dependencies
package(Package): leaf package properties
"""
def __init__(self, package: Package, dependencies: Set[str]) -> None:
@ -41,8 +41,8 @@ class Leaf:
default constructor
Args:
package(Package): package properties
dependencies(Set[str]): package dependencies
package(Package): package properties
dependencies(Set[str]): package dependencies
"""
self.package = package
self.dependencies = dependencies
@ -51,7 +51,7 @@ class Leaf:
def items(self) -> Iterable[str]:
"""
Returns:
Iterable[str]: packages containing in this leaf
Iterable[str]: packages containing in this leaf
"""
return self.package.packages.keys()
@ -61,11 +61,11 @@ class Leaf:
load leaf from package with dependencies
Args:
package(Package): package properties
database(SQLite): database instance
package(Package): package properties
database(SQLite): database instance
Returns:
Leaf: loaded class
Leaf: loaded class
"""
with tmpdir() as clone_dir:
Sources.load(clone_dir, package.git_url, database.patches_get(package.base))
@ -77,10 +77,10 @@ class Leaf:
check if package depends on any other package from list of not
Args:
packages(Iterable[Leaf]): list of known leaves
packages(Iterable[Leaf]): list of known leaves
Returns:
bool: True if any of packages is dependency of the leaf, False otherwise
bool: True if any of packages is dependency of the leaf, False otherwise
"""
for leaf in packages:
if self.dependencies.intersection(leaf.items):
@ -93,7 +93,7 @@ class Tree:
dependency tree implementation
Attributes:
leaves[List[Leaf]): list of tree leaves
leaves[List[Leaf]): list of tree leaves
"""
def __init__(self, leaves: List[Leaf]) -> None:
@ -101,7 +101,7 @@ class Tree:
default constructor
Args:
leaves(List[Leaf]): leaves to build the tree
leaves(List[Leaf]): leaves to build the tree
"""
self.leaves = leaves
@ -111,11 +111,11 @@ class Tree:
load tree from packages
Args:
packages(Iterable[Package]): packages list
database(SQLite): database instance
packages(Iterable[Package]): packages list
database(SQLite): database instance
Returns:
Tree: loaded class
Tree: loaded class
"""
return cls([Leaf.load(package, database) for package in packages])
@ -124,7 +124,7 @@ class Tree:
get build levels starting from the packages which do not require any other package to build
Returns:
List[List[Package]]: list of packages lists
List[List[Package]]: list of packages lists
"""
result: List[List[Package]] = []

View File

@ -34,8 +34,8 @@ class Github(HttpUpload):
upload files to github releases
Attributes:
gh_owner(str): github repository owner
gh_repository(str): github repository name
github_owner(str): github repository owner
github_repository(str): github repository name
"""
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
@ -43,21 +43,21 @@ class Github(HttpUpload):
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
"""
HttpUpload.__init__(self, architecture, configuration, section)
self.gh_owner = configuration.get(section, "owner")
self.gh_repository = configuration.get(section, "repository")
self.github_owner = configuration.get(section, "owner")
self.github_repository = configuration.get(section, "repository")
def asset_remove(self, release: Dict[str, Any], name: str) -> None:
"""
remove asset from the release by name
Args:
release(Dict[str, Any]): release object
name(str): asset name
release(Dict[str, Any]): release object
name(str): asset name
"""
try:
asset = next(asset for asset in release["assets"] if asset["name"] == name)
@ -70,8 +70,8 @@ class Github(HttpUpload):
upload asset to the release
Args:
release(Dict[str, Any]): release object
path(Path): path to local file
release(Dict[str, Any]): release object
path(Path): path to local file
"""
exists = any(path.name == asset["name"] for asset in release["assets"])
if exists:
@ -86,10 +86,10 @@ class Github(HttpUpload):
get all local files and their calculated checksums
Args:
path(Path): local path to sync
path(Path): local path to sync
Returns:
Dict[Path, str]: map of path objects to its checksum
Dict[Path, str]: map of path objects to its checksum
"""
return {
local_file: self.calculate_hash(local_file)
@ -101,9 +101,9 @@ class Github(HttpUpload):
remove files from github
Args:
release(Dict[str, Any]): release object
local_files(Dict[Path, str]): map of local file paths to its checksum
remote_files(Dict[str, str]): map of the remote files and its checksum
release(Dict[str, Any]): release object
local_files(Dict[Path, str]): map of local file paths to its checksum
remote_files(Dict[str, str]): map of the remote files and its checksum
"""
local_filenames = {local_file.name for local_file in local_files}
for remote_file in remote_files:
@ -116,9 +116,9 @@ class Github(HttpUpload):
upload files to github
Args:
release(Dict[str, Any]): release object
local_files(Dict[Path, str]): map of local file paths to its checksum
remote_files(Dict[str, str]): map of the remote files and its checksum
release(Dict[str, Any]): release object
local_files(Dict[Path, str]): map of local file paths to its checksum
remote_files(Dict[str, str]): map of the remote files and its checksum
"""
for local_file, checksum in local_files.items():
remote_checksum = remote_files.get(local_file.name)
@ -131,10 +131,10 @@ class Github(HttpUpload):
create empty release
Returns:
Dict[str, Any]: github API release object for the new release
Dict[str, Any]: github API release object for the new release
"""
response = self._request("POST", f"https://api.github.com/repos/{self.gh_owner}/{self.gh_repository}/releases",
json={"tag_name": self.architecture, "name": self.architecture})
url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases"
response = self._request("POST", url, json={"tag_name": self.architecture, "name": self.architecture})
release: Dict[str, Any] = response.json()
return release
@ -143,12 +143,11 @@ class Github(HttpUpload):
get release object if any
Returns:
Optional[Dict[str, Any]]: github API release object if release found and None otherwise
Optional[Dict[str, Any]]: 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}"
try:
response = self._request(
"GET",
f"https://api.github.com/repos/{self.gh_owner}/{self.gh_repository}/releases/tags/{self.architecture}")
response = self._request("GET", url)
release: Dict[str, Any] = response.json()
return release
except requests.HTTPError as e:
@ -162,8 +161,8 @@ class Github(HttpUpload):
update release
Args:
release(Dict[str, Any]): release object
body(str): new release body
release(Dict[str, Any]): release object
body(str): new release body
"""
self._request("POST", release["url"], json={"body": body})
@ -172,8 +171,8 @@ class Github(HttpUpload):
sync data to remote server
Args:
path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built
path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built
"""
release = self.release_get()
if release is None:

View File

@ -33,7 +33,7 @@ class HttpUpload(Upload):
helper for the http based uploads
Attributes:
auth(Tuple[str, str]): HTTP auth object
auth(Tuple[str, str]): HTTP auth object
"""
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
@ -41,9 +41,9 @@ class HttpUpload(Upload):
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): configuration section name
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): configuration section name
"""
Upload.__init__(self, architecture, configuration)
password = configuration.get(section, "password")
@ -56,10 +56,10 @@ class HttpUpload(Upload):
calculate file checksum
Args:
path(Path): path to local file
path(Path): path to local file
Returns:
str: calculated checksum of the file
str: calculated checksum of the file
"""
with path.open("rb") as local_file:
md5 = hashlib.md5(local_file.read()) # nosec
@ -71,10 +71,10 @@ class HttpUpload(Upload):
generate release body from the checksums as returned from HttpUpload.get_hashes method
Args:
local_files(Dict[Path, str]): map of the paths to its checksum
local_files(Dict[Path, str]): map of the paths to its checksum
Returns:
str: body to be inserted into release
str: body to be inserted into release
"""
return "\n".join(f"{file.name} {md5}" for file, md5 in sorted(local_files.items()))
@ -84,10 +84,10 @@ class HttpUpload(Upload):
get checksums of the content from the repository
Args:
body(str): release string body object
body(str): release string body object
Returns:
Dict[str, str]: map of the filename to its checksum as it is written in body
Dict[str, str]: map of the filename to its checksum as it is written in body
"""
files = {}
for line in body.splitlines():
@ -100,12 +100,12 @@ class HttpUpload(Upload):
request wrapper
Args:
method(str): request method
url(str): request url
**kwargs(Any): request parameters to be passed as is
method(str): request method
url(str): request url
**kwargs(Any): request parameters to be passed as is
Returns:
requests.Response: request response object
requests.Response: request response object
"""
try:
response = requests.request(method, url, auth=self.auth, **kwargs)

View File

@ -31,8 +31,8 @@ class Rsync(Upload):
rsync wrapper
Attributes:
command(List[str]): command arguments for sync
remote(str): remote address to sync
command(List[str]): command arguments for sync
remote(str): remote address to sync
"""
_check_output = check_output
@ -42,9 +42,9 @@ class Rsync(Upload):
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
"""
Upload.__init__(self, architecture, configuration)
self.command = configuration.getlist(section, "command")
@ -55,7 +55,7 @@ class Rsync(Upload):
sync data to remote server
Args:
path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built
path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built
"""
Rsync._check_output(*self.command, str(path), self.remote, exception=None, logger=self.logger)

View File

@ -35,8 +35,8 @@ class S3(Upload):
boto3 wrapper
Attributes
bucket(Any): boto3 S3 bucket object
chunk_size(int): chunk size for calculating checksums
bucket(Any): boto3 S3 bucket object
chunk_size(int): chunk size for calculating checksums
"""
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
@ -44,9 +44,9 @@ class S3(Upload):
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
"""
Upload.__init__(self, architecture, configuration)
self.bucket = self.get_bucket(configuration, section)
@ -60,11 +60,11 @@ class S3(Upload):
For this method we have to define nosec because it is out of any security context and provided by AWS
Args:
path(Path): path to local file
chunk_size(int): read chunk size, which depends on client settings
path(Path): path to local file
chunk_size(int): read chunk size, which depends on client settings
Returns:
str: calculated entity tag for local file
str: calculated entity tag for local file
"""
md5s = []
with path.open("rb") as local_file:
@ -84,11 +84,11 @@ class S3(Upload):
create resource client from configuration
Args:
configuration(Configuration): configuration instance
section(str): settings section name
configuration(Configuration): configuration instance
section(str): settings section name
Returns:
Any: amazon client
Any: amazon client
"""
client = boto3.resource(service_name="s3",
region_name=configuration.get(section, "region"),
@ -102,8 +102,8 @@ class S3(Upload):
remove files which have been removed locally
Args:
local_files(Dict[Path, str]): map of local path object to its checksum
remote_objects(Dict[Path, Any]): map of remote path object to the remote s3 object
local_files(Dict[Path, str]): map of local path object to its checksum
remote_objects(Dict[Path, Any]): map of remote path object to the remote s3 object
"""
for local_file, remote_object in remote_objects.items():
if local_file in local_files:
@ -115,9 +115,9 @@ class S3(Upload):
upload changed files to s3
Args:
path(Path): local path to sync
local_files(Dict[Path, str]): map of local path object to its checksum
remote_objects(Dict[Path, Any]): map of remote path object to the remote s3 object
path(Path): local path to sync
local_files(Dict[Path, str]): map of local path object to its checksum
remote_objects(Dict[Path, Any]): map of remote path object to the remote s3 object
"""
for local_file, checksum in local_files.items():
remote_object = remote_objects.get(local_file)
@ -138,10 +138,10 @@ class S3(Upload):
get all local files and their calculated checksums
Args:
path(Path): local path to sync
path(Path): local path to sync
Returns:
Dict[Path, str]: map of path object to its checksum
Dict[Path, str]: map of path object to its checksum
"""
return {
local_file.relative_to(path): self.calculate_etag(local_file, self.chunk_size)
@ -153,7 +153,7 @@ class S3(Upload):
get all remote objects and their checksums
Returns:
Dict[Path, Any]: map of path object to the remote s3 object
Dict[Path, Any]: map of path object to the remote s3 object
"""
objects = self.bucket.objects.filter(Prefix=self.architecture)
return {Path(item.key).relative_to(self.architecture): item for item in objects}
@ -163,8 +163,8 @@ class S3(Upload):
sync data to remote server
Args:
path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built
path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built
"""
remote_objects = self.get_remote_objects()
local_files = self.get_local_files(path)

View File

@ -35,9 +35,9 @@ class Upload:
base remote sync class
Attributes:
architecture(str): repository architecture
configuration(Configuration): configuration instance
logger(logging.Logger): application logger
architecture(str): repository architecture
configuration(Configuration): configuration instance
logger(logging.Logger): application logger
"""
def __init__(self, architecture: str, configuration: Configuration) -> None:
@ -45,8 +45,8 @@ class Upload:
default constructor
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
architecture(str): repository architecture
configuration(Configuration): configuration instance
"""
self.logger = logging.getLogger("root")
self.architecture = architecture
@ -58,12 +58,12 @@ class Upload:
load client from settings
Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
target(str): target to run sync (e.g. s3)
architecture(str): repository architecture
configuration(Configuration): configuration instance
target(str): target to run sync (e.g. s3)
Returns:
Upload: client according to current settings
Upload: client according to current settings
"""
section, provider_name = configuration.gettype(target, architecture)
provider = UploadSettings.from_option(provider_name)
@ -83,11 +83,11 @@ class Upload:
run remote sync
Args:
path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built
path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built
Raises:
SyncFailed: in case of any synchronization unmatched exception
SyncFailed: in case of any synchronization unmatched exception
"""
try:
self.sync(path, built_packages)
@ -100,6 +100,6 @@ class Upload:
sync data to remote server
Args:
path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built
path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built
"""

View File

@ -39,18 +39,18 @@ def check_output(*args: str, exception: Optional[Exception], cwd: Optional[Path]
subprocess wrapper
Args:
*args(str): command line arguments
exception(Optional[Exception]): exception which has to be reraised instead of default subprocess exception
cwd(Optional[Path], optional): current working directory (Default value = None)
input_data(Optional[str], optional): data which will be written to command stdin (Default value = None)
logger(Optional[Logger], optional): logger to log command result if required (Default value = None)
user(Optional[int], optional): run process as specified user (Default value = None)
*args(str): command line arguments
exception(Optional[Exception]): exception which has to be reraised instead of default subprocess exception
cwd(Optional[Path], optional): current working directory (Default value = None)
input_data(Optional[str], optional): data which will be written to command stdin (Default value = None)
logger(Optional[Logger], optional): logger to log command result if required (Default value = None)
user(Optional[int], optional): run process as specified user (Default value = None)
Returns:
str: command output
str: command output
Raises:
subprocess.CalledProcessError: if subprocess ended with status code different from 0 and no exception supplied
subprocess.CalledProcessError: if subprocess ended with status code different from 0 and no exception supplied
"""
def log(single: str) -> None:
if logger is not None:
@ -92,11 +92,11 @@ def check_user(paths: RepositoryPaths, unsafe: bool) -> None:
check if current user is the owner of the root
Args:
paths(RepositoryPaths): repository paths object
unsafe(bool): if set no user check will be performed before path creation
paths(RepositoryPaths): repository paths object
unsafe(bool): if set no user check will be performed before path creation
Raises:
UnsafeRun: if root uid differs from current uid and check is enabled
UnsafeRun: if root uid differs from current uid and check is enabled
"""
if not paths.root.exists():
return # no directory found, skip check
@ -113,10 +113,10 @@ def exception_response_text(exception: requests.exceptions.HTTPError) -> str:
safe response exception text generation
Args:
exception(requests.exceptions.HTTPError): exception raised
exception(requests.exceptions.HTTPError): exception raised
Returns:
str: text of the response if it is not None and empty string otherwise
str: text of the response if it is not None and empty string otherwise
"""
result: str = exception.response.text if exception.response is not None else ""
return result
@ -127,11 +127,11 @@ def filter_json(source: Dict[str, Any], known_fields: Iterable[str]) -> Dict[str
filter json object by fields used for json-to-object conversion
Args:
source(Dict[str, Any]): raw json object
known_fields(Iterable[str]): list of fields which have to be known for the target object
source(Dict[str, Any]): raw json object
known_fields(Iterable[str]): list of fields which have to be known for the target object
Returns:
Dict[str, Any]: json object without unknown and empty fields
Dict[str, Any]: json object without unknown and empty fields
"""
return {key: value for key, value in source.items() if key in known_fields and value is not None}
@ -141,12 +141,12 @@ def full_version(epoch: Union[str, int, None], pkgver: str, pkgrel: str) -> str:
generate full version from components
Args:
epoch(Union[str, int, None]): package epoch if any
pkgver(str): package version
pkgrel(str): package release version (arch linux specific)
epoch(Union[str, int, None]): package epoch if any
pkgver(str): package version
pkgrel(str): package release version (arch linux specific)
Returns:
str: generated version
str: generated version
"""
prefix = f"{epoch}:" if epoch else ""
return f"{prefix}{pkgver}-{pkgrel}"
@ -157,10 +157,10 @@ def package_like(filename: Path) -> bool:
check if file looks like package
Args:
filename(Path): name of file to check
filename(Path): name of file to check
Returns:
bool: True in case if name contains `.pkg.` and not signature, False otherwise
bool: True in case if name contains `.pkg.` and not signature, False otherwise
"""
name = filename.name
return ".pkg." in name and not name.endswith(".sig")
@ -171,10 +171,10 @@ def pretty_datetime(timestamp: Optional[Union[datetime.datetime, float, int]]) -
convert datetime object to string
Args:
timestamp(Optional[Union[datetime.datetime, float, int]]): datetime to convert
timestamp(Optional[Union[datetime.datetime, float, int]]): datetime to convert
Returns:
str: pretty printable datetime as string
str: pretty printable datetime as string
"""
if timestamp is None:
return ""
@ -188,14 +188,14 @@ def pretty_size(size: Optional[float], level: int = 0) -> str:
convert size to string
Args:
size(Optional[float]): size to convert
level(int, optional): represents current units, 0 is B, 1 is KiB etc (Default value = 0)
size(Optional[float]): size to convert
level(int, optional): represents current units, 0 is B, 1 is KiB etc (Default value = 0)
Returns:
str: pretty printable size as string
str: pretty printable size as string
Raises:
InvalidOption: if size is more than 1TiB
InvalidOption: if size is more than 1TiB
"""
def str_level() -> str:
if level == 0:
@ -221,7 +221,7 @@ def tmpdir() -> Generator[Path, None, None]:
wrapper for tempfile to remove directory after all
Yields:
Path: path to the created directory
Path: path to the created directory
"""
path = Path(tempfile.mkdtemp())
try:
@ -236,10 +236,10 @@ def walk(directory_path: Path) -> Generator[Path, None, None]:
Credits to https://stackoverflow.com/a/64915960
Args:
directory_path(Path): root directory path
directory_path(Path): root directory path
Yields:
Path: all found files in given directory with full path
Path: all found files in given directory with full path
"""
for element in directory_path.iterdir():
if element.is_dir():

View File

@ -25,9 +25,9 @@ class Action(Enum):
base action enumeration
Attributes:
List(Action): (class attribute) list available values
Remove(Action): (class attribute) remove everything from local storage
Update(Action): (class attribute) update local storage or add to
List(Action): (class attribute) list available values
Remove(Action): (class attribute) remove everything from local storage
Update(Action): (class attribute) update local storage or add to
"""
List = "list"

View File

@ -34,26 +34,26 @@ class AURPackage:
AUR package descriptor
Attributes:
id(int): package ID
name(str): package name
package_base_id(int): package base ID
version(str): package base version
description(str): package base description
url(Optional[str]): package upstream URL
num_votes(int): number of votes for the package
polularity(float): package popularity
out_of_date(Optional[datetime.datetime]): package out of date timestamp if any
maintainer(Optional[str]): package maintainer
first_submitted(datetime.datetime): timestamp of the first package submission
last_modified(datetime.datetime): timestamp of the last package submission
url_path(str): AUR package path
depends(List[str]): list of package dependencies
make_depends(List[str]): list of package make dependencies
opt_depends(List[str]): list of package optional dependencies
conflicts(List[str]): conflicts list for the package
provides(List[str]): list of packages which this package provides
license(List[str]): list of package licenses
keywords(List[str]): list of package keywords
id(int): package ID
name(str): package name
package_base_id(int): package base ID
version(str): package base version
description(str): package base description
url(Optional[str]): package upstream URL
num_votes(int): number of votes for the package
polularity(float): package popularity
out_of_date(Optional[datetime.datetime]): package out of date timestamp if any
maintainer(Optional[str]): package maintainer
first_submitted(datetime.datetime): timestamp of the first package submission
last_modified(datetime.datetime): timestamp of the last package submission
url_path(str): AUR package path
depends(List[str]): list of package dependencies
make_depends(List[str]): list of package make dependencies
opt_depends(List[str]): list of package optional dependencies
conflicts(List[str]): conflicts list for the package
provides(List[str]): list of packages which this package provides
license(List[str]): list of package licenses
keywords(List[str]): list of package keywords
"""
id: int
@ -84,10 +84,10 @@ class AURPackage:
construct package descriptor from RPC properties
Args:
dump(Dict[str, Any]): json dump body
dump(Dict[str, Any]): json dump body
Returns:
AURPackage: AUR package descriptor
AURPackage: AUR package descriptor
"""
# filter to only known fields
known_fields = [pair.name for pair in fields(cls)]
@ -100,10 +100,10 @@ class AURPackage:
construct package descriptor from official repository RPC properties
Args:
dump(Dict[str, Any]): json dump body
dump(Dict[str, Any]): json dump body
Returns:
AURPackage: AUR package descriptor
AURPackage: AUR package descriptor
"""
return cls(
id=0,
@ -137,10 +137,10 @@ class AURPackage:
covert AUR RPC key names to package keys
Args:
descriptor(Dict[str, Any]): RPC package descriptor
descriptor(Dict[str, Any]): RPC package descriptor
Returns:
Dict[str, Any]: package descriptor with names converted to snake case
Dict[str, Any]: package descriptor with names converted to snake case
"""
identity_mapper: Callable[[Any], Any] = lambda value: value
value_mapper: Dict[str, Callable[[Any], Any]] = {

View File

@ -28,9 +28,9 @@ class AuthSettings(Enum):
web authorization type
Attributes:
Disabled(AuthSettings): (class attribute) authorization is disabled
Configuration(AuthSettings): (class attribute) configuration based authorization
OAuth(AuthSettings): (class attribute) OAuth based provider
Disabled(AuthSettings): (class attribute) authorization is disabled
Configuration(AuthSettings): (class attribute) configuration based authorization
OAuth(AuthSettings): (class attribute) OAuth based provider
"""
Disabled = "disabled"
@ -43,10 +43,10 @@ class AuthSettings(Enum):
construct value from configuration
Args:
value(str): configuration value
value(str): configuration value
Returns:
AuthSettings: parsed value
AuthSettings: parsed value
"""
if value.lower() in ("configuration", "mapping"):
return cls.Configuration
@ -58,7 +58,7 @@ class AuthSettings(Enum):
def is_enabled(self) -> bool:
"""
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 False

View File

@ -33,11 +33,11 @@ class BuildStatusEnum(Enum):
build status enumeration
Attributes:
Unknown(BuildStatusEnum): (class attribute) build status is unknown
Pending(BuildStatusEnum): (class attribute) package is out-of-dated and will be built soon
Building(BuildStatusEnum): (class attribute) package is building right now
Failed(BuildStatusEnum): (class attribute) package build failed
Success(BuildStatusEnum): (class attribute) package has been built without errors
Unknown(BuildStatusEnum): (class attribute) build status is unknown
Pending(BuildStatusEnum): (class attribute) package is out-of-dated and will be built soon
Building(BuildStatusEnum): (class attribute) package is building right now
Failed(BuildStatusEnum): (class attribute) package build failed
Success(BuildStatusEnum): (class attribute) package has been built without errors
"""
Unknown = "unknown"
@ -51,7 +51,7 @@ class BuildStatusEnum(Enum):
convert itself to shield.io badges color
Returns:
str: shields.io color
str: shields.io color
"""
if self == BuildStatusEnum.Pending:
return "yellow"
@ -68,7 +68,7 @@ class BuildStatusEnum(Enum):
converts itself to bootstrap color
Returns:
str: bootstrap color
str: bootstrap color
"""
if self == BuildStatusEnum.Pending:
return "warning"
@ -87,8 +87,8 @@ class BuildStatus:
build status holder
Attributes:
status(BuildStatusEnum): build status
timestamp(int): build status update time
status(BuildStatusEnum): build status
timestamp(int): build status update time
"""
status: BuildStatusEnum = BuildStatusEnum.Unknown
@ -106,10 +106,10 @@ class BuildStatus:
construct status properties from json dump
Args:
dump(Dict[str, Any]): json dump body
dump(Dict[str, Any]): json dump body
Returns:
BuildStatus: status properties
BuildStatus: status properties
"""
known_fields = [pair.name for pair in fields(cls)]
return cls(**filter_json(dump, known_fields))
@ -119,7 +119,7 @@ class BuildStatus:
generate pretty string representation
Returns:
str: print-friendly string
str: print-friendly string
"""
return f"{self.status.value} ({pretty_datetime(self.timestamp)})"
@ -128,7 +128,7 @@ class BuildStatus:
generate json status view
Returns:
Dict[str, Any]: json-friendly dictionary
Dict[str, Any]: json-friendly dictionary
"""
return {
"status": self.status.value,

View File

@ -33,12 +33,12 @@ class Counters:
package counters
Attributes:
total(int): total packages count
unknown(int): packages in unknown status count
pending(int): packages in pending status count
building(int): packages in building status count
failed(int): packages in failed status count
success(int): packages in success status count
total(int): total packages count
unknown(int): packages in unknown status count
pending(int): packages in pending status count
building(int): packages in building status count
failed(int): packages in failed status count
success(int): packages in success status count
"""
total: int
@ -54,10 +54,10 @@ class Counters:
construct counters from json dump
Args:
dump(Dict[str, Any]): json dump body
dump(Dict[str, Any]): json dump body
Returns:
Counters: status counters
Counters: status counters
"""
# filter to only known fields
known_fields = [pair.name for pair in fields(cls)]
@ -69,10 +69,10 @@ class Counters:
construct counters from packages statuses
Args:
packages(List[Tuple[Package, BuildStatus]]): list of package and their status as per watcher property
packages(List[Tuple[Package, BuildStatus]]): list of package and their status as per watcher property
Returns:
Counters: status counters
Counters: status counters
"""
per_status = {"total": len(packages)}
for _, status in packages:

View File

@ -31,10 +31,10 @@ class InternalStatus:
internal server status
Attributes:
architecture(Optional[str]): repository architecture
packages(Counters): packages statuses counter object
repository(Optional[str]): repository name
version(Optional[str]): service version
architecture(Optional[str]): repository architecture
packages(Counters): packages statuses counter object
repository(Optional[str]): repository name
version(Optional[str]): service version
"""
architecture: Optional[str] = None
@ -48,10 +48,10 @@ class InternalStatus:
construct internal status from json dump
Args:
dump(Dict[str, Any]): json dump body
dump(Dict[str, Any]): json dump body
Returns:
InternalStatus: internal status
InternalStatus: internal status
"""
counters = Counters.from_json(dump["packages"]) if "packages" in dump else Counters(total=0)
return cls(architecture=dump.get("architecture"),
@ -64,6 +64,6 @@ class InternalStatus:
generate json status view
Returns:
Dict[str, Any]: json-friendly dictionary
Dict[str, Any]: json-friendly dictionary
"""
return asdict(self)

View File

@ -27,9 +27,9 @@ class Migration:
migration implementation
Attributes:
index(int): migration position
name(str): migration name
steps(List[str]): migration steps
index(int): migration position
name(str): migration name
steps(List[str]): migration steps
"""
index: int

View File

@ -28,8 +28,8 @@ class MigrationResult:
migration result implementation model
Attributes:
old_version(int): old schema version before migrations
new_version(int): new schema version after migrations
old_version(int): old schema version before migrations
new_version(int): new schema version after migrations
"""
old_version: int
@ -39,10 +39,10 @@ class MigrationResult:
def is_outdated(self) -> bool:
"""
Returns:
bool: True in case if it requires migrations and False otherwise
bool: True in case if it requires migrations and False otherwise
Raises:
MigrationError: if old version is newer than new one or negative
MigrationError: if old version is newer than new one or negative
"""
self.validate()
return self.new_version > self.old_version

View File

@ -44,10 +44,10 @@ class Package:
package properties representation
Attributes:
aur_url(str): AUR root url
base(str): package base name
packages(Dict[str, PackageDescription): map of package names to their properties. Filled only on load from archive
version(str): package full version
aur_url(str): AUR root url
base(str): package base name
packages(Dict[str, PackageDescription): map of package names to their properties. Filled only on load from archive
version(str): package full version
"""
base: str
@ -61,7 +61,7 @@ class Package:
def depends(self) -> List[str]:
"""
Returns:
List[str]: sum of dependencies per arch package
List[str]: sum of dependencies per arch package
"""
return sorted(set(sum([package.depends for package in self.packages.values()], start=[])))
@ -69,7 +69,7 @@ class Package:
def git_url(self) -> str:
"""
Returns:
str: package git url to clone
str: package git url to clone
"""
return f"{self.aur_url}/{self.base}.git"
@ -77,7 +77,7 @@ class Package:
def groups(self) -> List[str]:
"""
Returns:
List[str]: sum of groups per each package
List[str]: sum of groups per each package
"""
return sorted(set(sum([package.groups for package in self.packages.values()], start=[])))
@ -85,7 +85,7 @@ class Package:
def is_single_package(self) -> bool:
"""
Returns:
bool: true in case if this base has only one package with the same name
bool: true in case if this base has only one package with the same name
"""
return self.base in self.packages and len(self.packages) == 1
@ -93,7 +93,7 @@ class Package:
def is_vcs(self) -> bool:
"""
Returns:
bool: True in case if package base looks like VCS package and false otherwise
bool: True in case if package base looks like VCS package and false otherwise
"""
return self.base.endswith("-bzr") \
or self.base.endswith("-csv")\
@ -106,7 +106,7 @@ class Package:
def licenses(self) -> List[str]:
"""
Returns:
List[str]: sum of licenses per each package
List[str]: sum of licenses per each package
"""
return sorted(set(sum([package.licenses for package in self.packages.values()], start=[])))
@ -114,7 +114,7 @@ class Package:
def web_url(self) -> str:
"""
Returns:
str: package AUR url
str: package AUR url
"""
return f"{self.aur_url}/packages/{self.base}"
@ -124,12 +124,12 @@ class Package:
construct package properties from package archive
Args:
path(Path): path to package archive
pacman(Pacman): alpm wrapper instance
aur_url(str): AUR root url
path(Path): path to package archive
pacman(Pacman): alpm wrapper instance
aur_url(str): AUR root url
Returns:
Package: package properties
Package: package properties
"""
package = pacman.handle.load_pkg(str(path))
return cls(package.base, package.version, aur_url,
@ -141,11 +141,11 @@ class Package:
construct package properties from AUR page
Args:
name(str): package name (either base or normal name)
aur_url(str): AUR root url
name(str): package name (either base or normal name)
aur_url(str): AUR root url
Returns:
Package: package properties
Package: package properties
"""
package = AUR.info(name)
return cls(package.package_base, package.version, aur_url, {package.name: PackageDescription()})
@ -156,14 +156,14 @@ class Package:
construct package properties from sources directory
Args:
path(Path): path to package sources directory
aur_url(str): AUR root url
path(Path): path to package sources directory
aur_url(str): AUR root url
Returns:
Package: package properties
Package: package properties
Raises:
InvalidPackageInfo: if there are parsing errors
InvalidPackageInfo: if there are parsing errors
"""
srcinfo, errors = parse_srcinfo((path / ".SRCINFO").read_text())
if errors:
@ -179,10 +179,10 @@ class Package:
construct package properties from json dump
Args:
dump(Dict[str, Any]): json dump body
dump(Dict[str, Any]): json dump body
Returns:
Package: package properties
Package: package properties
"""
packages = {
key: PackageDescription.from_json(value)
@ -200,11 +200,11 @@ class Package:
construct package properties from official repository page
Args:
name(str): package name (either base or normal name)
aur_url(str): AUR root url
name(str): package name (either base or normal name)
aur_url(str): AUR root url
Returns:
Package: package properties
Package: package properties
"""
package = Official.info(name)
return cls(package.package_base, package.version, aur_url, {package.name: PackageDescription()})
@ -215,16 +215,16 @@ class Package:
package constructor from available sources
Args:
package(str): one of path to sources directory, path to archive or package name/base
source(PackageSource): source of the package required to define the load method
pacman(Pacman): alpm wrapper instance (required to load from archive)
aur_url(str): AUR root url
package(str): one of path to sources directory, path to archive or package name/base
source(PackageSource): source of the package required to define the load method
pacman(Pacman): alpm wrapper instance (required to load from archive)
aur_url(str): AUR root url
Returns:
Package: package properties
Package: package properties
Raises:
InvalidPackageInfo: if supplied package source is not valid
InvalidPackageInfo: if supplied package source is not valid
"""
try:
resolved_source = source.resolve(package)
@ -248,13 +248,13 @@ class Package:
load dependencies from package sources
Args:
path(Path): path to package sources directory
path(Path): path to package sources directory
Returns:
Set[str]: list of package dependencies including makedepends array, but excluding packages from this base
Set[str]: list of package dependencies including makedepends array, but excluding packages from this base
Raises:
InvalidPackageInfo: if there are parsing errors
InvalidPackageInfo: if there are parsing errors
"""
# additional function to remove versions from dependencies
def extract_packages(raw_packages_list: List[str]) -> Set[str]:
@ -282,13 +282,13 @@ class Package:
additional method to handle VCS package versions
Args:
paths(RepositoryPaths): repository paths instance
paths(RepositoryPaths): repository paths instance
Returns:
str: package version if package is not VCS and current version according to VCS otherwise
str: package version if package is not VCS and current version according to VCS otherwise
Raises:
InvalidPackageInfo: if there are parsing errors
InvalidPackageInfo: if there are parsing errors
"""
if not self.is_vcs:
return self.version
@ -320,11 +320,11 @@ class Package:
generate full dependencies list including transitive dependencies
Args:
pacman(Pacman): alpm wrapper instance
packages(Iterable[Package]): repository package list
pacman(Pacman): alpm wrapper instance
packages(Iterable[Package]): repository package list
Returns:
List[str]: all dependencies of the package
List[str]: all dependencies of the package
"""
dependencies = {}
# load own package dependencies
@ -354,12 +354,12 @@ class Package:
check if package is out-of-dated
Args:
remote(Package): package properties from remote source
paths(RepositoryPaths): repository paths instance. Required for VCS packages cache
calculate_version(bool, optional): expand version to actual value (by calculating git versions) (Default value = True)
remote(Package): package properties from remote source
paths(RepositoryPaths): repository paths instance. Required for VCS packages cache
calculate_version(bool, optional): expand version to actual value (by calculating git versions) (Default value = True)
Returns:
bool: True if the package is out-of-dated and False otherwise
bool: True if the package is out-of-dated and False otherwise
"""
remote_version = remote.actual_version(paths) if calculate_version else remote.version
result: int = vercmp(self.version, remote_version)
@ -370,7 +370,7 @@ class Package:
generate pretty string representation
Returns:
str: print-friendly string
str: print-friendly string
"""
details = "" if self.is_single_package else f""" ({" ".join(sorted(self.packages.keys()))})"""
return f"{self.base}{details}"
@ -380,6 +380,6 @@ class Package:
generate json package view
Returns:
Dict[str, Any]: json-friendly dictionary
Dict[str, Any]: json-friendly dictionary
"""
return asdict(self)

View File

@ -33,17 +33,17 @@ class PackageDescription:
package specific properties
Attributes:
architecture(Optional[str]): package architecture
archive_size(Optional[int]): package archive size
build_date(Optional[int]): package build date
depends(List[str]): package dependencies list
description(Optional[str]): package description
filename(Optional[str]): package archive name
groups(List[str]): package groups
installed_size(Optional[int]): package installed size
licenses(List[str]): package licenses list
provides(List[str]): list of provided packages
url(Optional[str]): package url
architecture(Optional[str]): package architecture
archive_size(Optional[int]): package archive size
build_date(Optional[int]): package build date
depends(List[str]): package dependencies list
description(Optional[str]): package description
filename(Optional[str]): package archive name
groups(List[str]): package groups
installed_size(Optional[int]): package installed size
licenses(List[str]): package licenses list
provides(List[str]): list of provided packages
url(Optional[str]): package url
"""
architecture: Optional[str] = None
@ -62,7 +62,7 @@ class PackageDescription:
def filepath(self) -> Optional[Path]:
"""
Returns:
Optional[Path]: path object for current filename
Optional[Path]: path object for current filename
"""
return Path(self.filename) if self.filename is not None else None
@ -72,10 +72,10 @@ class PackageDescription:
construct package properties from json dump
Args:
dump(Dict[str, Any]): json dump body
dump(Dict[str, Any]): json dump body
Returns:
PackageDescription: package properties
PackageDescription: package properties
"""
# filter to only known fields
known_fields = [pair.name for pair in fields(cls)]
@ -87,11 +87,11 @@ class PackageDescription:
construct class from alpm package class
Args:
package(Package): alpm generated object
path(Path): path to package archive
package(Package): alpm generated object
path(Path): path to package archive
Returns:
PackageDescription: package properties based on tarball
PackageDescription: package properties based on tarball
"""
return cls(
architecture=package.arch,
@ -111,6 +111,6 @@ class PackageDescription:
generate json package view
Returns:
Dict[str, Any]: json-friendly dictionary
Dict[str, Any]: json-friendly dictionary
"""
return asdict(self)

View File

@ -31,13 +31,13 @@ class PackageSource(Enum):
package source for addition enumeration
Attributes:
Auto(PackageSource): (class attribute) automatically determine type of the source
Archive(PackageSource): (class attribute) source is a package archive
AUR(PackageSource): (class attribute) source is an AUR package for which it should search
Directory(PackageSource): (class attribute) source is a directory which contains packages
Local(PackageSource): (class attribute) source is locally stored PKGBUILD
Remote(PackageSource): (class attribute) source is remote (http, ftp etc) link
Repository(PackageSource): (class attribute) source is official repository
Auto(PackageSource): (class attribute) automatically determine type of the source
Archive(PackageSource): (class attribute) source is a package archive
AUR(PackageSource): (class attribute) source is an AUR package for which it should search
Directory(PackageSource): (class attribute) source is a directory which contains packages
Local(PackageSource): (class attribute) source is locally stored PKGBUILD
Remote(PackageSource): (class attribute) source is remote (http, ftp etc) link
Repository(PackageSource): (class attribute) source is official repository
"""
Auto = "auto"
@ -53,10 +53,10 @@ class PackageSource(Enum):
resolve auto into the correct type
Args:
source(str): source of the package
source(str): source of the package
Returns:
PackageSource: non-auto type of the package source
PackageSource: non-auto type of the package source
"""
if self != PackageSource.Auto:
return self

View File

@ -27,9 +27,9 @@ class Property:
holder of object properties descriptor
Attributes:
name(str): name of the property
value(Any): property value
is_required(bool): if set to True then this property is required
name(str): name of the property
value(Any): property value
is_required(bool): if set to True then this property is required
"""
name: str

View File

@ -28,11 +28,11 @@ class ReportSettings(Enum):
report targets enumeration
Attributes:
Disabled(ReportSettings): (class attribute) option which generates no report for testing purpose
HTML(ReportSettings): (class attribute) html report generation
Email(ReportSettings): (class attribute) email report generation
Console(ReportSettings): (class attribute) print result to console
Telegram(ReportSettings): (class attribute) markdown report to telegram channel
Disabled(ReportSettings): (class attribute) option which generates no report for testing purpose
HTML(ReportSettings): (class attribute) html report generation
Email(ReportSettings): (class attribute) email report generation
Console(ReportSettings): (class attribute) print result to console
Telegram(ReportSettings): (class attribute) markdown report to telegram channel
"""
Disabled = "disabled" # for testing purpose
@ -47,10 +47,10 @@ class ReportSettings(Enum):
construct value from configuration
Args:
value(str): configuration value
value(str): configuration value
Returns:
ReportSettings: parsed value
ReportSettings: parsed value
"""
if value.lower() in ("html",):
return cls.HTML

View File

@ -35,8 +35,8 @@ class RepositoryPaths:
repository paths holder. For the most operations with paths you want to use this object
Attributes:
root(Path): repository root (i.e. ahriman home)
architecture(str): repository architecture
root(Path): repository root (i.e. ahriman home)
architecture(str): repository architecture
"""
root: Path
@ -46,7 +46,7 @@ class RepositoryPaths:
def cache(self) -> Path:
"""
Returns:
Path: directory for packages cache (mainly used for VCS packages)
Path: directory for packages cache (mainly used for VCS packages)
"""
return self.root / "cache"
@ -54,7 +54,7 @@ class RepositoryPaths:
def chroot(self) -> Path:
"""
Returns:
Path: directory for devtools chroot
Path: directory for devtools chroot
"""
# for the chroot directory devtools will create own tree, and we don"t have to specify architecture here
return self.root / "chroot"
@ -63,7 +63,7 @@ class RepositoryPaths:
def packages(self) -> Path:
"""
Returns:
Path: directory for built packages
Path: directory for built packages
"""
return self.root / "packages" / self.architecture
@ -71,7 +71,7 @@ class RepositoryPaths:
def repository(self) -> Path:
"""
Returns:
Path: repository directory
Path: repository directory
"""
return self.root / "repository" / self.architecture
@ -79,7 +79,7 @@ class RepositoryPaths:
def root_owner(self) -> Tuple[int, int]:
"""
Returns:
Tuple[int, int]: owner user and group of the root directory
Tuple[int, int]: owner user and group of the root directory
"""
return self.owner(self.root)
@ -89,10 +89,10 @@ class RepositoryPaths:
get known architectures
Args:
root(Path): repository root
root(Path): repository root
Returns:
Set[str]: list of architectures for which tree is created
Set[str]: list of architectures for which tree is created
"""
paths = cls(root, "")
return {
@ -107,10 +107,10 @@ class RepositoryPaths:
retrieve owner information by path
Args:
path(Path): path for which extract ids
path(Path): path for which extract ids
Returns:
Tuple[int, int]: owner user and group ids of the directory
Tuple[int, int]: owner user and group ids of the directory
"""
stat = path.stat()
return stat.st_uid, stat.st_gid
@ -120,10 +120,10 @@ class RepositoryPaths:
get path to cached PKGBUILD and package sources for the package base
Args:
package_base(str): package base name
package_base(str): package base name
Returns:
Path: full path to directory for specified package base cache
Path: full path to directory for specified package base cache
"""
return self.cache / package_base
@ -132,10 +132,10 @@ class RepositoryPaths:
set owner of path recursively (from root) to root owner
Args:
path(Path): path to be chown
path(Path): path to be chown
Raises:
InvalidPath: if path does not belong to root
InvalidPath: if path does not belong to root
"""
def set_owner(current: Path) -> None:
uid, gid = self.owner(current)
@ -155,7 +155,7 @@ class RepositoryPaths:
clear package specific files
Args:
package_base(str): package base name
package_base(str): package base name
"""
for directory in (
self.cache_for(package_base),

View File

@ -35,8 +35,8 @@ class Result:
default constructor
Args:
success(Optional[Iterable[Package]], optional): initial list of successes packages (Default value = None)
failed(Optional[Iterable[Package]], optional): initial list of failed packages (Default value = None)
success(Optional[Iterable[Package]], optional): initial list of successes packages (Default value = None)
failed(Optional[Iterable[Package]], optional): initial list of failed packages (Default value = None)
"""
success = success or []
self._success = {package.base: package for package in success}
@ -47,7 +47,7 @@ class Result:
def failed(self) -> List[Package]:
"""
Returns:
List[Package]: list of packages which were failed
List[Package]: list of packages which were failed
"""
return list(self._failed.values())
@ -55,7 +55,7 @@ class Result:
def is_empty(self) -> bool:
"""
Returns:
bool: True in case if success list is empty and False otherwise
bool: True in case if success list is empty and False otherwise
"""
return not bool(self._success)
@ -63,7 +63,7 @@ class Result:
def success(self) -> List[Package]:
"""
Returns:
List[Package]: list of packages with success result
List[Package]: list of packages with success result
"""
return list(self._success.values())
@ -72,7 +72,7 @@ class Result:
add new package to failed built
Args:
package(Package): package with errors during build
package(Package): package with errors during build
"""
self._failed[package.base] = package
@ -81,7 +81,7 @@ class Result:
add new package to success built
Args:
package(Package): package built
package(Package): package built
"""
self._success[package.base] = package
@ -91,13 +91,13 @@ class Result:
merge other result into this one. This method assumes that other has fresh info about status and override it
Args:
other(Result): instance of the newest result
other(Result): instance of the newest result
Returns:
Result: updated instance
Result: updated instance
Raises:
SuccessFailed: if there is previously failed package which is masked as success
SuccessFailed: if there is previously failed package which is masked as success
"""
for base, package in other._failed.items():
if base in self._success:
@ -115,10 +115,10 @@ class Result:
check if other is the same object
Args:
other(Any): other object instance
other(Any): other object instance
Returns:
bool: True if the other object is the same and False otherwise
bool: True if the other object is the same and False otherwise
"""
if not isinstance(other, Result):
return False

Some files were not shown because too many files have changed in this diff Show More