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 formatter for the help message
Args: Args:
prog(str): application name prog(str): application name
Returns: Returns:
argparse.HelpFormatter: formatter used by default argparse.HelpFormatter: formatter used by default
""" """
return argparse.ArgumentDefaultsHelpFormatter(prog, width=120) return argparse.ArgumentDefaultsHelpFormatter(prog, width=120)
@ -58,7 +58,7 @@ def _parser() -> argparse.ArgumentParser:
command line parser generator command line parser generator
Returns: 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", parser = argparse.ArgumentParser(prog="ahriman", description="ArcH Linux ReposItory MANager",
epilog="Argument list can also be read from file by using @ prefix.", 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 add parser for AUR search subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("aur-search", aliases=["search"], help="search for package", parser = root.add_parser("aur-search", aliases=["search"], help="search for package",
description="search for package in AUR using API", formatter_class=_formatter) 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 add parser for listing help subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("help", help="show help message", parser = root.add_parser("help", help="show help message",
description="show help message for application or command and exit", 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 add parser for listing unsafe commands
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("help-commands-unsafe", help="list unsafe commands", parser = root.add_parser("help-commands-unsafe", help="list unsafe commands",
description="list unsafe commands as defined in default args", formatter_class=_formatter) 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 add parser for key import subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("key-import", help="import PGP key", parser = root.add_parser("key-import", help="import PGP key",
description="import PGP key from public sources to the repository user", 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 add parser for package addition subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("package-add", aliases=["add", "package-update"], help="add package", parser = root.add_parser("package-add", aliases=["add", "package-update"], help="add package",
description="add existing or new package to the build queue", 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 add parser for package removal subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("package-remove", aliases=["remove"], help="remove package", parser = root.add_parser("package-remove", aliases=["remove"], help="remove package",
description="remove package from the repository", formatter_class=_formatter) 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 add parser for package status subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("package-status", aliases=["status"], help="get package status", parser = root.add_parser("package-status", aliases=["status"], help="get package status",
description="request status of the package", 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 add parser for package status remove subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("package-status-remove", help="remove package status", parser = root.add_parser("package-status-remove", help="remove package status",
description="remove the package from the status page", 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 add parser for package status update subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: 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", 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) 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 add parser for new patch subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: 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", 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 " 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 add parser for list patches subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("patch-list", help="list patch sets", parser = root.add_parser("patch-list", help="list patch sets",
description="list available patches for the package", formatter_class=_formatter) 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 add parser for remove patches subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: 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", parser = root.add_parser("patch-remove", help="remove patch set", description="remove patches for the package",
formatter_class=_formatter) formatter_class=_formatter)
@ -375,10 +375,10 @@ def _set_repo_backup_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for repository backup subcommand add parser for repository backup subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-backup", help="backup repository data", parser = root.add_parser("repo-backup", help="backup repository data",
description="backup settings and database", formatter_class=_formatter) 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 add parser for repository check subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-check", aliases=["check"], help="check for updates", parser = root.add_parser("repo-check", aliases=["check"], help="check for updates",
description="check for packages updates. Same as update --dry-run --no-manual", 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 add parser for repository clean subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-clean", aliases=["clean"], help="clean local caches", parser = root.add_parser("repo-clean", aliases=["clean"], help="clean local caches",
description="remove local caches", description="remove local caches",
@ -436,10 +436,10 @@ def _set_repo_config_parser(root: SubParserAction) -> argparse.ArgumentParser:
add parser for config subcommand add parser for config subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-config", aliases=["config"], help="dump configuration", parser = root.add_parser("repo-config", aliases=["config"], help="dump configuration",
description="dump configuration for the specified architecture", 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 add parser for repository rebuild subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-rebuild", aliases=["rebuild"], help="rebuild repository", parser = root.add_parser("repo-rebuild", aliases=["rebuild"], help="rebuild repository",
description="force rebuild whole repository", formatter_class=_formatter) 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 add parser for remove unknown packages subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: 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", 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", 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 add parser for report subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-report", aliases=["report"], help="generate report", parser = root.add_parser("repo-report", aliases=["report"], help="generate report",
description="generate repository report according to current settings", 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 add parser for repository restore subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-restore", help="restore repository data", parser = root.add_parser("repo-restore", help="restore repository data",
description="restore settings and database", formatter_class=_formatter) 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 add parser for setup subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: 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", parser = root.add_parser("repo-setup", aliases=["init", "repo-init", "setup"], help="initial service configuration",
description="create initial service configuration, requires root", 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 add parser for sign subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-sign", aliases=["sign"], help="sign packages", parser = root.add_parser("repo-sign", aliases=["sign"], help="sign packages",
description="(re-)sign packages and repository database according to current settings", 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 add parser for repository status update subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-status-update", help="update repository status", parser = root.add_parser("repo-status-update", help="update repository status",
description="update repository status on the status page", formatter_class=_formatter) 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 add parser for repository sync subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-sync", aliases=["sync"], help="sync repository", parser = root.add_parser("repo-sync", aliases=["sync"], help="sync repository",
description="sync repository files to remote server according to current settings", 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 add parser for repository update subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-update", aliases=["update"], help="update packages", parser = root.add_parser("repo-update", aliases=["update"], help="update packages",
description="check for packages updates and run build process if requested", 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 add parser for create user subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("user-add", help="create or update user", parser = root.add_parser("user-add", help="create or update user",
description="update user for web services with the given password and role. " 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 add parser for user list subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("user-list", help="user known users and their access", parser = root.add_parser("user-list", help="user known users and their access",
description="list users from the user mapping and their roles", 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 add parser for user removal subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: Returns:
argparse.ArgumentParser: created argument parser argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("user-remove", help="remove user", parser = root.add_parser("user-remove", help="remove user",
description="remove user from the user mapping and update the configuration", 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 add parser for web subcommand
Args: Args:
root(SubParserAction): subparsers for the commands root(SubParserAction): subparsers for the commands
Returns: 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 = 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) 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 generate report and sync to remote server
Args: Args:
result(Result): build result result(Result): build result
""" """
self.report([], result) self.report([], result)
self.sync([], result.success) self.sync([], result.success)
@ -44,7 +44,7 @@ class Application(Packages, Repository):
load packages from repository and pacman repositories load packages from repository and pacman repositories
Returns: Returns:
Set[str]: list of known packages Set[str]: list of known packages
""" """
known_packages: Set[str] = set() known_packages: Set[str] = set()
# local set # local set

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,8 +36,8 @@ class Handler:
base handler class for command callbacks base handler class for command callbacks
Attributes: Attributes:
ALLOW_AUTO_ARCHITECTURE_RUN(bool): (class attribute) allow defining architecture from existing repositories 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_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
""" """
ALLOW_AUTO_ARCHITECTURE_RUN = True ALLOW_AUTO_ARCHITECTURE_RUN = True
@ -49,13 +49,13 @@ class Handler:
get known architectures get known architectures
Args: Args:
args(argparse.Namespace): command line args args(argparse.Namespace): command line args
Returns: Returns:
List[str]: list of architectures for which tree is created List[str]: list of architectures for which tree is created
Raises: 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: 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 # 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 additional function to wrap all calls for multiprocessing library
Args: Args:
args(argparse.Namespace): command line args args(argparse.Namespace): command line args
architecture(str): repository architecture architecture(str): repository architecture
Returns: Returns:
bool: True on success, False otherwise bool: True on success, False otherwise
""" """
try: try:
configuration = Configuration.from_path(args.configuration, architecture, args.quiet) configuration = Configuration.from_path(args.configuration, architecture, args.quiet)
@ -104,13 +104,13 @@ class Handler:
execute function for all aru execute function for all aru
Args: Args:
args(argparse.Namespace): command line args args(argparse.Namespace): command line args
Returns: Returns:
int: 0 on success, 1 otherwise int: 0 on success, 1 otherwise
Raises: 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) architectures = cls.architectures_extract(args)
@ -134,14 +134,14 @@ class Handler:
callback for command line callback for command line
Args: Args:
args(argparse.Namespace): command line args args(argparse.Namespace): command line args
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
no_report(bool): force disable reporting no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation unsafe(bool): if set no user check will be performed before path creation
Raises: Raises:
NotImplementedError: not implemented method NotImplementedError: not implemented method
""" """
raise NotImplementedError 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 check condition and flag and raise ExitCode exception in case if it is enabled and condition match
Args: Args:
enabled(bool): if False no check will be performed enabled(bool): if False no check will be performed
predicate(bool): indicates condition on which exception should be thrown predicate(bool): indicates condition on which exception should be thrown
Raises: Raises:
ExitCode: if result is empty and check is enabled ExitCode: if result is empty and check is enabled
""" """
if enabled and predicate: if enabled and predicate:
raise ExitCode() raise ExitCode()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -41,11 +41,11 @@ class UnsafeCommands(Handler):
callback for command line callback for command line
Args: Args:
args(argparse.Namespace): command line args args(argparse.Namespace): command line args
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
no_report(bool): force disable reporting no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation unsafe(bool): if set no user check will be performed before path creation
""" """
parser = args.parser() parser = args.parser()
unsafe_commands = UnsafeCommands.get_unsafe_commands(parser) unsafe_commands = UnsafeCommands.get_unsafe_commands(parser)
@ -61,9 +61,9 @@ class UnsafeCommands(Handler):
check if command is unsafe check if command is unsafe
Args: Args:
command(str): command to check command(str): command to check
unsafe_commands(List[str]): list of unsafe commands unsafe_commands(List[str]): list of unsafe commands
parser(argparse.ArgumentParser): generated argument parser parser(argparse.ArgumentParser): generated argument parser
""" """
args = parser.parse_args(shlex.split(command)) args = parser.parse_args(shlex.split(command))
UnsafeCommands.check_if_empty(True, args.command in unsafe_commands) UnsafeCommands.check_if_empty(True, args.command in unsafe_commands)
@ -74,10 +74,10 @@ class UnsafeCommands(Handler):
extract unsafe commands from argument parser extract unsafe commands from argument parser
Args: Args:
parser(argparse.ArgumentParser): generated argument parser parser(argparse.ArgumentParser): generated argument parser
Returns: Returns:
List[str]: list of commands with default unsafe flag List[str]: list of commands with default unsafe flag
""" """
# pylint: disable=protected-access # pylint: disable=protected-access
subparser = next(action for action in parser._actions if isinstance(action, argparse._SubParsersAction)) 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 callback for command line
Args: Args:
args(argparse.Namespace): command line args args(argparse.Namespace): command line args
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
no_report(bool): force disable reporting no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, no_report, unsafe) application = Application(architecture, configuration, no_report, unsafe)
packages = application.updates(args.package, args.no_aur, args.no_local, args.no_manual, args.no_vcs, 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 package updates log function
Args: Args:
application(Application): application instance application(Application): application instance
dry_run(bool): do not perform update itself dry_run(bool): do not perform update itself
Returns: 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: def inner(line: str) -> None:
return print(line) if dry_run else application.logger.info(line) return print(line) if dry_run else application.logger.info(line)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,10 +34,10 @@ class Auth:
helper to deal with user authorization helper to deal with user authorization
Attributes: Attributes:
enabled(bool): indicates if authorization is enabled enabled(bool): indicates if authorization is enabled
logger(logging.Logger): class logger logger(logging.Logger): class logger
max_age(int): session age in seconds. It will be used for both client side and server side checks 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 safe_build_status(bool): allow read only access to the index page
""" """
def __init__(self, configuration: Configuration, provider: AuthSettings = AuthSettings.Disabled) -> None: def __init__(self, configuration: Configuration, provider: AuthSettings = AuthSettings.Disabled) -> None:
@ -45,8 +45,8 @@ class Auth:
default constructor default constructor
Args: Args:
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Disabled) provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Disabled)
""" """
self.logger = logging.getLogger("http") self.logger = logging.getLogger("http")
@ -64,7 +64,7 @@ class Auth:
request to external resource request to external resource
Returns: 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>""" 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 load authorization module from settings
Args: Args:
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
database(SQLite): database instance database(SQLite): database instance
Returns: Returns:
Auth: authorization module according to current settings Auth: authorization module according to current settings
""" """
provider = AuthSettings.from_option(configuration.get("auth", "target", fallback="disabled")) provider = AuthSettings.from_option(configuration.get("auth", "target", fallback="disabled"))
if provider == AuthSettings.Configuration: if provider == AuthSettings.Configuration:
@ -94,11 +94,11 @@ class Auth:
validate user password validate user password
Args: Args:
username(Optional[str]): username username(Optional[str]): username
password(Optional[str]): entered password password(Optional[str]): entered password
Returns: Returns:
bool: True in case if password matches, False otherwise bool: True in case if password matches, False otherwise
""" """
del username, password del username, password
return True return True
@ -108,10 +108,10 @@ class Auth:
check if user is known check if user is known
Args: Args:
username(Optional[str]): username username(Optional[str]): username
Returns: 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 del username
return True return True
@ -121,12 +121,12 @@ class Auth:
validate if user has access to requested resource validate if user has access to requested resource
Args: Args:
username(str): username username(str): username
required(UserAccess): required access level required(UserAccess): required access level
context(Optional[str]): URI request path context(Optional[str]): URI request path
Returns: 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 del username, required, context
return True return True

View File

@ -31,10 +31,10 @@ async def authorized_userid(*args: Any) -> Any:
handle aiohttp security methods handle aiohttp security methods
Args: Args:
*args(Any): argument list as provided by authorized_userid function *args(Any): argument list as provided by authorized_userid function
Returns: 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: if _has_aiohttp_security:
return await aiohttp_security.authorized_userid(*args) # pylint: disable=no-value-for-parameter 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 handle aiohttp security methods
Args: Args:
*args(Any): argument list as provided by check_authorized function *args(Any): argument list as provided by check_authorized function
Returns: 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: if _has_aiohttp_security:
return await aiohttp_security.check_authorized(*args) # pylint: disable=no-value-for-parameter 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 handle aiohttp security methods
Args: Args:
*args(Any): argument list as provided by forget function *args(Any): argument list as provided by forget function
Returns: 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: if _has_aiohttp_security:
return await aiohttp_security.forget(*args) # pylint: disable=no-value-for-parameter 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 handle disabled auth
Args: Args:
*args(Any): argument list as provided by remember function *args(Any): argument list as provided by remember function
Returns: 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: if _has_aiohttp_security:
return await aiohttp_security.remember(*args) # pylint: disable=no-value-for-parameter 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 user authorization based on mapping from configuration file
Attributes: Attributes:
salt(str): random generated string to salt passwords salt(str): random generated string to salt passwords
database(SQLite): database instance database(SQLite): database instance
""" """
def __init__(self, configuration: Configuration, database: SQLite, def __init__(self, configuration: Configuration, database: SQLite,
@ -43,9 +43,9 @@ class Mapping(Auth):
default constructor default constructor
Args: Args:
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
database(SQLite): database instance database(SQLite): database instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Configuration) provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Configuration)
""" """
Auth.__init__(self, configuration, provider) Auth.__init__(self, configuration, provider)
self.database = database self.database = database
@ -56,11 +56,11 @@ class Mapping(Auth):
validate user password validate user password
Args: Args:
username(Optional[str]): username username(Optional[str]): username
password(Optional[str]): entered password password(Optional[str]): entered password
Returns: 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: if username is None or password is None:
return False # invalid data supplied return False # invalid data supplied
@ -72,10 +72,10 @@ class Mapping(Auth):
retrieve user from in-memory mapping retrieve user from in-memory mapping
Args: Args:
username(str): username username(str): username
Returns: 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) return self.database.user_get(username)
@ -84,10 +84,10 @@ class Mapping(Auth):
check if user is known check if user is known
Args: Args:
username(Optional[str]): username username(Optional[str]): username
Returns: 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 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 validate if user has access to requested resource
Args: Args:
username(str): username username(str): username
required(UserAccess): required access level required(UserAccess): required access level
context(Optional[str]): URI request path context(Optional[str]): URI request path
Returns: 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) user = self.get_user(username)
return user is not None and user.verify_access(required) 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. It is required to create application first and put application credentials.
Attributes: Attributes:
client_id(str): application client id client_id(str): application client id
client_secret(str): application client secret key client_secret(str): application client secret key
provider(aioauth_client.OAuth2Client): provider class, should be one of aiohttp-client provided classes provider(aioauth_client.OAuth2Client): provider class, should be one of aiohttp-client provided classes
redirect_uri(str): redirect URI registered in provider redirect_uri(str): redirect URI registered in provider
scopes(str): list of scopes required by the application scopes(str): list of scopes required by the application
""" """
def __init__(self, configuration: Configuration, database: SQLite, def __init__(self, configuration: Configuration, database: SQLite,
@ -47,9 +47,9 @@ class OAuth(Mapping):
default constructor default constructor
Args: Args:
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
database(SQLite): database instance database(SQLite): database instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.OAuth) provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.OAuth)
""" """
Mapping.__init__(self, configuration, database, provider) Mapping.__init__(self, configuration, database, provider)
self.client_id = configuration.get("auth", "client_id") self.client_id = configuration.get("auth", "client_id")
@ -65,7 +65,7 @@ class OAuth(Mapping):
def auth_control(self) -> str: def auth_control(self) -> str:
""" """
Returns: 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>""" 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 load OAuth2 provider by name
Args: 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: Returns:
Type[aioauth_client.OAuth2Client]: loaded provider type Type[aioauth_client.OAuth2Client]: loaded provider type
Raises: 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) provider: Type[aioauth_client.OAuth2Client] = getattr(aioauth_client, name)
try: try:
@ -97,7 +97,7 @@ class OAuth(Mapping):
load client from parameters load client from parameters
Returns: 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) 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 get authorization URI for the specified settings
Returns: Returns:
str: authorization URI as a string str: authorization URI as a string
""" """
client = self.get_client() client = self.get_client()
uri: str = client.get_authorize_url(scope=self.scopes, redirect_uri=self.redirect_uri) 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 extract OAuth username from remote
Args: Args:
code(str): authorization code provided by external service code(str): authorization code provided by external service
Returns: Returns:
Optional[str]: username as is in OAuth provider Optional[str]: username as is in OAuth provider
""" """
try: try:
client = self.get_client() client = self.get_client()

View File

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

View File

@ -37,11 +37,11 @@ class Task:
base package build task base package build task
Attributes: Attributes:
build_logger(logging.Logger): logger for build process build_logger(logging.Logger): logger for build process
logger(logging.Logger): class logger logger(logging.Logger): class logger
package(Package): package definitions package(Package): package definitions
paths(RepositoryPaths): repository paths instance paths(RepositoryPaths): repository paths instance
uid(int): uid of the repository owner user uid(int): uid of the repository owner user
""" """
_check_output = check_output _check_output = check_output
@ -51,9 +51,9 @@ class Task:
default constructor default constructor
Args: Args:
package(Package): package definitions package(Package): package definitions
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
paths(RepositoryPaths): repository paths instance paths(RepositoryPaths): repository paths instance
""" """
self.logger = logging.getLogger("root") self.logger = logging.getLogger("root")
self.build_logger = logging.getLogger("build_details") self.build_logger = logging.getLogger("build_details")
@ -71,10 +71,10 @@ class Task:
run package build run package build
Args: Args:
sources_path(Path): path to where sources are sources_path(Path): path to where sources are
Returns: Returns:
List[Path]: paths of produced packages List[Path]: paths of produced packages
""" """
command = [self.build_command, "-r", str(self.paths.chroot)] command = [self.build_command, "-r", str(self.paths.chroot)]
command.extend(self.archbuild_flags) command.extend(self.archbuild_flags)
@ -101,8 +101,8 @@ class Task:
fetch package from git fetch package from git
Args: Args:
path(Path): local path to fetch path(Path): local path to fetch
database(SQLite): database instance database(SQLite): database instance
""" """
if self.paths.cache_for(self.package.base).is_dir(): if self.paths.cache_for(self.package.base).is_dir():
# no need to clone whole repository, just copy from cache first # 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 extension for built-in configuration parser
Attributes: Attributes:
ARCHITECTURE_SPECIFIC_SECTIONS(List[str]): (class attribute) known sections which can be architecture specific (required by dump) ARCHITECTURE_SPECIFIC_SECTIONS(List[str]): (class attribute) known sections which can be architecture specific.
DEFAULT_LOG_FORMAT(str): (class attribute) default log format (in case of fallback) Required by dump and merging functions
DEFAULT_LOG_LEVEL(int): (class attribute) default log level (in case of fallback) DEFAULT_LOG_FORMAT(str): (class attribute) default log format (in case of fallback)
SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package DEFAULT_LOG_LEVEL(int): (class attribute) default log level (in case of fallback)
architecture(Optional[str]): repository architecture SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package
path(Optional[Path]): path to root configuration file 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" 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: def include(self) -> Path:
""" """
Returns: Returns:
Path: path to directory with configuration includes Path: path to directory with configuration includes
""" """
return self.getpath("settings", "include") return self.getpath("settings", "include")
@ -73,7 +74,7 @@ class Configuration(configparser.RawConfigParser):
def logging_path(self) -> Path: def logging_path(self) -> Path:
""" """
Returns: Returns:
Path: path to logging configuration Path: path to logging configuration
""" """
return self.getpath("settings", "logging") return self.getpath("settings", "logging")
@ -81,7 +82,7 @@ class Configuration(configparser.RawConfigParser):
def repository_paths(self) -> RepositoryPaths: def repository_paths(self) -> RepositoryPaths:
""" """
Returns: Returns:
RepositoryPaths: repository paths instance RepositoryPaths: repository paths instance
""" """
_, architecture = self.check_loaded() _, architecture = self.check_loaded()
return RepositoryPaths(self.getpath("repository", "root"), architecture) return RepositoryPaths(self.getpath("repository", "root"), architecture)
@ -92,12 +93,12 @@ class Configuration(configparser.RawConfigParser):
constructor with full object initialization constructor with full object initialization
Args: Args:
path(Path): path to root configuration file path(Path): path to root configuration file
architecture(str): repository architecture architecture(str): repository architecture
quiet(bool): force disable any log messages quiet(bool): force disable any log messages
Returns: Returns:
Configuration: configuration instance Configuration: configuration instance
""" """
config = cls() config = cls()
config.load(path) config.load(path)
@ -111,13 +112,13 @@ class Configuration(configparser.RawConfigParser):
convert string value to list of strings convert string value to list of strings
Args: Args:
value(str): string configuration value value(str): string configuration value
Returns: Returns:
List[str]: list of string from the parsed string List[str]: list of string from the parsed string
Raises: 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]: def generator() -> Generator[str, None, None]:
quote_mark = None quote_mark = None
@ -127,7 +128,7 @@ class Configuration(configparser.RawConfigParser):
quote_mark = char quote_mark = char
elif char == quote_mark: # quoted part ended, reset quotation elif char == quote_mark: # quoted part ended, reset quotation
quote_mark = None 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 yield word
word = "" word = ""
else: # append character to the buffer else: # append character to the buffer
@ -144,11 +145,11 @@ class Configuration(configparser.RawConfigParser):
generate section name for sections which depends on context generate section name for sections which depends on context
Args: Args:
section(str): section name section(str): section name
suffix(str): session suffix, e.g. repository architecture suffix(str): session suffix, e.g. repository architecture
Returns: Returns:
str: correct section name for repository specific section str: correct section name for repository specific section
""" """
return f"{section}:{suffix}" return f"{section}:{suffix}"
@ -157,10 +158,10 @@ class Configuration(configparser.RawConfigParser):
convert string value to path object convert string value to path object
Args: Args:
value(str): string configuration value value(str): string configuration value
Returns: Returns:
Path: path object which represents the configuration value Path: path object which represents the configuration value
""" """
path = Path(value) path = Path(value)
if self.path is None or path.is_absolute(): if self.path is None or path.is_absolute():
@ -172,10 +173,10 @@ class Configuration(configparser.RawConfigParser):
check if service was actually loaded check if service was actually loaded
Returns: Returns:
Tuple[Path, str]: configuration root path and architecture if loaded Tuple[Path, str]: configuration root path and architecture if loaded
Raises: 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: if self.path is None or self.architecture is None:
raise InitializeException("Configuration path and/or architecture are not set") raise InitializeException("Configuration path and/or architecture are not set")
@ -186,7 +187,7 @@ class Configuration(configparser.RawConfigParser):
dump configuration to dictionary dump configuration to dictionary
Returns: Returns:
Dict[str, Dict[str, str]]: configuration dump for specific architecture Dict[str, Dict[str, str]]: configuration dump for specific architecture
""" """
return { return {
section: dict(self[section]) 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 Despite the fact that it has same semantics as other get* methods, but it has different argument list
Args: Args:
section(str): section name section(str): section name
architecture(str): repository architecture architecture(str): repository architecture
Returns: Returns:
Tuple[str, str]: section name and found type name Tuple[str, str]: section name and found type name
Raises: 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 group_type = self.get(section, "type", fallback=None) # new-style logic
if group_type is not None: if group_type is not None:
@ -231,7 +232,7 @@ class Configuration(configparser.RawConfigParser):
fully load configuration fully load configuration
Args: 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 if not path.is_file(): # fallback to the system file
path = self.SYSTEM_CONFIGURATION_PATH path = self.SYSTEM_CONFIGURATION_PATH
@ -256,7 +257,7 @@ class Configuration(configparser.RawConfigParser):
setup logging settings from configuration setup logging settings from configuration
Args: Args:
quiet(bool): force disable any log messages quiet(bool): force disable any log messages
""" """
try: try:
path = self.logging_path path = self.logging_path
@ -273,7 +274,7 @@ class Configuration(configparser.RawConfigParser):
merge architecture specific sections into main configuration merge architecture specific sections into main configuration
Args: Args:
architecture(str): repository architecture architecture(str): repository architecture
""" """
self.architecture = architecture self.architecture = architecture
for section in self.ARCHITECTURE_SPECIFIC_SECTIONS: 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 set option. Unlike default `configparser.RawConfigParser.set` it also creates section if it does not exist
Args: Args:
section(str): section name section(str): section name
option(str): option name option(str): option name
value(Optional[str]): option value as string in parsable format value(Optional[str]): option value as string in parsable format
""" """
if not self.has_section(section): if not self.has_section(section):
self.add_section(section) self.add_section(section)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -31,7 +31,7 @@ class BuildFailed(RuntimeError):
default constructor default constructor
Args: 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") RuntimeError.__init__(self, f"Package {package_base} build failed, check logs for details")
@ -65,7 +65,7 @@ class InitializeException(RuntimeError):
default constructor default constructor
Args: Args:
details(str): details of the exception details(str): details of the exception
""" """
RuntimeError.__init__(self, f"Could not load service: {details}") RuntimeError.__init__(self, f"Could not load service: {details}")
@ -80,7 +80,7 @@ class InvalidOption(ValueError):
default constructor default constructor
Args: Args:
value(Any): option value value(Any): option value
""" """
ValueError.__init__(self, f"Invalid or unknown option value `{value}`") ValueError.__init__(self, f"Invalid or unknown option value `{value}`")
@ -95,8 +95,8 @@ class InvalidPath(ValueError):
default constructor default constructor
Args: Args:
path(Path): path which raised an exception path(Path): path which raised an exception
root(Path): repository root (i.e. ahriman home) root(Path): repository root (i.e. ahriman home)
""" """
ValueError.__init__(self, f"Path `{path}` does not belong to repository root `{root}`") ValueError.__init__(self, f"Path `{path}` does not belong to repository root `{root}`")
@ -111,7 +111,7 @@ class InvalidPackageInfo(RuntimeError):
default constructor default constructor
Args: Args:
details(Any): error details details(Any): error details
""" """
RuntimeError.__init__(self, f"There are errors during reading package information: `{details}`") RuntimeError.__init__(self, f"There are errors during reading package information: `{details}`")
@ -126,7 +126,7 @@ class MigrationError(RuntimeError):
default constructor default constructor
Args: Args:
details(str): error details details(str): error details
""" """
RuntimeError.__init__(self, details) RuntimeError.__init__(self, details)
@ -141,7 +141,7 @@ class MissingArchitecture(ValueError):
default constructor default constructor
Args: 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") ValueError.__init__(self, f"Architecture required for subcommand {command}, but missing")
@ -156,7 +156,7 @@ class MultipleArchitectures(ValueError):
default constructor default constructor
Args: 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}") ValueError.__init__(self, f"Multiple architectures are not supported by subcommand {command}")
@ -183,7 +183,7 @@ class SuccessFailed(ValueError):
default constructor default constructor
Args: 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") 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 default constructor
Args: Args:
package_base(str): package base name package_base(str): package base name
""" """
ValueError.__init__(self, f"Package base {package_base} is unknown") ValueError.__init__(self, f"Package base {package_base} is unknown")
@ -225,8 +225,8 @@ class UnsafeRun(RuntimeError):
default constructor default constructor
Args: Args:
current_uid(int): current user ID current_uid(int): current user ID
root_uid(int): ID of the owner of root directory root_uid(int): ID of the owner of root directory
""" """
RuntimeError.__init__(self, f"Current UID {current_uid} differs from root owner {root_uid}. " 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." 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 print content of the AUR package
Attributes: Attributes:
package(AURPackage): AUR package description package(AURPackage): AUR package description
""" """
def __init__(self, package: AURPackage) -> None: def __init__(self, package: AURPackage) -> None:
@ -38,7 +38,7 @@ class AurPrinter(StringPrinter):
default constructor default constructor
Args: Args:
package(AURPackage): AUR package description package(AURPackage): AUR package description
""" """
StringPrinter.__init__(self, f"{package.name} {package.version} ({package.num_votes})") StringPrinter.__init__(self, f"{package.name} {package.version} ({package.num_votes})")
self.package = package self.package = package
@ -48,7 +48,7 @@ class AurPrinter(StringPrinter):
convert content into printable data convert content into printable data
Returns: Returns:
List[Property]: list of content properties List[Property]: list of content properties
""" """
return [ return [
Property("Package base", self.package.package_base), Property("Package base", self.package.package_base),

View File

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

View File

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

View File

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

View File

@ -32,10 +32,10 @@ class Printer:
print content print content
Args: Args:
verbose(bool): print all fields verbose(bool): print all fields
log_fn(Callable[[str]): logger function to log data log_fn(Callable[[str]): logger function to log data
None]: (Default value = print) None]: (Default value = print)
separator(str, optional): separator for property name and property value (Default value = ": ") separator(str, optional): separator for property name and property value (Default value = ": ")
""" """
if (title := self.title()) is not None: if (title := self.title()) is not None:
log_fn(title) log_fn(title)
@ -49,7 +49,7 @@ class Printer:
convert content into printable data convert content into printable data
Returns: Returns:
List[Property]: list of content properties List[Property]: list of content properties
""" """
return [] return []
@ -58,5 +58,5 @@ class Printer:
generate entry title from content generate entry title from content
Returns: 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 default constructor
Args: Args:
status(BuildStatus): build status status(BuildStatus): build status
""" """
StringPrinter.__init__(self, status.pretty_print()) StringPrinter.__init__(self, status.pretty_print())

View File

@ -32,7 +32,7 @@ class StringPrinter(Printer):
default constructor default constructor
Args: Args:
content(str): any content string content(str): any content string
""" """
self.content = content self.content = content
@ -41,6 +41,6 @@ class StringPrinter(Printer):
generate entry title from content generate entry title from content
Returns: 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 return self.content

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,11 +34,11 @@ class GPG:
gnupg wrapper gnupg wrapper
Attributes: Attributes:
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
default_key(Optional[str]): default PGP key ID to use default_key(Optional[str]): default PGP key ID to use
logger(logging.Logger): class logger logger(logging.Logger): class logger
targets(Set[SignSettings]): list of targets to sign (repository, package etc) targets(Set[SignSettings]): list of targets to sign (repository, package etc)
""" """
_check_output = check_output _check_output = check_output
@ -48,8 +48,8 @@ class GPG:
default constructor default constructor
Args: Args:
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
""" """
self.logger = logging.getLogger("build_details") self.logger = logging.getLogger("build_details")
self.architecture = architecture self.architecture = architecture
@ -60,7 +60,7 @@ class GPG:
def repository_sign_args(self) -> List[str]: def repository_sign_args(self) -> List[str]:
""" """
Returns: 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: if SignSettings.Repository not in self.targets:
return [] return []
@ -75,11 +75,11 @@ class GPG:
gpg command to run gpg command to run
Args: Args:
path(Path): path to file to sign path(Path): path to file to sign
key(str): PGP key ID key(str): PGP key ID
Returns: Returns:
List[str]: gpg command with all required arguments List[str]: gpg command with all required arguments
""" """
return ["gpg", "-u", key, "-b", str(path)] return ["gpg", "-u", key, "-b", str(path)]
@ -89,10 +89,10 @@ class GPG:
extract default sign options from configuration extract default sign options from configuration
Args: Args:
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
Returns: 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() targets: Set[SignSettings] = set()
for option in configuration.getlist("sign", "target"): for option in configuration.getlist("sign", "target"):
@ -108,11 +108,11 @@ class GPG:
download key from public PGP server download key from public PGP server
Args: Args:
server(str): public PGP server which will be used to download the key server(str): public PGP server which will be used to download the key
key(str): key ID to download key(str): key ID to download
Returns: Returns:
str: key as plain text str: key as plain text
""" """
key = key if key.startswith("0x") else f"0x{key}" key = key if key.startswith("0x") else f"0x{key}"
try: try:
@ -132,8 +132,8 @@ class GPG:
import key to current user and sign it locally import key to current user and sign it locally
Args: Args:
server(str): public PGP server which will be used to download the key server(str): public PGP server which will be used to download the key
key(str): key ID to import key(str): key ID to import
""" """
key_body = self.key_download(server, key) key_body = self.key_download(server, key)
GPG._check_output("gpg", "--import", input_data=key_body, exception=None, logger=self.logger) GPG._check_output("gpg", "--import", input_data=key_body, exception=None, logger=self.logger)
@ -143,11 +143,11 @@ class GPG:
gpg command wrapper gpg command wrapper
Args: Args:
path(Path): path to file to sign path(Path): path to file to sign
key(str): PGP key ID key(str): PGP key ID
Returns: Returns:
List[Path]: list of generated files including original file List[Path]: list of generated files including original file
""" """
GPG._check_output( GPG._check_output(
*GPG.sign_command(path, key), *GPG.sign_command(path, key),
@ -160,11 +160,11 @@ class GPG:
sign package if required by configuration sign package if required by configuration
Args: Args:
path(Path): path to file to sign path(Path): path to file to sign
base(str): package base required to check for key overrides base(str): package base required to check for key overrides
Returns: 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: if SignSettings.Packages not in self.targets:
return [path] return [path]
@ -180,10 +180,10 @@ class GPG:
:note: more likely you just want to pass `repository_sign_args` to repo wrapper :note: more likely you just want to pass `repository_sign_args` to repo wrapper
Args: Args:
path(Path): path to repository database path(Path): path to repository database
Returns: 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: if SignSettings.Repository not in self.targets:
return [path] 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 MUST NOT be used directly, the only one usage allowed is to spawn process from web services
Attributes: Attributes:
active(Dict[str, Process]): map of active child processes required to avoid zombies active(Dict[str, Process]): map of active child processes required to avoid zombies
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
logger(logging.Logger): spawner logger logger(logging.Logger): spawner logger
queue(Queue[Tuple[str, bool]]): multiprocessing queue to read updates from processes queue(Queue[Tuple[str, bool]]): multiprocessing queue to read updates from processes
""" """
def __init__(self, args_parser: argparse.ArgumentParser, architecture: str, configuration: Configuration) -> None: def __init__(self, args_parser: argparse.ArgumentParser, architecture: str, configuration: Configuration) -> None:
@ -49,9 +49,9 @@ class Spawn(Thread):
default constructor default constructor
Args: Args:
args_parser(argparse.ArgumentParser): command line parser for the application args_parser(argparse.ArgumentParser): command line parser for the application
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
""" """
Thread.__init__(self, name="spawn") Thread.__init__(self, name="spawn")
self.architecture = architecture self.architecture = architecture
@ -71,11 +71,11 @@ class Spawn(Thread):
helper to run external process helper to run external process
Args: Args:
callback(Callable[[argparse.Namespace, str], bool]): application run function (i.e. Handler.run method) callback(Callable[[argparse.Namespace, str], bool]): application run function (i.e. Handler.run method)
args(argparse.Namespace): command line arguments args(argparse.Namespace): command line arguments
architecture(str): repository architecture architecture(str): repository architecture
process_id(str): process unique identifier process_id(str): process unique identifier
queue(Queue[Tuple[str, bool]]): output queue queue(Queue[Tuple[str, bool]]): output queue
""" """
result = callback(args, architecture) result = callback(args, architecture)
queue.put((process_id, result)) queue.put((process_id, result))
@ -85,8 +85,8 @@ class Spawn(Thread):
add packages add packages
Args: Args:
packages(Iterable[str]): packages list to add packages(Iterable[str]): packages list to add
now(bool): build packages now now(bool): build packages now
""" """
kwargs = {"source": PackageSource.AUR.value} # avoid abusing by building non-aur packages kwargs = {"source": PackageSource.AUR.value} # avoid abusing by building non-aur packages
if now: if now:
@ -98,7 +98,7 @@ class Spawn(Thread):
remove packages remove packages
Args: Args:
packages(Iterable[str]): packages list to remove packages(Iterable[str]): packages list to remove
""" """
self.spawn_process("remove", *packages) self.spawn_process("remove", *packages)
@ -107,9 +107,9 @@ class Spawn(Thread):
spawn external ahriman process with supplied arguments spawn external ahriman process with supplied arguments
Args: Args:
command(str): subcommand to run command(str): subcommand to run
*args(str): positional command arguments *args(str): positional command arguments
**kwargs(str): named command arguments **kwargs(str): named command arguments
""" """
# default arguments # default arguments
arguments = ["--architecture", self.architecture] arguments = ["--architecture", self.architecture]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -33,7 +33,7 @@ class HttpUpload(Upload):
helper for the http based uploads helper for the http based uploads
Attributes: 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: def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
@ -41,9 +41,9 @@ class HttpUpload(Upload):
default constructor default constructor
Args: Args:
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
section(str): configuration section name section(str): configuration section name
""" """
Upload.__init__(self, architecture, configuration) Upload.__init__(self, architecture, configuration)
password = configuration.get(section, "password") password = configuration.get(section, "password")
@ -56,10 +56,10 @@ class HttpUpload(Upload):
calculate file checksum calculate file checksum
Args: Args:
path(Path): path to local file path(Path): path to local file
Returns: Returns:
str: calculated checksum of the file str: calculated checksum of the file
""" """
with path.open("rb") as local_file: with path.open("rb") as local_file:
md5 = hashlib.md5(local_file.read()) # nosec 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 generate release body from the checksums as returned from HttpUpload.get_hashes method
Args: 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: 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())) 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 get checksums of the content from the repository
Args: Args:
body(str): release string body object body(str): release string body object
Returns: 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 = {} files = {}
for line in body.splitlines(): for line in body.splitlines():
@ -100,12 +100,12 @@ class HttpUpload(Upload):
request wrapper request wrapper
Args: Args:
method(str): request method method(str): request method
url(str): request url url(str): request url
**kwargs(Any): request parameters to be passed as is **kwargs(Any): request parameters to be passed as is
Returns: Returns:
requests.Response: request response object requests.Response: request response object
""" """
try: try:
response = requests.request(method, url, auth=self.auth, **kwargs) response = requests.request(method, url, auth=self.auth, **kwargs)

View File

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

View File

@ -35,9 +35,9 @@ class Upload:
base remote sync class base remote sync class
Attributes: Attributes:
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
logger(logging.Logger): application logger logger(logging.Logger): application logger
""" """
def __init__(self, architecture: str, configuration: Configuration) -> None: def __init__(self, architecture: str, configuration: Configuration) -> None:
@ -45,8 +45,8 @@ class Upload:
default constructor default constructor
Args: Args:
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
""" """
self.logger = logging.getLogger("root") self.logger = logging.getLogger("root")
self.architecture = architecture self.architecture = architecture
@ -58,12 +58,12 @@ class Upload:
load client from settings load client from settings
Args: Args:
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
target(str): target to run sync (e.g. s3) target(str): target to run sync (e.g. s3)
Returns: Returns:
Upload: client according to current settings Upload: client according to current settings
""" """
section, provider_name = configuration.gettype(target, architecture) section, provider_name = configuration.gettype(target, architecture)
provider = UploadSettings.from_option(provider_name) provider = UploadSettings.from_option(provider_name)
@ -83,11 +83,11 @@ class Upload:
run remote sync run remote sync
Args: Args:
path(Path): local path to sync path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built built_packages(Iterable[Package]): list of packages which has just been built
Raises: Raises:
SyncFailed: in case of any synchronization unmatched exception SyncFailed: in case of any synchronization unmatched exception
""" """
try: try:
self.sync(path, built_packages) self.sync(path, built_packages)
@ -100,6 +100,6 @@ class Upload:
sync data to remote server sync data to remote server
Args: Args:
path(Path): local path to sync path(Path): local path to sync
built_packages(Iterable[Package]): list of packages which has just been built 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 subprocess wrapper
Args: Args:
*args(str): command line arguments *args(str): command line arguments
exception(Optional[Exception]): exception which has to be reraised instead of default subprocess exception exception(Optional[Exception]): exception which has to be reraised instead of default subprocess exception
cwd(Optional[Path], optional): current working directory (Default value = None) 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) 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) 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) user(Optional[int], optional): run process as specified user (Default value = None)
Returns: Returns:
str: command output str: command output
Raises: 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: def log(single: str) -> None:
if logger is not 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 check if current user is the owner of the root
Args: Args:
paths(RepositoryPaths): repository paths object paths(RepositoryPaths): repository paths object
unsafe(bool): if set no user check will be performed before path creation unsafe(bool): if set no user check will be performed before path creation
Raises: 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(): if not paths.root.exists():
return # no directory found, skip check return # no directory found, skip check
@ -113,10 +113,10 @@ def exception_response_text(exception: requests.exceptions.HTTPError) -> str:
safe response exception text generation safe response exception text generation
Args: Args:
exception(requests.exceptions.HTTPError): exception raised exception(requests.exceptions.HTTPError): exception raised
Returns: 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 "" result: str = exception.response.text if exception.response is not None else ""
return result 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 filter json object by fields used for json-to-object conversion
Args: Args:
source(Dict[str, Any]): raw json object source(Dict[str, Any]): raw json object
known_fields(Iterable[str]): list of fields which have to be known for the target object known_fields(Iterable[str]): list of fields which have to be known for the target object
Returns: 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} 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 generate full version from components
Args: Args:
epoch(Union[str, int, None]): package epoch if any epoch(Union[str, int, None]): package epoch if any
pkgver(str): package version pkgver(str): package version
pkgrel(str): package release version (arch linux specific) pkgrel(str): package release version (arch linux specific)
Returns: Returns:
str: generated version str: generated version
""" """
prefix = f"{epoch}:" if epoch else "" prefix = f"{epoch}:" if epoch else ""
return f"{prefix}{pkgver}-{pkgrel}" return f"{prefix}{pkgver}-{pkgrel}"
@ -157,10 +157,10 @@ def package_like(filename: Path) -> bool:
check if file looks like package check if file looks like package
Args: Args:
filename(Path): name of file to check filename(Path): name of file to check
Returns: 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 name = filename.name
return ".pkg." in name and not name.endswith(".sig") 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 convert datetime object to string
Args: Args:
timestamp(Optional[Union[datetime.datetime, float, int]]): datetime to convert timestamp(Optional[Union[datetime.datetime, float, int]]): datetime to convert
Returns: Returns:
str: pretty printable datetime as string str: pretty printable datetime as string
""" """
if timestamp is None: if timestamp is None:
return "" return ""
@ -188,14 +188,14 @@ def pretty_size(size: Optional[float], level: int = 0) -> str:
convert size to string convert size to string
Args: Args:
size(Optional[float]): size to convert size(Optional[float]): size to convert
level(int, optional): represents current units, 0 is B, 1 is KiB etc (Default value = 0) level(int, optional): represents current units, 0 is B, 1 is KiB etc (Default value = 0)
Returns: Returns:
str: pretty printable size as string str: pretty printable size as string
Raises: Raises:
InvalidOption: if size is more than 1TiB InvalidOption: if size is more than 1TiB
""" """
def str_level() -> str: def str_level() -> str:
if level == 0: if level == 0:
@ -221,7 +221,7 @@ def tmpdir() -> Generator[Path, None, None]:
wrapper for tempfile to remove directory after all wrapper for tempfile to remove directory after all
Yields: Yields:
Path: path to the created directory Path: path to the created directory
""" """
path = Path(tempfile.mkdtemp()) path = Path(tempfile.mkdtemp())
try: try:
@ -236,10 +236,10 @@ def walk(directory_path: Path) -> Generator[Path, None, None]:
Credits to https://stackoverflow.com/a/64915960 Credits to https://stackoverflow.com/a/64915960
Args: Args:
directory_path(Path): root directory path directory_path(Path): root directory path
Yields: 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(): for element in directory_path.iterdir():
if element.is_dir(): if element.is_dir():

View File

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

View File

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

View File

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

View File

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

View File

@ -33,12 +33,12 @@ class Counters:
package counters package counters
Attributes: Attributes:
total(int): total packages count total(int): total packages count
unknown(int): packages in unknown status count unknown(int): packages in unknown status count
pending(int): packages in pending status count pending(int): packages in pending status count
building(int): packages in building status count building(int): packages in building status count
failed(int): packages in failed status count failed(int): packages in failed status count
success(int): packages in success status count success(int): packages in success status count
""" """
total: int total: int
@ -54,10 +54,10 @@ class Counters:
construct counters from json dump construct counters from json dump
Args: Args:
dump(Dict[str, Any]): json dump body dump(Dict[str, Any]): json dump body
Returns: Returns:
Counters: status counters Counters: status counters
""" """
# filter to only known fields # filter to only known fields
known_fields = [pair.name for pair in fields(cls)] known_fields = [pair.name for pair in fields(cls)]
@ -69,10 +69,10 @@ class Counters:
construct counters from packages statuses construct counters from packages statuses
Args: 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: Returns:
Counters: status counters Counters: status counters
""" """
per_status = {"total": len(packages)} per_status = {"total": len(packages)}
for _, status in packages: for _, status in packages:

View File

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

View File

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

View File

@ -28,8 +28,8 @@ class MigrationResult:
migration result implementation model migration result implementation model
Attributes: Attributes:
old_version(int): old schema version before migrations old_version(int): old schema version before migrations
new_version(int): new schema version after migrations new_version(int): new schema version after migrations
""" """
old_version: int old_version: int
@ -39,10 +39,10 @@ class MigrationResult:
def is_outdated(self) -> bool: def is_outdated(self) -> bool:
""" """
Returns: Returns:
bool: True in case if it requires migrations and False otherwise bool: True in case if it requires migrations and False otherwise
Raises: 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() self.validate()
return self.new_version > self.old_version return self.new_version > self.old_version

View File

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

View File

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

View File

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

View File

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

View File

@ -28,11 +28,11 @@ class ReportSettings(Enum):
report targets enumeration report targets enumeration
Attributes: Attributes:
Disabled(ReportSettings): (class attribute) option which generates no report for testing purpose Disabled(ReportSettings): (class attribute) option which generates no report for testing purpose
HTML(ReportSettings): (class attribute) html report generation HTML(ReportSettings): (class attribute) html report generation
Email(ReportSettings): (class attribute) email report generation Email(ReportSettings): (class attribute) email report generation
Console(ReportSettings): (class attribute) print result to console Console(ReportSettings): (class attribute) print result to console
Telegram(ReportSettings): (class attribute) markdown report to telegram channel Telegram(ReportSettings): (class attribute) markdown report to telegram channel
""" """
Disabled = "disabled" # for testing purpose Disabled = "disabled" # for testing purpose
@ -47,10 +47,10 @@ class ReportSettings(Enum):
construct value from configuration construct value from configuration
Args: Args:
value(str): configuration value value(str): configuration value
Returns: Returns:
ReportSettings: parsed value ReportSettings: parsed value
""" """
if value.lower() in ("html",): if value.lower() in ("html",):
return cls.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 repository paths holder. For the most operations with paths you want to use this object
Attributes: Attributes:
root(Path): repository root (i.e. ahriman home) root(Path): repository root (i.e. ahriman home)
architecture(str): repository architecture architecture(str): repository architecture
""" """
root: Path root: Path
@ -46,7 +46,7 @@ class RepositoryPaths:
def cache(self) -> Path: def cache(self) -> Path:
""" """
Returns: 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" return self.root / "cache"
@ -54,7 +54,7 @@ class RepositoryPaths:
def chroot(self) -> Path: def chroot(self) -> Path:
""" """
Returns: 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 # for the chroot directory devtools will create own tree, and we don"t have to specify architecture here
return self.root / "chroot" return self.root / "chroot"
@ -63,7 +63,7 @@ class RepositoryPaths:
def packages(self) -> Path: def packages(self) -> Path:
""" """
Returns: Returns:
Path: directory for built packages Path: directory for built packages
""" """
return self.root / "packages" / self.architecture return self.root / "packages" / self.architecture
@ -71,7 +71,7 @@ class RepositoryPaths:
def repository(self) -> Path: def repository(self) -> Path:
""" """
Returns: Returns:
Path: repository directory Path: repository directory
""" """
return self.root / "repository" / self.architecture return self.root / "repository" / self.architecture
@ -79,7 +79,7 @@ class RepositoryPaths:
def root_owner(self) -> Tuple[int, int]: def root_owner(self) -> Tuple[int, int]:
""" """
Returns: 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) return self.owner(self.root)
@ -89,10 +89,10 @@ class RepositoryPaths:
get known architectures get known architectures
Args: Args:
root(Path): repository root root(Path): repository root
Returns: Returns:
Set[str]: list of architectures for which tree is created Set[str]: list of architectures for which tree is created
""" """
paths = cls(root, "") paths = cls(root, "")
return { return {
@ -107,10 +107,10 @@ class RepositoryPaths:
retrieve owner information by path retrieve owner information by path
Args: Args:
path(Path): path for which extract ids path(Path): path for which extract ids
Returns: 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() stat = path.stat()
return stat.st_uid, stat.st_gid 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 get path to cached PKGBUILD and package sources for the package base
Args: Args:
package_base(str): package base name package_base(str): package base name
Returns: 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 return self.cache / package_base
@ -132,10 +132,10 @@ class RepositoryPaths:
set owner of path recursively (from root) to root owner set owner of path recursively (from root) to root owner
Args: Args:
path(Path): path to be chown path(Path): path to be chown
Raises: Raises:
InvalidPath: if path does not belong to root InvalidPath: if path does not belong to root
""" """
def set_owner(current: Path) -> None: def set_owner(current: Path) -> None:
uid, gid = self.owner(current) uid, gid = self.owner(current)
@ -155,7 +155,7 @@ class RepositoryPaths:
clear package specific files clear package specific files
Args: Args:
package_base(str): package base name package_base(str): package base name
""" """
for directory in ( for directory in (
self.cache_for(package_base), self.cache_for(package_base),

View File

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

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