mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-08-31 05:49:56 +00:00
Compare commits
2 Commits
b36bcb194b
...
203c024287
Author | SHA1 | Date | |
---|---|---|---|
203c024287 | |||
22600a9eac |
@ -236,16 +236,50 @@ The projects also uses typing checks (provided by `mypy`) and some linter checks
|
||||
tox
|
||||
```
|
||||
|
||||
Must be usually done before any pushes.
|
||||
|
||||
### Generate documentation templates
|
||||
|
||||
```shell
|
||||
tox -e docs
|
||||
```
|
||||
|
||||
Must be usually done if there are changes in modules structure.
|
||||
|
||||
### Create release
|
||||
|
||||
```shell
|
||||
tox -m release -- x.y.z
|
||||
tox -m release -- major.minor.patch
|
||||
```
|
||||
|
||||
The command above will generate documentation, tags, etc., and will push them to GitHub. Other things will be handled by GitHub workflows automatically.
|
||||
|
||||
### Hotfixes policy
|
||||
|
||||
Sometimes it is required to publish hotfix with specific commits, but some features have been already committed, which should not be included to the hotfix. In this case, some manual steps are required:
|
||||
|
||||
1. Create new branch from the last stable release (`major.minor.patch`):
|
||||
|
||||
```shell
|
||||
git checkout -b release/major.minor major.minor.patch
|
||||
```
|
||||
|
||||
2. Cherry-pick desired commit(s):
|
||||
|
||||
```shell
|
||||
git cherry-pick <commit-sha>
|
||||
```
|
||||
|
||||
Alternatively, make changes to the new branch and commit them.
|
||||
|
||||
3. Push newly created branch to remote:
|
||||
|
||||
```shell
|
||||
git push --set-upstream origin release/major.minor
|
||||
```
|
||||
|
||||
4. Proceed to release as usual:
|
||||
|
||||
```shell
|
||||
tox -m release -- major.minor.patch+1
|
||||
```
|
||||
|
@ -36,6 +36,14 @@ ahriman.core.exceptions module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.module\_loader module
|
||||
----------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.module_loader
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.spawn module
|
||||
-------------------------
|
||||
|
||||
|
@ -18,7 +18,7 @@ Full dependency diagram:
|
||||
``ahriman.application`` package
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This package contains application (aka executable) related classes and everything for it. It also contains package called ``ahriman.application.handlers`` in which all available subcommands are described as separated classes derived from the base ``ahriman.application.handlers.Handler`` class.
|
||||
This package contains application (aka executable) related classes and everything for it. It also contains package called ``ahriman.application.handlers`` in which all available subcommands are described as separated classes derived from the base ``ahriman.application.handlers.handler.Handler`` class.
|
||||
|
||||
``ahriman.application.application.Application`` (god class) is used for any interaction from parsers with repository. It is divided into multiple traits by functions (package related and repository related) in the same package.
|
||||
|
||||
|
@ -30,12 +30,14 @@ class ImportType(StrEnum):
|
||||
import type enumeration
|
||||
|
||||
Attributes:
|
||||
Future(MethodTypeOrder): (class attribute) from __future__ import
|
||||
Package(MethodTypeOrder): (class attribute) package import
|
||||
PackageFrom(MethodTypeOrder): (class attribute) package import, from clause
|
||||
System(ImportType): (class attribute) system installed packages
|
||||
SystemFrom(MethodTypeOrder): (class attribute) system installed packages, from clause
|
||||
"""
|
||||
|
||||
Future = "future"
|
||||
Package = "package"
|
||||
PackageFrom = "package-from"
|
||||
System = "system"
|
||||
@ -70,6 +72,7 @@ class ImportOrder(BaseRawFileChecker):
|
||||
"import-type-order",
|
||||
{
|
||||
"default": [
|
||||
"future",
|
||||
"system",
|
||||
"system-from",
|
||||
"package",
|
||||
@ -91,7 +94,7 @@ class ImportOrder(BaseRawFileChecker):
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def imports(source: Iterable[Any], start_lineno: int = 0) -> list[nodes.Import | nodes.ImportFrom]:
|
||||
def imports(source: Iterable[Any], start_lineno: int = 0) -> Iterable[nodes.Import | nodes.ImportFrom]:
|
||||
"""
|
||||
extract import nodes from list of raw nodes
|
||||
|
||||
@ -100,7 +103,7 @@ class ImportOrder(BaseRawFileChecker):
|
||||
start_lineno(int, optional): minimal allowed line number (Default value = 0)
|
||||
|
||||
Returns:
|
||||
list[nodes.Import | nodes.ImportFrom]: list of import nodes
|
||||
Iterable[nodes.Import | nodes.ImportFrom]: list of import nodes
|
||||
"""
|
||||
|
||||
def is_defined_import(imports: Any) -> bool:
|
||||
@ -108,7 +111,7 @@ class ImportOrder(BaseRawFileChecker):
|
||||
and imports.lineno is not None \
|
||||
and imports.lineno >= start_lineno
|
||||
|
||||
return list(filter(is_defined_import, source))
|
||||
return sorted(filter(is_defined_import, source), key=lambda imports: imports.lineno)
|
||||
|
||||
def check_from_imports(self, imports: nodes.ImportFrom) -> None:
|
||||
"""
|
||||
@ -124,30 +127,36 @@ class ImportOrder(BaseRawFileChecker):
|
||||
self.add_message("from-imports-out-of-order", line=imports.lineno, args=(real, expected))
|
||||
break
|
||||
|
||||
def check_imports(self, imports: list[nodes.Import | nodes.ImportFrom], root_package: str) -> None:
|
||||
def check_imports(self, imports: Iterable[nodes.Import | nodes.ImportFrom], root_package: str) -> None:
|
||||
"""
|
||||
check imports
|
||||
|
||||
Args:
|
||||
imports(list[nodes.Import | nodes.ImportFrom]): list of imports in their defined order
|
||||
imports(Iterable[nodes.Import | nodes.ImportFrom]): list of imports in their defined order
|
||||
root_package(str): root package name
|
||||
"""
|
||||
last_statement: tuple[int, str] | None = None
|
||||
|
||||
for statement in imports:
|
||||
# define types and perform specific checks
|
||||
if isinstance(statement, nodes.ImportFrom):
|
||||
import_name = statement.modname
|
||||
root, *_ = import_name.split(".", maxsplit=1)
|
||||
import_type = ImportType.PackageFrom if root_package == root else ImportType.SystemFrom
|
||||
# check from import itself
|
||||
self.check_from_imports(statement)
|
||||
else:
|
||||
import_name = next(name for name, _ in statement.names)
|
||||
root, *_ = import_name.split(".", maxsplit=1)[0]
|
||||
import_type = ImportType.Package if root_package == root else ImportType.System
|
||||
# check import itself
|
||||
self.check_package_imports(statement)
|
||||
match statement:
|
||||
case nodes.ImportFrom() if statement.modname == "__future__":
|
||||
import_name = statement.modname
|
||||
import_type = ImportType.Future
|
||||
case nodes.ImportFrom():
|
||||
import_name = statement.modname
|
||||
root, *_ = import_name.split(".", maxsplit=1)
|
||||
import_type = ImportType.PackageFrom if root_package == root else ImportType.SystemFrom
|
||||
# check from import itself
|
||||
self.check_from_imports(statement)
|
||||
case nodes.Import():
|
||||
import_name = next(name for name, _ in statement.names)
|
||||
root, *_ = import_name.split(".", maxsplit=1)
|
||||
import_type = ImportType.Package if root_package == root else ImportType.System
|
||||
# check import itself
|
||||
self.check_package_imports(statement)
|
||||
case _:
|
||||
continue
|
||||
|
||||
# extract index
|
||||
try:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,37 +17,3 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from ahriman.application.handlers.add import Add
|
||||
from ahriman.application.handlers.backup import Backup
|
||||
from ahriman.application.handlers.change import Change
|
||||
from ahriman.application.handlers.clean import Clean
|
||||
from ahriman.application.handlers.copy import Copy
|
||||
from ahriman.application.handlers.daemon import Daemon
|
||||
from ahriman.application.handlers.dump import Dump
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.help import Help
|
||||
from ahriman.application.handlers.key_import import KeyImport
|
||||
from ahriman.application.handlers.patch import Patch
|
||||
from ahriman.application.handlers.rebuild import Rebuild
|
||||
from ahriman.application.handlers.remove import Remove
|
||||
from ahriman.application.handlers.remove_unknown import RemoveUnknown
|
||||
from ahriman.application.handlers.repositories import Repositories
|
||||
from ahriman.application.handlers.restore import Restore
|
||||
from ahriman.application.handlers.run import Run
|
||||
from ahriman.application.handlers.search import Search
|
||||
from ahriman.application.handlers.service_updates import ServiceUpdates
|
||||
from ahriman.application.handlers.setup import Setup
|
||||
from ahriman.application.handlers.shell import Shell
|
||||
from ahriman.application.handlers.sign import Sign
|
||||
from ahriman.application.handlers.statistics import Statistics
|
||||
from ahriman.application.handlers.status import Status
|
||||
from ahriman.application.handlers.status_update import StatusUpdate
|
||||
from ahriman.application.handlers.structure import Structure
|
||||
from ahriman.application.handlers.tree_migrate import TreeMigrate
|
||||
from ahriman.application.handlers.triggers import Triggers
|
||||
from ahriman.application.handlers.unsafe_commands import UnsafeCommands
|
||||
from ahriman.application.handlers.update import Update
|
||||
from ahriman.application.handlers.users import Users
|
||||
from ahriman.application.handlers.validate import Validate
|
||||
from ahriman.application.handlers.versions import Versions
|
||||
from ahriman.application.handlers.web import Web
|
||||
|
@ -20,8 +20,10 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.utils import enum_values, extract_user
|
||||
from ahriman.models.package_source import PackageSource
|
||||
from ahriman.models.packagers import Packagers
|
||||
from ahriman.models.pkgbuild_patch import PkgbuildPatch
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
@ -66,3 +68,49 @@ class Add(Handler):
|
||||
application.print_updates(packages, log_fn=application.logger.info)
|
||||
result = application.update(packages, packagers, bump_pkgrel=args.increment)
|
||||
Add.check_status(args.exit_code, not result.is_empty)
|
||||
|
||||
@staticmethod
|
||||
def _set_package_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package addition subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-add", aliases=["add", "package-update"], help="add package",
|
||||
description="add existing or new package to the build queue",
|
||||
epilog="This subcommand should be used for new package addition. "
|
||||
"It also supports flag --now in case if you would like to build "
|
||||
"the package immediately. You can add new package from one of "
|
||||
"supported sources:\n\n"
|
||||
"1. If it is already built package you can specify the path to the archive.\n"
|
||||
"2. You can also add built packages from the directory (e.g. during the "
|
||||
"migration from another repository source).\n"
|
||||
"3. It is also possible to add package from local PKGBUILD, but in this case "
|
||||
"it will be ignored during the next automatic updates.\n"
|
||||
"4. Ahriman supports downloading archives from remote (e.g. HTTP) sources.\n"
|
||||
"5. Finally you can add package from AUR.")
|
||||
parser.add_argument("package", help="package source (base name, path to local files, remote URL)", nargs="+")
|
||||
parser.add_argument("--changes", help="calculate changes from the latest known commit if available",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--dependencies", help="process missing package dependencies",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||
action="store_true")
|
||||
parser.add_argument("--increment", help="increment package release (pkgrel) version on duplicate",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-n", "--now", help="run update function after", action="store_true")
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=False)
|
||||
parser.add_argument("-s", "--source", help="explicitly specify the package source for this command",
|
||||
type=PackageSource, choices=enum_values(PackageSource), default=PackageSource.Auto)
|
||||
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
|
||||
parser.add_argument("-v", "--variable", help="apply specified makepkg variables to the next build",
|
||||
action="append")
|
||||
return parser
|
||||
|
||||
arguments = [_set_package_add_parser]
|
||||
|
@ -23,7 +23,7 @@ import tarfile
|
||||
from pathlib import Path
|
||||
from pwd import getpwuid
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
@ -53,6 +53,23 @@ class Backup(Handler):
|
||||
for backup_path in backup_paths:
|
||||
archive.add(backup_path)
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_backup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository backup subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-backup", help="backup repository data",
|
||||
description="backup repository settings and database")
|
||||
parser.add_argument("path", help="path of the output archive", type=Path)
|
||||
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def get_paths(configuration: Configuration) -> set[Path]:
|
||||
"""
|
||||
@ -83,3 +100,5 @@ class Backup(Handler):
|
||||
paths.add(gnupg_home)
|
||||
|
||||
return paths
|
||||
|
||||
arguments = [_set_repo_backup_parser]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import ChangesPrinter
|
||||
from ahriman.models.action import Action
|
||||
@ -57,3 +57,43 @@ class Change(Handler):
|
||||
Change.check_status(args.exit_code, not changes.is_empty)
|
||||
case Action.Remove:
|
||||
client.package_changes_update(args.package, Changes())
|
||||
|
||||
@staticmethod
|
||||
def _set_package_changes_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package changes subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-changes", help="get package changes",
|
||||
description="retrieve package changes stored in database",
|
||||
epilog="This command requests package status from the web interface "
|
||||
"if it is available.")
|
||||
parser.add_argument("package", help="package base")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||
action="store_true")
|
||||
parser.set_defaults(action=Action.List, lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_package_changes_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package change remove subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-changes-remove", help="remove package changes",
|
||||
description="remove the package changes stored remotely")
|
||||
parser.add_argument("package", help="package base")
|
||||
parser.set_defaults(action=Action.Remove, exit_code=False, lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_package_changes_parser, _set_package_changes_remove_parser]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
@ -46,3 +46,33 @@ class Clean(Handler):
|
||||
application.on_start()
|
||||
application.clean(cache=args.cache, chroot=args.chroot, manual=args.manual, packages=args.packages,
|
||||
pacman=args.pacman)
|
||||
|
||||
@staticmethod
|
||||
def _set_service_clean_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository clean subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-clean", aliases=["clean", "repo-clean"], help="clean local caches",
|
||||
description="remove local caches",
|
||||
epilog="The subcommand clears every temporary directories (builds, caches etc). "
|
||||
"Normally you should not run this command manually. Also in case if "
|
||||
"you are going to clear the chroot directories you will need root privileges.")
|
||||
parser.add_argument("--cache", help="clear directory with package caches",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--chroot", help="clear build chroot", action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--manual", help="clear manually added packages queue",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--packages", help="clear directory with built packages",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--pacman", help="clear directory with pacman local database cache",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.set_defaults(lock=None, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_service_clean_parser]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.build_status import BuildStatusEnum
|
||||
from ahriman.models.package import Package
|
||||
@ -67,6 +67,26 @@ class Copy(Handler):
|
||||
if args.remove:
|
||||
source_application.remove(args.package)
|
||||
|
||||
@staticmethod
|
||||
def _set_package_copy_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package copy subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-copy", aliases=["copy"], help="copy package from another repository",
|
||||
description="copy package and its metadata from another repository")
|
||||
parser.add_argument("source", help="source repository name")
|
||||
parser.add_argument("package", help="package base", nargs="+")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||
action="store_true")
|
||||
parser.add_argument("--remove", help="remove package from the source repository after", action="store_true")
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def copy_package(package: Package, application: Application, source_application: Application) -> None:
|
||||
"""
|
||||
@ -93,3 +113,5 @@ class Copy(Handler):
|
||||
package.base, source_application.reporter.package_dependencies_get(package.base)
|
||||
)
|
||||
application.reporter.package_update(package, BuildStatusEnum.Pending)
|
||||
|
||||
arguments = [_set_package_copy_parser]
|
||||
|
@ -19,11 +19,14 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.application.updates_iterator import FixedUpdatesIterator, UpdatesIterator
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.application.handlers.update import Update
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.utils import extract_user
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
@ -56,3 +59,48 @@ class Daemon(Handler):
|
||||
|
||||
args.package = packages
|
||||
Update.run(args, repository_id, configuration, report=report)
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_daemon_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for daemon subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-daemon", aliases=["daemon"], help="run application as daemon",
|
||||
description="start process which periodically will run update process")
|
||||
parser.add_argument("-i", "--interval", help="interval between runs in seconds", type=int, default=60 * 60 * 12)
|
||||
parser.add_argument("--aur", help="enable or disable checking for AUR updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--changes", help="calculate changes from the latest known commit if available. "
|
||||
"Only applicable in dry run mode",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--check-files", help="enable or disable checking of broken dependencies "
|
||||
"(e.g. dynamically linked libraries or modules directories)",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--dependencies", help="process missing package dependencies",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--dry-run", help="just perform check for updates, same as check command",
|
||||
action="store_true")
|
||||
parser.add_argument("--increment", help="increment package release (pkgrel) on duplicate",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--local", help="enable or disable checking of local packages for updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--manual", help="include or exclude manual updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--partitions", help="instead of updating whole repository, split updates into chunks",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
|
||||
parser.add_argument("--vcs", help="fetch actual version of VCS packages",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=False)
|
||||
parser.set_defaults(exit_code=False, lock=Path("ahriman-daemon.pid"), package=[])
|
||||
return parser
|
||||
|
||||
arguments = [_set_repo_daemon_parser]
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import ConfigurationPathsPrinter, ConfigurationPrinter, StringPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
@ -59,3 +59,27 @@ class Dump(Handler):
|
||||
case section, key: # key only
|
||||
value = configuration.get(section, key, fallback="")
|
||||
StringPrinter(value)(verbose=False)
|
||||
|
||||
@staticmethod
|
||||
def _set_service_config_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for config subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-config", aliases=["config", "repo-config"], help="dump configuration",
|
||||
description="dump configuration for the specified architecture")
|
||||
parser.add_argument("section", help="filter settings by section", nargs="?")
|
||||
parser.add_argument("key", help="filter settings by key", nargs="?")
|
||||
parser.add_argument("--info", help="show additional information, e.g. configuration files",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--secure", help="hide passwords and secrets from output",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_service_config_parser]
|
||||
|
@ -22,6 +22,7 @@ import logging
|
||||
|
||||
from collections.abc import Callable, Iterable
|
||||
from multiprocessing import Pool
|
||||
from typing import TypeVar
|
||||
|
||||
from ahriman.application.lock import Lock
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -32,12 +33,21 @@ from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
# this workaround is for several things
|
||||
# firstly python devs don't think that is it error and asking you for workarounds https://bugs.python.org/issue41592
|
||||
# secondly linters don't like when you are importing private members
|
||||
# thirdly new mypy doesn't like _SubParsersAction and thinks it is a template
|
||||
SubParserAction = TypeVar("SubParserAction", bound="argparse._SubParsersAction[argparse.ArgumentParser]")
|
||||
|
||||
|
||||
class Handler:
|
||||
"""
|
||||
base handler class for command callbacks
|
||||
|
||||
Attributes:
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
|
||||
arguments(list[Callable[[SubParserAction], argparse.ArgumentParser]]): (class attribute) argument parser
|
||||
methods, which will be called to create command line parsers
|
||||
|
||||
Examples:
|
||||
Wrapper for all command line actions, though each derived class implements :func:`run()` method, it usually
|
||||
@ -49,6 +59,7 @@ class Handler:
|
||||
"""
|
||||
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = True
|
||||
arguments: list[Callable[[SubParserAction], argparse.ArgumentParser]]
|
||||
|
||||
@classmethod
|
||||
def call(cls, args: argparse.Namespace, repository_id: RepositoryId) -> bool:
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
@ -48,3 +48,22 @@ class Help(Handler):
|
||||
parser.parse_args(["--help"])
|
||||
else:
|
||||
parser.parse_args([args.subcommand, "--help"])
|
||||
|
||||
@staticmethod
|
||||
def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for listing help subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("help", help="show help message",
|
||||
description="show help message for application or command and exit")
|
||||
parser.add_argument("subcommand", help="show help message for specific command", nargs="?")
|
||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_help_parser]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
@ -46,3 +46,27 @@ class KeyImport(Handler):
|
||||
"""
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
application.repository.sign.key_import(args.key_server, args.key)
|
||||
|
||||
@staticmethod
|
||||
def _set_service_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for key import subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-key-import", aliases=["key-import"], help="import PGP key",
|
||||
description="import PGP key from public sources to the repository user",
|
||||
epilog="By default ahriman runs build process with package sources validation "
|
||||
"(in case if signature and keys are available in PKGBUILD). This process will "
|
||||
"fail in case if key is not known for build user. This subcommand can be used "
|
||||
"in order to import the PGP key to user keychain.")
|
||||
parser.add_argument("--key-server", help="key server for key import", default="keyserver.ubuntu.com")
|
||||
parser.add_argument("key", help="PGP key to import from public server")
|
||||
parser.set_defaults(architecture="", lock=None, report=False, repository="")
|
||||
return parser
|
||||
|
||||
arguments = [_set_service_key_import_parser]
|
||||
|
@ -23,7 +23,7 @@ import sys
|
||||
from pathlib import Path
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import PatchPrinter
|
||||
@ -67,6 +67,100 @@ class Patch(Handler):
|
||||
case Action.Remove:
|
||||
Patch.patch_set_remove(application, args.package, args.variable)
|
||||
|
||||
@staticmethod
|
||||
def _set_patch_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for new single-function patch subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("patch-add", help="add patch for PKGBUILD function",
|
||||
description="create or update patched PKGBUILD function or variable",
|
||||
epilog="Unlike ``patch-set-add``, this function allows to patch only one PKGBUILD "
|
||||
"function, e.g. typing ``ahriman patch-add ahriman pkgver`` it will change the "
|
||||
"``pkgver`` inside PKGBUILD, typing ``ahriman patch-add ahriman build()`` "
|
||||
"it will change ``build()`` function inside PKGBUILD.")
|
||||
parser.add_argument("package", help="package base")
|
||||
parser.add_argument("variable", help="PKGBUILD variable or function name. If variable is a function, "
|
||||
"it must end with ()")
|
||||
parser.add_argument("patch", help="path to file which contains function or variable value. If not set, "
|
||||
"the value will be read from stdin", type=Path, nargs="?")
|
||||
parser.set_defaults(action=Action.Update, architecture="", exit_code=False, lock=None, report=False,
|
||||
repository="")
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_patch_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for list patches subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("patch-list", help="list patch sets",
|
||||
description="list available patches for the package")
|
||||
parser.add_argument("package", help="package base")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||
action="store_true")
|
||||
parser.add_argument("-v", "--variable", help="if set, show only patches for specified PKGBUILD variables",
|
||||
action="append")
|
||||
parser.set_defaults(action=Action.List, architecture="", lock=None, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_patch_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for remove patches subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("patch-remove", help="remove patch set", description="remove patches for the package")
|
||||
parser.add_argument("package", help="package base")
|
||||
parser.add_argument("-v", "--variable",
|
||||
help="should be used for single-function patches in case if you wold like "
|
||||
"to remove only specified PKGBUILD variables. In case if not set, "
|
||||
"it will remove all patches related to the package",
|
||||
action="append")
|
||||
parser.set_defaults(action=Action.Remove, architecture="", exit_code=False, lock=None, report=False,
|
||||
repository="")
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_patch_set_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for new full-diff patch subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("patch-set-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:\n\n"
|
||||
"1. Clone the AUR package manually.\n"
|
||||
"2. Add required changes (e.g. external patches, edit PKGBUILD).\n"
|
||||
"3. Run command, e.g. ``ahriman patch-set-add path/to/directory``.\n\n"
|
||||
"By default it tracks ``*.patch`` and ``*.diff`` files, but this behavior "
|
||||
"can be changed by using ``--track`` option.")
|
||||
parser.add_argument("package", help="path to directory with changed files for patch addition/update", type=Path)
|
||||
parser.add_argument("-t", "--track", help="files which has to be tracked", action="append",
|
||||
default=["*.diff", "*.patch"])
|
||||
parser.set_defaults(action=Action.Update, architecture="", exit_code=False, lock=None, report=False,
|
||||
repository="", variable=None)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def patch_create_from_diff(sources_dir: Path, architecture: str, track: list[str]) -> tuple[str, PkgbuildPatch]:
|
||||
"""
|
||||
@ -155,3 +249,10 @@ class Patch(Handler):
|
||||
application.reporter.package_patches_remove(package_base, variable)
|
||||
else:
|
||||
application.reporter.package_patches_remove(package_base, None) # just pass as is
|
||||
|
||||
arguments = [
|
||||
_set_patch_add_parser,
|
||||
_set_patch_list_parser,
|
||||
_set_patch_remove_parser,
|
||||
_set_patch_set_add_parser,
|
||||
]
|
||||
|
@ -20,8 +20,9 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.utils import enum_values, extract_user
|
||||
from ahriman.models.build_status import BuildStatusEnum
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.packagers import Packagers
|
||||
@ -59,6 +60,38 @@ class Rebuild(Handler):
|
||||
result = application.update(packages, Packagers(args.username), bump_pkgrel=args.increment)
|
||||
Rebuild.check_status(args.exit_code, not result.is_empty)
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_rebuild_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository rebuild subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-rebuild", aliases=["rebuild"], help="rebuild repository",
|
||||
description="force rebuild whole repository")
|
||||
parser.add_argument("--depends-on", help="only rebuild packages that depend on specified packages",
|
||||
action="append")
|
||||
parser.add_argument("--dry-run", help="just perform check for packages without rebuild process itself",
|
||||
action="store_true")
|
||||
parser.add_argument("--from-database",
|
||||
help="read packages from database instead of filesystem. This feature in particular is "
|
||||
"required in case if you would like to restore repository from another repository "
|
||||
"instance. Note, however, that in order to restore packages you need to have original "
|
||||
"ahriman instance run with web service and have run repo-update at least once.",
|
||||
action="store_true")
|
||||
parser.add_argument("--increment", help="increment package release (pkgrel) on duplicate",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||
action="store_true")
|
||||
parser.add_argument("-s", "--status", help="filter packages by status. Requires --from-database to be set",
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
|
||||
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def extract_packages(application: Application, status: BuildStatusEnum | None, *,
|
||||
from_database: bool) -> list[Package]:
|
||||
@ -81,3 +114,5 @@ class Rebuild(Handler):
|
||||
]
|
||||
|
||||
return application.repository.packages()
|
||||
|
||||
arguments = [_set_repo_rebuild_parser]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
@ -45,3 +45,21 @@ class Remove(Handler):
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
application.on_start()
|
||||
application.remove(args.package)
|
||||
|
||||
@staticmethod
|
||||
def _set_package_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package removal subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-remove", aliases=["remove"], help="remove package",
|
||||
description="remove package from the repository")
|
||||
parser.add_argument("package", help="package name or base", nargs="+")
|
||||
return parser
|
||||
|
||||
arguments = [_set_package_remove_parser]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
@ -53,3 +53,21 @@ class RemoveUnknown(Handler):
|
||||
return
|
||||
|
||||
application.remove(unknown_packages)
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_remove_unknown_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for remove unknown packages subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-remove-unknown", aliases=["remove-unknown"], help="remove unknown packages",
|
||||
description="remove packages which are missing in AUR and do not have local PKGBUILDs")
|
||||
parser.add_argument("--dry-run", help="just perform check for packages without removal", action="store_true")
|
||||
return parser
|
||||
|
||||
arguments = [_set_repo_remove_unknown_parser]
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import RepositoryPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
@ -52,3 +52,23 @@ class Repositories(Handler):
|
||||
)
|
||||
for repository in cls.repositories_extract(dummy_args):
|
||||
RepositoryPrinter(repository)(verbose=not args.id_only)
|
||||
|
||||
@staticmethod
|
||||
def _set_service_repositories(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repositories listing
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-repositories", help="show repositories",
|
||||
description="list all available repositories")
|
||||
parser.add_argument("--id-only", help="show machine readable identifier instead",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_service_repositories]
|
||||
|
@ -20,7 +20,9 @@
|
||||
import argparse
|
||||
import tarfile
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from pathlib import Path
|
||||
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
@ -46,3 +48,23 @@ class Restore(Handler):
|
||||
"""
|
||||
with tarfile.open(args.path) as archive:
|
||||
archive.extractall(path=args.output) # nosec
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository restore subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-restore", help="restore repository data",
|
||||
description="restore settings and database")
|
||||
parser.add_argument("path", help="path of the input archive", type=Path)
|
||||
parser.add_argument("-o", "--output", help="root path of the extracted files", type=Path, default=Path("/"))
|
||||
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_repo_restore_parser]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
import shlex
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
@ -49,6 +49,25 @@ class Run(Handler):
|
||||
status = Run.run_command(shlex.split(command), parser)
|
||||
Run.check_status(True, status)
|
||||
|
||||
@staticmethod
|
||||
def _set_service_run(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for multicommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-run", aliases=["run"], help="run multiple commands",
|
||||
description="run multiple commands on success run of the previous command",
|
||||
epilog="Commands must be quoted by using usual bash rules. Processes will be spawned "
|
||||
"under the same user as this command.")
|
||||
parser.add_argument("command", help="command to be run (quoted) without ``ahriman``", nargs="+")
|
||||
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def run_command(command: list[str], parser: argparse.ArgumentParser) -> bool:
|
||||
"""
|
||||
@ -64,3 +83,5 @@ class Run(Handler):
|
||||
args = parser.parse_args(command)
|
||||
handler: Handler = args.handler
|
||||
return handler.execute(args) == 0
|
||||
|
||||
arguments = [_set_service_run]
|
||||
|
@ -22,7 +22,7 @@ import argparse
|
||||
from collections.abc import Callable, Iterable
|
||||
from dataclasses import fields
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.alpm.remote import AUR, Official
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import OptionError
|
||||
@ -68,6 +68,33 @@ class Search(Handler):
|
||||
for package in Search.sort(packages_list, args.sort_by):
|
||||
AurPrinter(package)(verbose=args.info)
|
||||
|
||||
@staticmethod
|
||||
def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for AUR search subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("aur-search", aliases=["search"], help="search for package",
|
||||
description="search for package in AUR using API")
|
||||
parser.add_argument("search",
|
||||
help="search terms, can be specified multiple times, the result will match all terms",
|
||||
nargs="+")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||
action="store_true")
|
||||
parser.add_argument("--info", help="show additional package information",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--sort-by",
|
||||
help="sort field by this field. In case if two packages have the same value of "
|
||||
"the specified field, they will be always sorted by name",
|
||||
default="name", choices=sorted(Search.SORT_FIELDS))
|
||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def sort(packages: Iterable[AURPackage], sort_by: str) -> list[AURPackage]:
|
||||
"""
|
||||
@ -90,3 +117,5 @@ class Search(Handler):
|
||||
comparator: Callable[[AURPackage], tuple[str, str]] =\
|
||||
lambda package: (getattr(package, sort_by), package.name)
|
||||
return sorted(packages, key=comparator)
|
||||
|
||||
arguments = [_set_aur_search_parser]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from ahriman import __version__
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import UpdatePrinter
|
||||
from ahriman.models.package import Package
|
||||
@ -58,3 +58,23 @@ class ServiceUpdates(Handler):
|
||||
|
||||
UpdatePrinter(remote, local_version)(verbose=True, separator=" -> ")
|
||||
ServiceUpdates.check_status(args.exit_code, same_version)
|
||||
|
||||
@staticmethod
|
||||
def _set_help_updates_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for service update check subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("help-updates", help="check for service updates",
|
||||
description="request AUR for current version and compare with current service version")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit code if updates available",
|
||||
action="store_true")
|
||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_help_updates_parser]
|
||||
|
@ -24,11 +24,13 @@ from pwd import getpwuid
|
||||
from urllib.parse import quote_plus as urlencode
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import MissingArchitectureError
|
||||
from ahriman.core.utils import enum_values
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
from ahriman.models.sign_settings import SignSettings
|
||||
from ahriman.models.user import User
|
||||
|
||||
|
||||
@ -80,6 +82,44 @@ class Setup(Handler):
|
||||
# lazy database sync
|
||||
application.repository.pacman.handle # pylint: disable=pointless-statement
|
||||
|
||||
@staticmethod
|
||||
def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for setup subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-setup", aliases=["init", "repo-init", "repo-setup", "setup"],
|
||||
help="initial service configuration",
|
||||
description="create initial service configuration, requires root",
|
||||
epilog="Create minimal configuration for the service according to provided options.")
|
||||
parser.add_argument("--build-as-user", help="force makepkg user to the specific one")
|
||||
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration",
|
||||
type=Path,
|
||||
default=Path("/") / "usr" / "share" / "devtools" / "pacman.conf.d" / "extra.conf")
|
||||
parser.add_argument("--generate-salt", help="generate salt for user passwords",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--makeflags-jobs",
|
||||
help="append MAKEFLAGS variable with parallelism set to number of cores",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--mirror", help="use the specified explicitly mirror instead of including mirrorlist")
|
||||
parser.add_argument("--multilib", help="add or do not multilib repository",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--packager", help="packager name and email", required=True)
|
||||
parser.add_argument("--server", help="server to be used for devtools. If none set, local files will be used")
|
||||
parser.add_argument("--sign-key", help="sign key id")
|
||||
parser.add_argument("--sign-target", help="sign options", action="append",
|
||||
type=SignSettings.from_option, choices=enum_values(SignSettings))
|
||||
parser.add_argument("--web-port", help="port of the web service", type=int)
|
||||
parser.add_argument("--web-unix-socket", help="path to unix socket used for interprocess communications",
|
||||
type=Path)
|
||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def build_command(root: Path, repository_id: RepositoryId) -> Path:
|
||||
"""
|
||||
@ -240,3 +280,5 @@ class Setup(Handler):
|
||||
command.unlink(missing_ok=True)
|
||||
command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH)
|
||||
paths.chown(command) # we would like to keep owner inside ahriman's home
|
||||
|
||||
arguments = [_set_service_setup_parser]
|
||||
|
@ -23,7 +23,7 @@ import sys
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
@ -63,3 +63,23 @@ class Shell(Handler):
|
||||
code.interact(local=local_variables)
|
||||
else:
|
||||
code.InteractiveConsole(locals=local_variables).runcode(args.code)
|
||||
|
||||
@staticmethod
|
||||
def _set_service_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for shell subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-shell", aliases=["shell"], help="invoke python shell",
|
||||
description="drop into python shell")
|
||||
parser.add_argument("code", help="instead of dropping into shell, just execute the specified code", nargs="?")
|
||||
parser.add_argument("-v", "--verbose", help=argparse.SUPPRESS, action="store_true")
|
||||
parser.set_defaults(lock=None, report=False)
|
||||
return parser
|
||||
|
||||
arguments = [_set_service_shell_parser]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
@ -43,3 +43,22 @@ class Sign(Handler):
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
Application(repository_id, configuration, report=report).sign(args.package)
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_sign_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for sign subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-sign", aliases=["sign"], help="sign packages",
|
||||
description="(re-)sign packages and repository database according to current settings",
|
||||
epilog="Sign repository and/or packages as configured.")
|
||||
parser.add_argument("package", help="sign only specified packages", nargs="*")
|
||||
return parser
|
||||
|
||||
arguments = [_set_repo_sign_parser]
|
||||
|
@ -25,11 +25,11 @@ from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import EventStatsPrinter, PackageStatsPrinter
|
||||
from ahriman.core.utils import pretty_datetime
|
||||
from ahriman.models.event import Event
|
||||
from ahriman.core.utils import enum_values, pretty_datetime
|
||||
from ahriman.models.event import Event, EventType
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
@ -68,6 +68,30 @@ class Statistics(Handler):
|
||||
case _:
|
||||
Statistics.stats_for_package(args.event, events, args.chart)
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_statistics_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository statistics subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-statistics", help="repository statistics",
|
||||
description="fetch repository statistics")
|
||||
parser.add_argument("package", help="fetch only events for the specified package", nargs="?")
|
||||
parser.add_argument("--chart", help="create updates chart and save it to the specified path", type=Path)
|
||||
parser.add_argument("-e", "--event", help="event type filter",
|
||||
type=EventType, choices=enum_values(EventType), default=EventType.PackageUpdated)
|
||||
parser.add_argument("--from-date", help="only fetch events which are newer than the date")
|
||||
parser.add_argument("--limit", help="limit response by specified amount of events", type=int, default=-1)
|
||||
parser.add_argument("--offset", help="skip specified amount of events", type=int, default=0)
|
||||
parser.add_argument("--to-date", help="only fetch events which are older than the date")
|
||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def event_stats(event_type: str, events: list[Event]) -> None:
|
||||
"""
|
||||
@ -168,3 +192,5 @@ class Statistics(Handler):
|
||||
# chart if enabled
|
||||
if chart_path is not None:
|
||||
Statistics.plot_packages(event_type, by_object_id, chart_path)
|
||||
|
||||
arguments = [_set_repo_statistics_parser]
|
||||
|
@ -22,10 +22,11 @@ import argparse
|
||||
from collections.abc import Callable
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import PackagePrinter, StatusPrinter
|
||||
from ahriman.models.build_status import BuildStatus
|
||||
from ahriman.core.utils import enum_values
|
||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
@ -68,3 +69,31 @@ class Status(Handler):
|
||||
lambda item: args.status is None or item[1].status == args.status
|
||||
for package, package_status in sorted(filter(filter_fn, packages), key=comparator):
|
||||
PackagePrinter(package, package_status)(verbose=args.info)
|
||||
|
||||
@staticmethod
|
||||
def _set_package_status_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package status subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-status", aliases=["status"], help="get package status",
|
||||
description="request status of the package",
|
||||
epilog="This command requests package status from the web interface "
|
||||
"if it is available.")
|
||||
parser.add_argument("package", help="filter status by package base", nargs="*")
|
||||
parser.add_argument("--ahriman", help="get service status itself", action="store_true")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||
action="store_true")
|
||||
parser.add_argument("--info", help="show additional package information",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("-s", "--status", help="filter packages by status",
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
|
||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_package_status_parser]
|
||||
|
@ -20,9 +20,11 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.utils import enum_values
|
||||
from ahriman.models.action import Action
|
||||
from ahriman.models.build_status import BuildStatusEnum
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
@ -59,3 +61,67 @@ class StatusUpdate(Handler):
|
||||
case Action.Remove:
|
||||
for package in args.package:
|
||||
client.package_remove(package)
|
||||
|
||||
@staticmethod
|
||||
def _set_package_status_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package status remove subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-status-remove", help="remove package status",
|
||||
description="remove the package from the status page",
|
||||
epilog="Please note that this subcommand does not remove the package itself, it just "
|
||||
"clears the status page.")
|
||||
parser.add_argument("package", help="remove specified packages from status page", nargs="+")
|
||||
parser.set_defaults(action=Action.Remove, lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_package_status_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package status update subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-status-update", aliases=["status-update"], help="update package status",
|
||||
description="update package status on the status page")
|
||||
parser.add_argument("package", help="set status for specified packages. "
|
||||
"If no packages supplied, service status will be updated",
|
||||
nargs="*")
|
||||
parser.add_argument("-s", "--status", help="new package build status",
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
||||
parser.set_defaults(action=Action.Update, lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_status_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository status update subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-status-update", help="update repository status",
|
||||
description="update repository status on the status page")
|
||||
parser.add_argument("-s", "--status", help="new status",
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
||||
parser.set_defaults(action=Action.Update, lock=None, package=[], quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [
|
||||
_set_package_status_remove_parser,
|
||||
_set_package_status_update_parser,
|
||||
_set_repo_status_update_parser,
|
||||
]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import StringPrinter, TreePrinter
|
||||
from ahriman.core.tree import Tree
|
||||
@ -58,3 +58,23 @@ class Structure(Handler):
|
||||
|
||||
# empty line
|
||||
StringPrinter("")(verbose=False)
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_tree_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository tree subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-tree", help="dump repository tree",
|
||||
description="dump repository tree based on packages dependencies")
|
||||
parser.add_argument("-p", "--partitions", help="also divide packages by independent partitions",
|
||||
type=int, default=1)
|
||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_repo_tree_parser]
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
@ -50,6 +50,22 @@ class TreeMigrate(Handler):
|
||||
# perform migration
|
||||
TreeMigrate.tree_move(current_tree, target_tree)
|
||||
|
||||
@staticmethod
|
||||
def _set_service_tree_migrate_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for tree migration subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-tree-migrate", help="migrate repository tree",
|
||||
description="migrate repository tree between versions")
|
||||
parser.set_defaults(lock=None, quiet=True, report=False)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def tree_move(from_tree: RepositoryPaths, to_tree: RepositoryPaths) -> None:
|
||||
"""
|
||||
@ -66,3 +82,5 @@ class TreeMigrate(Handler):
|
||||
RepositoryPaths.repository,
|
||||
):
|
||||
attribute.fget(from_tree).rename(attribute.fget(to_tree)) # type: ignore[attr-defined]
|
||||
|
||||
arguments = [_set_service_tree_migrate_parser]
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.result import Result
|
||||
@ -49,3 +49,98 @@ class Triggers(Handler):
|
||||
loader.triggers = [loader.load_trigger(trigger, repository_id, configuration) for trigger in args.trigger]
|
||||
application.on_start()
|
||||
application.on_result(Result())
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_create_keyring_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for create-keyring subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-create-keyring", help="create keyring package",
|
||||
description="create package which contains list of trusted keys as set by "
|
||||
"configuration. Note, that this action will only create package, "
|
||||
"the package itself has to be built manually")
|
||||
parser.set_defaults(trigger=["ahriman.core.support.KeyringTrigger"])
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_create_mirrorlist_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for create-mirrorlist subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-create-mirrorlist", help="create mirrorlist package",
|
||||
description="create package which contains list of available mirrors as set by "
|
||||
"configuration. Note, that this action will only create package, "
|
||||
"the package itself has to be built manually")
|
||||
parser.set_defaults(trigger=["ahriman.core.support.MirrorlistTrigger"])
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_report_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for report subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-report", aliases=["report"], help="generate report",
|
||||
description="generate repository report according to current settings",
|
||||
epilog="Create and/or update repository report as configured.")
|
||||
parser.set_defaults(trigger=["ahriman.core.report.ReportTrigger"])
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_sync_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository sync subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-sync", aliases=["sync"], help="sync repository",
|
||||
description="sync repository files to remote server according to current settings",
|
||||
epilog="Synchronize the repository to remote services as configured.")
|
||||
parser.set_defaults(trigger=["ahriman.core.upload.UploadTrigger"])
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_triggers_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository triggers subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-triggers", help="run triggers",
|
||||
description="run triggers on empty build result as configured by settings")
|
||||
parser.add_argument("trigger", help="instead of running all triggers as set by configuration, just process "
|
||||
"specified ones in order of mention", nargs="*")
|
||||
return parser
|
||||
|
||||
arguments = [
|
||||
_set_repo_create_keyring_parser,
|
||||
_set_repo_create_mirrorlist_parser,
|
||||
_set_repo_report_parser,
|
||||
_set_repo_sync_parser,
|
||||
_set_repo_triggers_parser,
|
||||
]
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
@ -52,6 +52,25 @@ class UnsafeCommands(Handler):
|
||||
for command in unsafe_commands:
|
||||
StringPrinter(command)(verbose=True)
|
||||
|
||||
@staticmethod
|
||||
def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for listing unsafe commands
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("help-commands-unsafe", help="list unsafe commands",
|
||||
description="list unsafe commands as defined in default args")
|
||||
parser.add_argument("subcommand",
|
||||
help="instead of showing commands, just test command line for unsafe subcommand "
|
||||
"and return 0 in case if command is safe and 1 otherwise", nargs="*")
|
||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def check_unsafe(command: list[str], unsafe_commands: list[str], parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
@ -81,3 +100,5 @@ class UnsafeCommands(Handler):
|
||||
subparser = next((action for action in parser._actions if isinstance(action, argparse._SubParsersAction)), None)
|
||||
actions = subparser.choices if subparser is not None else {}
|
||||
return sorted(action_name for action_name, action in actions.items() if action.get_default("unsafe"))
|
||||
|
||||
arguments = [_set_help_commands_unsafe_parser]
|
||||
|
@ -22,8 +22,9 @@ import argparse
|
||||
from collections.abc import Callable
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.utils import extract_user
|
||||
from ahriman.models.packagers import Packagers
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
@ -64,6 +65,78 @@ class Update(Handler):
|
||||
result = application.update(packages, packagers, bump_pkgrel=args.increment)
|
||||
Update.check_status(args.exit_code, not result.is_empty)
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_check_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository check subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-check", aliases=["check"], help="check for updates",
|
||||
description="check for packages updates. Same as repo-update --dry-run --no-manual")
|
||||
parser.add_argument("package", help="filter check by package base", nargs="*")
|
||||
parser.add_argument("--changes", help="calculate changes from the latest known commit if available",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--check-files", help="enable or disable checking of broken dependencies "
|
||||
"(e.g. dynamically linked libraries or modules directories)",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||
action="store_true")
|
||||
parser.add_argument("--vcs", help="fetch actual version of VCS packages",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=False)
|
||||
parser.set_defaults(aur=True, dependencies=False, dry_run=True, increment=False, local=True, manual=False,
|
||||
username=None)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_repo_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository update subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-update", aliases=["update"], help="update packages",
|
||||
description="check for packages updates and run build process if requested")
|
||||
parser.add_argument("package", help="filter check by package base", nargs="*")
|
||||
parser.add_argument("--aur", help="enable or disable checking for AUR updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--changes", help="calculate changes from the latest known commit if available. "
|
||||
"Only applicable in dry run mode",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--check-files", help="enable or disable checking of broken dependencies "
|
||||
"(e.g. dynamically linked libraries or modules directories)",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--dependencies", help="process missing package dependencies",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--dry-run", help="just perform check for updates, same as check command",
|
||||
action="store_true")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||
action="store_true")
|
||||
parser.add_argument("--increment", help="increment package release (pkgrel) on duplicate",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--local", help="enable or disable checking of local packages for updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--manual", help="include or exclude manual updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
|
||||
parser.add_argument("--vcs", help="fetch actual version of VCS packages",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=False)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def log_fn(application: Application, dry_run: bool) -> Callable[[str], None]:
|
||||
"""
|
||||
@ -79,3 +152,8 @@ class Update(Handler):
|
||||
def inner(line: str) -> None:
|
||||
return print(line) if dry_run else application.logger.info(line) # pylint: disable=bad-builtin
|
||||
return inner
|
||||
|
||||
arguments = [
|
||||
_set_repo_check_parser,
|
||||
_set_repo_update_parser,
|
||||
]
|
||||
|
@ -20,14 +20,16 @@
|
||||
import argparse
|
||||
import getpass
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.exceptions import PasswordError
|
||||
from ahriman.core.formatters import UserPrinter
|
||||
from ahriman.core.utils import enum_values
|
||||
from ahriman.models.action import Action
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.user import User
|
||||
from ahriman.models.user_access import UserAccess
|
||||
|
||||
|
||||
class Users(Handler):
|
||||
@ -65,6 +67,73 @@ class Users(Handler):
|
||||
case Action.Remove:
|
||||
database.user_remove(args.username)
|
||||
|
||||
@staticmethod
|
||||
def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for create user subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("user-add", help="create or update user",
|
||||
description="update user for web services with the given password and role. "
|
||||
"In case if password was not entered it will be asked interactively")
|
||||
parser.add_argument("username", help="username for web service")
|
||||
parser.add_argument("--key", help="optional PGP key used by this user. The private key must be imported")
|
||||
parser.add_argument("--packager", help="optional packager id used for build process in form of "
|
||||
"`Name Surname <mail@example.com>`")
|
||||
parser.add_argument(
|
||||
"-p", "--password", help="user password. Blank password will be treated as empty password, "
|
||||
"which is in particular must be used for OAuth2 authorization type.")
|
||||
parser.add_argument("-R", "--role", help="user access level",
|
||||
type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read)
|
||||
parser.set_defaults(action=Action.Update, architecture="", exit_code=False, lock=None, quiet=True,
|
||||
report=False, repository="")
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for user list subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("user-list", help="user known users and their access",
|
||||
description="list users from the user mapping and their roles")
|
||||
parser.add_argument("username", help="filter users by username", nargs="?")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||
action="store_true")
|
||||
parser.add_argument("-R", "--role", help="filter users by role", type=UserAccess,
|
||||
choices=enum_values(UserAccess))
|
||||
parser.set_defaults(action=Action.List, architecture="", lock=None, quiet=True, report=False, repository="",
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for user removal subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("user-remove", help="remove user",
|
||||
description="remove user from the user mapping and update the configuration")
|
||||
parser.add_argument("username", help="username for web service")
|
||||
parser.set_defaults(action=Action.Remove, architecture="", exit_code=False, lock=None, quiet=True,
|
||||
report=False, repository="")
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def user_create(args: argparse.Namespace) -> User:
|
||||
"""
|
||||
@ -92,3 +161,9 @@ class Users(Handler):
|
||||
|
||||
return User(username=args.username, password=password, access=args.role,
|
||||
packager_id=args.packager, key=args.key)
|
||||
|
||||
arguments = [
|
||||
_set_user_add_parser,
|
||||
_set_user_list_parser,
|
||||
_set_user_remove_parser,
|
||||
]
|
||||
|
@ -22,7 +22,7 @@ import copy
|
||||
|
||||
from typing import Any
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.configuration.schema import CONFIGURATION_SCHEMA, ConfigurationSchema
|
||||
from ahriman.core.exceptions import ExtensionError
|
||||
@ -63,6 +63,25 @@ class Validate(Handler):
|
||||
# as we reach this part it means that we always have errors
|
||||
Validate.check_status(args.exit_code, False)
|
||||
|
||||
@staticmethod
|
||||
def _set_service_config_validate_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for config validation subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-config-validate", aliases=["config-validate", "repo-config-validate"],
|
||||
help="validate system configuration",
|
||||
description="validate configuration and print found errors")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if configuration is invalid",
|
||||
action="store_true")
|
||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def schema(repository_id: RepositoryId, configuration: Configuration) -> ConfigurationSchema:
|
||||
"""
|
||||
@ -136,3 +155,5 @@ class Validate(Handler):
|
||||
Validate.schema_merge(value, schema[key])
|
||||
|
||||
return schema
|
||||
|
||||
arguments = [_set_service_config_validate_parser]
|
||||
|
@ -25,7 +25,7 @@ from collections.abc import Generator
|
||||
from importlib import metadata
|
||||
|
||||
from ahriman import __version__
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import VersionPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
@ -59,6 +59,22 @@ class Versions(Handler):
|
||||
packages = Versions.package_dependencies("ahriman")
|
||||
VersionPrinter("Installed packages", dict(packages))(verbose=False, separator=" ")
|
||||
|
||||
@staticmethod
|
||||
def _set_help_version_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for version subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("help-version", aliases=["version"], help="application version",
|
||||
description="print application and its dependencies versions")
|
||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def package_dependencies(root: str) -> Generator[tuple[str, str], None, None]:
|
||||
"""
|
||||
@ -96,3 +112,5 @@ class Versions(Handler):
|
||||
yield distribution.name, distribution.version
|
||||
except metadata.PackageNotFoundError:
|
||||
continue
|
||||
|
||||
arguments = [_set_help_version_parser]
|
||||
|
@ -20,8 +20,9 @@
|
||||
import argparse
|
||||
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.spawn import Spawn
|
||||
from ahriman.core.triggers import TriggerLoader
|
||||
@ -71,6 +72,21 @@ class Web(Handler):
|
||||
spawner.stop()
|
||||
spawner.join()
|
||||
|
||||
@staticmethod
|
||||
def _set_web_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for web subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("web", help="web server", description="start web server")
|
||||
parser.set_defaults(architecture="", lock=Path("ahriman-web.pid"), report=False, repository="")
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def extract_arguments(args: argparse.Namespace, configuration: Configuration) -> Generator[str, None, None]:
|
||||
"""
|
||||
@ -100,3 +116,5 @@ class Web(Handler):
|
||||
# arguments from configuration
|
||||
if (wait_timeout := configuration.getint("web", "wait_timeout", fallback=None)) is not None:
|
||||
yield from ["--wait-timeout", str(wait_timeout)]
|
||||
|
||||
arguments = [_set_web_parser]
|
||||
|
@ -17,14 +17,14 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from typing import Any
|
||||
|
||||
try:
|
||||
import aiohttp_security
|
||||
_has_aiohttp_security = True
|
||||
except ImportError:
|
||||
_has_aiohttp_security = False
|
||||
|
||||
from typing import Any
|
||||
|
||||
|
||||
__all__ = ["authorized_userid", "check_authorized", "forget", "remember"]
|
||||
|
||||
|
@ -17,7 +17,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from logging import NullHandler # pylint: disable=imports-out-of-order
|
||||
# pylint: disable=imports-out-of-order
|
||||
from logging import NullHandler
|
||||
from typing import Any
|
||||
|
||||
|
||||
|
78
src/ahriman/core/module_loader.py
Normal file
78
src/ahriman/core/module_loader.py
Normal file
@ -0,0 +1,78 @@
|
||||
#
|
||||
# Copyright (c) 2021-2024 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import inspect
|
||||
|
||||
from collections.abc import Generator
|
||||
from importlib import import_module
|
||||
from pathlib import Path
|
||||
from pkgutil import ModuleInfo, walk_packages
|
||||
from types import ModuleType
|
||||
from typing import Any, TypeGuard, TypeVar
|
||||
|
||||
|
||||
__all__ = ["implementations"]
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def _modules(module_root: Path, prefix: str) -> Generator[ModuleInfo, None, None]:
|
||||
"""
|
||||
extract available modules from package
|
||||
|
||||
Args:
|
||||
module_root(Path): module root path
|
||||
prefix(str): modules package prefix
|
||||
|
||||
Yields:
|
||||
ModuleInfo: module information each available module
|
||||
"""
|
||||
prefix = f"{prefix}." if prefix else ""
|
||||
for module_info in walk_packages([str(module_root)], prefix):
|
||||
if module_info.ispkg:
|
||||
yield from _modules(module_root / module_info.name, prefix)
|
||||
else:
|
||||
yield module_info
|
||||
|
||||
|
||||
def implementations(root_module: ModuleType, base_class: type[T]) -> Generator[type[T], None, None]:
|
||||
"""
|
||||
extract implementations of the ``base_class`` from the module
|
||||
|
||||
Args:
|
||||
root_module(ModuleType): root module
|
||||
base_class(type[T]): base class type
|
||||
|
||||
Yields:
|
||||
type[T]: found implementations
|
||||
"""
|
||||
def is_base_class(clazz: Any) -> TypeGuard[type[T]]:
|
||||
return inspect.isclass(clazz) \
|
||||
and issubclass(clazz, base_class) and clazz != base_class \
|
||||
and clazz.__module__ == module.__name__
|
||||
|
||||
prefix = root_module.__name__
|
||||
|
||||
for module_root in root_module.__path__:
|
||||
for module_info in _modules(Path(module_root), prefix):
|
||||
module = import_module(module_info.name)
|
||||
|
||||
for _, attribute in inspect.getmembers(module, is_base_class):
|
||||
yield attribute
|
@ -18,93 +18,35 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from aiohttp.web import Application, View
|
||||
from collections.abc import Generator
|
||||
from importlib.machinery import SourceFileLoader
|
||||
from pathlib import Path
|
||||
from pkgutil import ModuleInfo, iter_modules
|
||||
from types import ModuleType
|
||||
from typing import Any, Type, TypeGuard
|
||||
|
||||
import ahriman.web.views
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.module_loader import implementations
|
||||
from ahriman.web.views.base import BaseView
|
||||
|
||||
|
||||
__all__ = ["setup_routes"]
|
||||
|
||||
|
||||
def _dynamic_routes(module_root: Path, configuration: Configuration) -> dict[str, Type[View]]:
|
||||
def _dynamic_routes(configuration: Configuration) -> dict[str, type[View]]:
|
||||
"""
|
||||
extract dynamic routes based on views
|
||||
|
||||
Args:
|
||||
module_root(Path): root module path with views
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
dict[str, Type[View]]: map of the route to its view
|
||||
dict[str, type[View]]: map of the route to its view
|
||||
"""
|
||||
def is_base_view(clazz: Any) -> TypeGuard[Type[BaseView]]:
|
||||
return isinstance(clazz, type) and issubclass(clazz, BaseView)
|
||||
|
||||
routes: dict[str, Type[View]] = {}
|
||||
for module_info in _modules(module_root):
|
||||
module = _module(module_info)
|
||||
|
||||
for attribute_name in dir(module):
|
||||
view = getattr(module, attribute_name)
|
||||
if not is_base_view(view):
|
||||
continue
|
||||
|
||||
view_routes = view.routes(configuration)
|
||||
routes.update([(route, view) for route in view_routes])
|
||||
routes: dict[str, type[View]] = {}
|
||||
for view in implementations(ahriman.web.views, BaseView):
|
||||
view_routes = view.routes(configuration)
|
||||
routes.update([(route, view) for route in view_routes])
|
||||
|
||||
return routes
|
||||
|
||||
|
||||
def _module(module_info: ModuleInfo) -> ModuleType:
|
||||
"""
|
||||
load module from its info
|
||||
|
||||
Args:
|
||||
module_info(ModuleInfo): module info descriptor
|
||||
|
||||
Returns:
|
||||
ModuleType: loaded module
|
||||
|
||||
Raises:
|
||||
ValueError: if loader is not an instance of :class:`importlib.machinery.SourceFileLoader`
|
||||
"""
|
||||
module_spec = module_info.module_finder.find_spec(module_info.name, None)
|
||||
if module_spec is None:
|
||||
raise ValueError(f"Module specification of {module_info.name} is empty")
|
||||
|
||||
loader = module_spec.loader
|
||||
if not isinstance(loader, SourceFileLoader):
|
||||
raise ValueError(f"Module {module_info.name} loader is not an instance of SourceFileLoader")
|
||||
|
||||
module = ModuleType(loader.name)
|
||||
loader.exec_module(module)
|
||||
|
||||
return module
|
||||
|
||||
|
||||
def _modules(module_root: Path) -> Generator[ModuleInfo, None, None]:
|
||||
"""
|
||||
extract available modules from package
|
||||
|
||||
Args:
|
||||
module_root(Path): module root path
|
||||
|
||||
Yields:
|
||||
ModuleInfo: module information each available module
|
||||
"""
|
||||
for module_info in iter_modules([str(module_root)]):
|
||||
if module_info.ispkg:
|
||||
yield from _modules(module_root / module_info.name)
|
||||
else:
|
||||
yield module_info
|
||||
|
||||
|
||||
def setup_routes(application: Application, configuration: Configuration) -> None:
|
||||
"""
|
||||
setup all defined routes
|
||||
@ -115,6 +57,5 @@ def setup_routes(application: Application, configuration: Configuration) -> None
|
||||
"""
|
||||
application.router.add_static("/static", configuration.getpath("web", "static_path"), follow_symlinks=True)
|
||||
|
||||
views_root = Path(__file__).parent / "views"
|
||||
for route, view in _dynamic_routes(views_root, configuration).items():
|
||||
for route, view in _dynamic_routes(configuration).items():
|
||||
application.router.add_view(route, view)
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
|
||||
from ahriman.models.log_handler import LogHandler
|
||||
@ -19,7 +19,7 @@ def test_call(args: argparse.Namespace, configuration: Configuration, mocker: Mo
|
||||
args.log_handler = LogHandler.Console
|
||||
args.quiet = False
|
||||
args.report = False
|
||||
mocker.patch("ahriman.application.handlers.Handler.run")
|
||||
mocker.patch("ahriman.application.handlers.handler.Handler.run")
|
||||
configuration_mock = mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration)
|
||||
log_handler_mock = mocker.patch("ahriman.core.log.log_loader.LogLoader.handler", return_value=args.log_handler)
|
||||
log_load_mock = mocker.patch("ahriman.core.log.log_loader.LogLoader.load")
|
||||
@ -76,7 +76,7 @@ def test_execute(args: argparse.Namespace, mocker: MockerFixture) -> None:
|
||||
RepositoryId("i686", "aur"),
|
||||
RepositoryId("x86_64", "aur"),
|
||||
]
|
||||
mocker.patch("ahriman.application.handlers.Handler.repositories_extract", return_value=ids)
|
||||
mocker.patch("ahriman.application.handlers.handler.Handler.repositories_extract", return_value=ids)
|
||||
starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap")
|
||||
|
||||
Handler.execute(args)
|
||||
@ -88,7 +88,7 @@ def test_execute_multiple_not_supported(args: argparse.Namespace, mocker: Mocker
|
||||
must raise an exception if multiple architectures are not supported by the handler
|
||||
"""
|
||||
args.command = "web"
|
||||
mocker.patch("ahriman.application.handlers.Handler.repositories_extract", return_value=[
|
||||
mocker.patch("ahriman.application.handlers.handler.Handler.repositories_extract", return_value=[
|
||||
RepositoryId("i686", "aur"),
|
||||
RepositoryId("x86_64", "aur"),
|
||||
])
|
||||
@ -102,7 +102,7 @@ def test_execute_single(args: argparse.Namespace, mocker: MockerFixture) -> None
|
||||
"""
|
||||
must run execution in current process if only one architecture supplied
|
||||
"""
|
||||
mocker.patch("ahriman.application.handlers.Handler.repositories_extract", return_value=[
|
||||
mocker.patch("ahriman.application.handlers.handler.Handler.repositories_extract", return_value=[
|
||||
RepositoryId("x86_64", "aur"),
|
||||
])
|
||||
starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap")
|
||||
|
@ -3,7 +3,7 @@ import pytest
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Add
|
||||
from ahriman.application.handlers.add import Add
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.package import Package
|
||||
@ -82,7 +82,7 @@ def test_run_with_updates(args: argparse.Namespace, configuration: Configuration
|
||||
mocker.patch("ahriman.application.application.Application.add")
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.update", return_value=result)
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
changes_mock = mocker.patch("ahriman.application.application.Application.changes")
|
||||
updates_mock = mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
|
||||
dependencies_mock = mocker.patch("ahriman.application.application.Application.with_dependencies",
|
||||
@ -113,7 +113,7 @@ def test_run_no_changes(args: argparse.Namespace, configuration: Configuration,
|
||||
mocker.patch("ahriman.application.application.Application.add")
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.application.Application.update")
|
||||
mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
mocker.patch("ahriman.application.application.Application.updates")
|
||||
mocker.patch("ahriman.application.application.Application.with_dependencies")
|
||||
mocker.patch("ahriman.application.application.Application.print_updates")
|
||||
@ -138,7 +138,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
|
||||
mocker.patch("ahriman.application.application.Application.with_dependencies")
|
||||
mocker.patch("ahriman.application.application.Application.updates")
|
||||
mocker.patch("ahriman.application.application.Application.print_updates")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Add.run(args, repository_id, configuration, report=False)
|
||||
|
@ -4,7 +4,7 @@ from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from ahriman.application.handlers import Backup
|
||||
from ahriman.application.handlers.backup import Backup
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
@ -28,7 +28,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
must run command
|
||||
"""
|
||||
args = _default_args(args)
|
||||
mocker.patch("ahriman.application.handlers.Backup.get_paths", return_value=[Path("path")])
|
||||
mocker.patch("ahriman.application.handlers.backup.Backup.get_paths", return_value=[Path("path")])
|
||||
tarfile = MagicMock()
|
||||
add_mock = tarfile.__enter__.return_value = MagicMock()
|
||||
mocker.patch("ahriman.application.handlers.backup.tarfile.open", return_value=tarfile)
|
||||
|
@ -3,7 +3,7 @@ import pytest
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Change
|
||||
from ahriman.application.handlers.change import Change
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.repository import Repository
|
||||
@ -36,7 +36,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
application_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_get",
|
||||
return_value=Changes("sha", "change"))
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -55,7 +55,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
|
||||
args.exit_code = True
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_get", return_value=Changes())
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Change.run(args, repository_id, configuration, report=False)
|
||||
|
@ -2,7 +2,7 @@ import argparse
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Clean
|
||||
from ahriman.application.handlers.clean import Clean
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Copy
|
||||
from ahriman.application.handlers.copy import Copy
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.build_status import BuildStatusEnum
|
||||
@ -37,7 +37,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
args = _default_args(args)
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Copy.copy_package")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.copy.Copy.copy_package")
|
||||
update_mock = mocker.patch("ahriman.application.application.Application.update")
|
||||
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
|
||||
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
|
||||
@ -59,7 +59,7 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, repo
|
||||
args.remove = True
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
|
||||
mocker.patch("ahriman.application.handlers.Copy.copy_package")
|
||||
mocker.patch("ahriman.application.handlers.copy.Copy.copy_package")
|
||||
mocker.patch("ahriman.application.application.Application.update")
|
||||
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
|
||||
|
||||
@ -77,7 +77,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
|
||||
args.exit_code = True
|
||||
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[])
|
||||
mocker.patch("ahriman.application.application.Application.update")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Copy.run(args, repository_id, configuration, report=False)
|
||||
|
@ -2,7 +2,7 @@ import argparse
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Daemon
|
||||
from ahriman.application.handlers.daemon import Daemon
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.package import Package
|
||||
@ -31,7 +31,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, package_ahr
|
||||
"""
|
||||
args = _default_args(args)
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
run_mock = mocker.patch("ahriman.application.handlers.Update.run")
|
||||
run_mock = mocker.patch("ahriman.application.handlers.update.Update.run")
|
||||
iter_mock = mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.__iter__",
|
||||
return_value=iter([[package_ahriman.base]]))
|
||||
|
||||
@ -50,7 +50,7 @@ def test_run_no_partitions(args: argparse.Namespace, configuration: Configuratio
|
||||
args = _default_args(args)
|
||||
args.partitions = False
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
run_mock = mocker.patch("ahriman.application.handlers.Update.run")
|
||||
run_mock = mocker.patch("ahriman.application.handlers.update.Update.run")
|
||||
iter_mock = mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.__iter__",
|
||||
return_value=iter([[]]))
|
||||
|
||||
@ -67,7 +67,7 @@ def test_run_no_updates(args: argparse.Namespace, configuration: Configuration,
|
||||
"""
|
||||
args = _default_args(args)
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
run_mock = mocker.patch("ahriman.application.handlers.Update.run")
|
||||
run_mock = mocker.patch("ahriman.application.handlers.update.Update.run")
|
||||
iter_mock = mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.__iter__",
|
||||
return_value=iter([[package_ahriman.base], None]))
|
||||
|
||||
|
@ -3,7 +3,7 @@ import pytest
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Dump
|
||||
from ahriman.application.handlers.dump import Dump
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@ import argparse
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.ahriman import _parser
|
||||
from ahriman.application.handlers import Help
|
||||
from ahriman.application.handlers.help import Help
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@ import argparse
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import KeyImport
|
||||
from ahriman.application.handlers.key_import import KeyImport
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
|
||||
|
@ -6,7 +6,7 @@ from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Patch
|
||||
from ahriman.application.handlers.patch import Patch
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.action import Action
|
||||
@ -40,9 +40,9 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
args = _default_args(args)
|
||||
args.action = Action.Update
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
patch_mock = mocker.patch("ahriman.application.handlers.Patch.patch_create_from_diff",
|
||||
patch_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_create_from_diff",
|
||||
return_value=(args.package, PkgbuildPatch(None, "patch")))
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_create")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_create")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Patch.run(args, repository_id, configuration, report=False)
|
||||
@ -61,8 +61,9 @@ def test_run_function(args: argparse.Namespace, configuration: Configuration, re
|
||||
args.variable = "version"
|
||||
patch = PkgbuildPatch(args.variable, args.patch)
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
patch_mock = mocker.patch("ahriman.application.handlers.Patch.patch_create_from_function", return_value=patch)
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_create")
|
||||
patch_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_create_from_function",
|
||||
return_value=patch)
|
||||
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_create")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Patch.run(args, repository_id, configuration, report=False)
|
||||
@ -79,7 +80,7 @@ def test_run_list(args: argparse.Namespace, configuration: Configuration, reposi
|
||||
args.action = Action.List
|
||||
args.variable = ["version"]
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_list")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_list")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Patch.run(args, repository_id, configuration, report=False)
|
||||
@ -95,7 +96,7 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, repo
|
||||
args.action = Action.Remove
|
||||
args.variable = ["version"]
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_remove")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_remove")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Patch.run(args, repository_id, configuration, report=False)
|
||||
@ -163,7 +164,7 @@ def test_patch_set_list(application: Application, mocker: MockerFixture) -> None
|
||||
get_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_patches_get",
|
||||
return_value=[PkgbuildPatch(None, "patch"), PkgbuildPatch("version", "value")])
|
||||
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
Patch.patch_set_list(application, "ahriman", ["version"], False)
|
||||
get_mock.assert_called_once_with("ahriman", None)
|
||||
@ -178,7 +179,7 @@ def test_patch_set_list_all(application: Application, mocker: MockerFixture) ->
|
||||
get_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_patches_get",
|
||||
return_value=[PkgbuildPatch(None, "patch")])
|
||||
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
Patch.patch_set_list(application, "ahriman", None, False)
|
||||
get_mock.assert_called_once_with("ahriman", None)
|
||||
@ -191,7 +192,7 @@ def test_patch_set_list_empty_exception(application: Application, mocker: Mocker
|
||||
must raise ExitCode exception on empty patch list
|
||||
"""
|
||||
mocker.patch("ahriman.core.status.local_client.LocalClient.package_patches_get", return_value={})
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
Patch.patch_set_list(application, "ahriman", [], True)
|
||||
check_mock.assert_called_once_with(True, [])
|
||||
|
@ -5,7 +5,7 @@ from pytest_mock import MockerFixture
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Rebuild
|
||||
from ahriman.application.handlers.rebuild import Rebuild
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||
@ -43,11 +43,12 @@ def test_run(args: argparse.Namespace, package_ahriman: Package, configuration:
|
||||
result = Result()
|
||||
result.add_updated(package_ahriman)
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
extract_mock = mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[package_ahriman])
|
||||
extract_mock = mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages",
|
||||
return_value=[package_ahriman])
|
||||
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on",
|
||||
return_value=[package_ahriman])
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.update", return_value=result)
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -70,7 +71,7 @@ def test_run_extract_packages(args: argparse.Namespace, configuration: Configura
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.application.Application.add")
|
||||
mocker.patch("ahriman.application.application.Application.print_updates")
|
||||
extract_mock = mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
|
||||
extract_mock = mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages", return_value=[])
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Rebuild.run(args, repository_id, configuration, report=False)
|
||||
@ -85,9 +86,9 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, rep
|
||||
args = _default_args(args)
|
||||
args.dry_run = True
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[package_ahriman])
|
||||
mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages", return_value=[package_ahriman])
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.update")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -106,7 +107,7 @@ def test_run_filter(args: argparse.Namespace, configuration: Configuration, repo
|
||||
args.depends_on = ["python-aur"]
|
||||
mocker.patch("ahriman.application.application.Application.update")
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
|
||||
mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages", return_value=[])
|
||||
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -122,7 +123,7 @@ def test_run_without_filter(args: argparse.Namespace, configuration: Configurati
|
||||
args = _default_args(args)
|
||||
mocker.patch("ahriman.application.application.Application.update")
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
|
||||
mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages", return_value=[])
|
||||
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -139,10 +140,10 @@ def test_run_update_empty_exception(args: argparse.Namespace, configuration: Con
|
||||
args.exit_code = True
|
||||
args.dry_run = True
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages")
|
||||
mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages")
|
||||
mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on", return_value=[])
|
||||
mocker.patch("ahriman.application.application.Application.print_updates")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Rebuild.run(args, repository_id, configuration, report=False)
|
||||
@ -157,10 +158,10 @@ def test_run_build_empty_exception(args: argparse.Namespace, configuration: Conf
|
||||
args = _default_args(args)
|
||||
args.exit_code = True
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages")
|
||||
mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages")
|
||||
mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on", return_value=[package_ahriman])
|
||||
mocker.patch("ahriman.application.application.Application.update", return_value=Result())
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Rebuild.run(args, repository_id, configuration, report=False)
|
||||
|
@ -2,7 +2,7 @@ import argparse
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Remove
|
||||
from ahriman.application.handlers.remove import Remove
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
|
||||
|
@ -3,7 +3,7 @@ import pytest
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import RemoveUnknown
|
||||
from ahriman.application.handlers.remove_unknown import RemoveUnknown
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.package import Package
|
||||
|
@ -3,7 +3,7 @@ import pytest
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Repositories
|
||||
from ahriman.application.handlers.repositories import Repositories
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
args = _default_args(args)
|
||||
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
_, repository_id = configuration.check_loaded()
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Handler.repositories_extract",
|
||||
application_mock = mocker.patch("ahriman.application.handlers.handler.Handler.repositories_extract",
|
||||
return_value=[repository_id])
|
||||
|
||||
Repositories.run(args, repository_id, configuration, report=False)
|
||||
|
@ -4,7 +4,7 @@ from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from ahriman.application.handlers import Restore
|
||||
from ahriman.application.handlers.restore import Restore
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.ahriman import _parser
|
||||
from ahriman.application.handlers import Run
|
||||
from ahriman.application.handlers.run import Run
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import ExitCode
|
||||
|
||||
@ -29,7 +29,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
must run command
|
||||
"""
|
||||
args = _default_args(args)
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Run.run_command")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.run.Run.run_command")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Run.run(args, repository_id, configuration, report=False)
|
||||
@ -42,7 +42,7 @@ def test_run_failed(args: argparse.Namespace, configuration: Configuration, mock
|
||||
"""
|
||||
args = _default_args(args)
|
||||
args.command = ["help", "config"]
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Run.run_command", return_value=False)
|
||||
application_mock = mocker.patch("ahriman.application.handlers.run.Run.run_command", return_value=False)
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
with pytest.raises(ExitCode):
|
||||
@ -54,8 +54,13 @@ def test_run_command(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly run external command
|
||||
"""
|
||||
execute_mock = mocker.patch("ahriman.application.handlers.Help.execute")
|
||||
Run.run_command(["help"], _parser())
|
||||
# because of dynamic load we need to patch exact instance of the object
|
||||
parser = _parser()
|
||||
subparser = next((action for action in parser._actions if isinstance(action, argparse._SubParsersAction)), None)
|
||||
action = subparser.choices["help"]
|
||||
execute_mock = mocker.patch.object(action.get_default("handler"), "execute")
|
||||
|
||||
Run.run_command(["help"], parser)
|
||||
execute_mock.assert_called_once_with(pytest.helpers.anyvar(int))
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.application.handlers import Search
|
||||
from ahriman.application.handlers.search import Search
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import OptionError
|
||||
from ahriman.core.repository import Repository
|
||||
@ -39,7 +39,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
aur_search_mock = mocker.patch("ahriman.core.alpm.remote.AUR.multisearch", return_value=[aur_package_ahriman])
|
||||
official_search_mock = mocker.patch("ahriman.core.alpm.remote.Official.multisearch",
|
||||
return_value=[aur_package_ahriman])
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -64,7 +64,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
|
||||
mocker.patch("ahriman.core.alpm.remote.Official.multisearch", return_value=[])
|
||||
mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Search.run(args, repository_id, configuration, report=False)
|
||||
@ -80,7 +80,7 @@ def test_run_sort(args: argparse.Namespace, configuration: Configuration, reposi
|
||||
mocker.patch("ahriman.core.alpm.remote.AUR.multisearch", return_value=[aur_package_ahriman])
|
||||
mocker.patch("ahriman.core.alpm.remote.Official.multisearch", return_value=[])
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
sort_mock = mocker.patch("ahriman.application.handlers.Search.sort")
|
||||
sort_mock = mocker.patch("ahriman.application.handlers.search.Search.sort")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Search.run(args, repository_id, configuration, report=False)
|
||||
@ -100,7 +100,7 @@ def test_run_sort_by(args: argparse.Namespace, configuration: Configuration, rep
|
||||
mocker.patch("ahriman.core.alpm.remote.AUR.multisearch", return_value=[aur_package_ahriman])
|
||||
mocker.patch("ahriman.core.alpm.remote.Official.multisearch", return_value=[])
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
sort_mock = mocker.patch("ahriman.application.handlers.Search.sort")
|
||||
sort_mock = mocker.patch("ahriman.application.handlers.search.Search.sort")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Search.run(args, repository_id, configuration, report=False)
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman import __version__
|
||||
from ahriman.application.handlers import ServiceUpdates
|
||||
from ahriman.application.handlers.service_updates import ServiceUpdates
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.package import Package
|
||||
@ -34,7 +34,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
package_mock = mocker.patch("ahriman.models.package.Package.from_aur", return_value=package_ahriman)
|
||||
application_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
ServiceUpdates.run(args, repository_id, configuration, report=False)
|
||||
@ -53,7 +53,7 @@ def test_run_skip(args: argparse.Namespace, configuration: Configuration, reposi
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.models.package.Package.from_aur", return_value=package_ahriman)
|
||||
application_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
ServiceUpdates.run(args, repository_id, configuration, report=False)
|
||||
|
@ -7,7 +7,7 @@ from typing import Any
|
||||
from unittest.mock import call as MockCall
|
||||
from urllib.parse import quote_plus as urlencode
|
||||
|
||||
from ahriman.application.handlers import Setup
|
||||
from ahriman.application.handlers.setup import Setup
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import MissingArchitectureError
|
||||
from ahriman.core.repository import Repository
|
||||
@ -50,11 +50,11 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
"""
|
||||
args = _default_args(args)
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
ahriman_configuration_mock = mocker.patch("ahriman.application.handlers.Setup.configuration_create_ahriman")
|
||||
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.Setup.configuration_create_devtools")
|
||||
makepkg_configuration_mock = mocker.patch("ahriman.application.handlers.Setup.configuration_create_makepkg")
|
||||
sudo_configuration_mock = mocker.patch("ahriman.application.handlers.Setup.configuration_create_sudo")
|
||||
executable_mock = mocker.patch("ahriman.application.handlers.Setup.executable_create")
|
||||
ahriman_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_ahriman")
|
||||
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_devtools")
|
||||
makepkg_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_makepkg")
|
||||
sudo_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_sudo")
|
||||
executable_mock = mocker.patch("ahriman.application.handlers.setup.Setup.executable_create")
|
||||
init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -95,12 +95,12 @@ def test_run_with_server(args: argparse.Namespace, configuration: Configuration,
|
||||
args = _default_args(args)
|
||||
args.server = "server"
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.handlers.Setup.configuration_create_ahriman")
|
||||
mocker.patch("ahriman.application.handlers.Setup.configuration_create_makepkg")
|
||||
mocker.patch("ahriman.application.handlers.Setup.configuration_create_sudo")
|
||||
mocker.patch("ahriman.application.handlers.Setup.executable_create")
|
||||
mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_ahriman")
|
||||
mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_makepkg")
|
||||
mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_sudo")
|
||||
mocker.patch("ahriman.application.handlers.setup.Setup.executable_create")
|
||||
mocker.patch("ahriman.core.alpm.repo.Repo.init")
|
||||
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.Setup.configuration_create_devtools")
|
||||
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_devtools")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Setup.run(args, repository_id, configuration, report=False)
|
||||
|
@ -3,7 +3,7 @@ import pytest
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Shell
|
||||
from ahriman.application.handlers.shell import Shell
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
|
||||
|
@ -2,7 +2,7 @@ import argparse
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Sign
|
||||
from ahriman.application.handlers.sign import Sign
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
|
||||
|
@ -5,7 +5,7 @@ from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.application.handlers import Statistics
|
||||
from ahriman.application.handlers.statistics import Statistics
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.core.utils import pretty_datetime, utcnow
|
||||
@ -42,7 +42,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
events = [Event("1", "1"), Event("2", "2")]
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
events_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.event_get", return_value=events)
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Statistics.stats_per_package")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.statistics.Statistics.stats_per_package")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Statistics.run(args, repository_id, configuration, report=False)
|
||||
@ -60,7 +60,7 @@ def test_run_for_package(args: argparse.Namespace, configuration: Configuration,
|
||||
events = [Event("1", "1"), Event("2", "2")]
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
events_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.event_get", return_value=events)
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Statistics.stats_for_package")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.statistics.Statistics.stats_for_package")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Statistics.run(args, repository_id, configuration, report=False)
|
||||
@ -77,7 +77,7 @@ def test_run_convert_from_date(args: argparse.Namespace, configuration: Configur
|
||||
date = utcnow()
|
||||
args.from_date = date.isoformat()
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.handlers.Statistics.stats_per_package")
|
||||
mocker.patch("ahriman.application.handlers.statistics.Statistics.stats_per_package")
|
||||
events_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.event_get", return_value=[])
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -94,7 +94,7 @@ def test_run_convert_to_date(args: argparse.Namespace, configuration: Configurat
|
||||
date = utcnow()
|
||||
args.to_date = date.isoformat()
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.handlers.Statistics.stats_per_package")
|
||||
mocker.patch("ahriman.application.handlers.statistics.Statistics.stats_per_package")
|
||||
events_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.event_get", return_value=[])
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -147,8 +147,8 @@ def test_stats_for_package(mocker: MockerFixture) -> None:
|
||||
must print statistics for the package
|
||||
"""
|
||||
events = [Event("event", "1"), Event("event", "1")]
|
||||
events_mock = mocker.patch("ahriman.application.handlers.Statistics.event_stats")
|
||||
chart_plot = mocker.patch("ahriman.application.handlers.Statistics.plot_times")
|
||||
events_mock = mocker.patch("ahriman.application.handlers.statistics.Statistics.event_stats")
|
||||
chart_plot = mocker.patch("ahriman.application.handlers.statistics.Statistics.plot_times")
|
||||
|
||||
Statistics.stats_for_package("event", events, None)
|
||||
events_mock.assert_called_once_with("event", events)
|
||||
@ -161,8 +161,8 @@ def test_stats_for_package_with_chart(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
local = Path("local")
|
||||
events = [Event("event", "1"), Event("event", "1")]
|
||||
mocker.patch("ahriman.application.handlers.Statistics.event_stats")
|
||||
chart_plot = mocker.patch("ahriman.application.handlers.Statistics.plot_times")
|
||||
mocker.patch("ahriman.application.handlers.statistics.Statistics.event_stats")
|
||||
chart_plot = mocker.patch("ahriman.application.handlers.statistics.Statistics.plot_times")
|
||||
|
||||
Statistics.stats_for_package("event", events, local)
|
||||
chart_plot.assert_called_once_with("event", events, local)
|
||||
@ -174,8 +174,8 @@ def test_stats_per_package(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
events = [Event("event", "1"), Event("event", "2"), Event("event", "1")]
|
||||
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
events_mock = mocker.patch("ahriman.application.handlers.Statistics.event_stats")
|
||||
chart_plot = mocker.patch("ahriman.application.handlers.Statistics.plot_packages")
|
||||
events_mock = mocker.patch("ahriman.application.handlers.statistics.Statistics.event_stats")
|
||||
chart_plot = mocker.patch("ahriman.application.handlers.statistics.Statistics.plot_packages")
|
||||
|
||||
Statistics.stats_per_package("event", events, None)
|
||||
print_mock.assert_has_calls([
|
||||
@ -192,8 +192,8 @@ def test_stats_per_package_with_chart(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
local = Path("local")
|
||||
events = [Event("event", "1"), Event("event", "2"), Event("event", "1")]
|
||||
mocker.patch("ahriman.application.handlers.Statistics.event_stats")
|
||||
chart_plot = mocker.patch("ahriman.application.handlers.Statistics.plot_packages")
|
||||
mocker.patch("ahriman.application.handlers.statistics.Statistics.event_stats")
|
||||
chart_plot = mocker.patch("ahriman.application.handlers.statistics.Statistics.plot_packages")
|
||||
|
||||
Statistics.stats_per_package("event", events, local)
|
||||
chart_plot.assert_called_once_with("event", {"1": 2, "2": 1}, local)
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.application.handlers import Status
|
||||
from ahriman.application.handlers.status import Status
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.repository import Repository
|
||||
@ -43,7 +43,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
application_mock = mocker.patch("ahriman.core.status.Client.status_get")
|
||||
packages_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_get", return_value=packages)
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -67,7 +67,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.core.status.Client.status_get")
|
||||
mocker.patch("ahriman.core.status.local_client.LocalClient.package_get", return_value=[])
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Status.run(args, repository_id, configuration, report=False)
|
||||
|
@ -2,7 +2,7 @@ import argparse
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import StatusUpdate
|
||||
from ahriman.application.handlers.status_update import StatusUpdate
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.repository import Repository
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.application.handlers import Structure
|
||||
from ahriman.application.handlers.structure import Structure
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.package import Package
|
||||
|
@ -4,7 +4,7 @@ from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.application.handlers import TreeMigrate
|
||||
from ahriman.application.handlers.tree_migrate import TreeMigrate
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
@ -15,7 +15,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
must run command
|
||||
"""
|
||||
tree_create_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.TreeMigrate.tree_move")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.tree_migrate.TreeMigrate.tree_move")
|
||||
_, repository_id = configuration.check_loaded()
|
||||
old_paths = configuration.repository_paths
|
||||
new_paths = RepositoryPaths(old_paths.root, old_paths.repository_id, _force_current_tree=True)
|
||||
|
@ -2,7 +2,7 @@ import argparse
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Triggers
|
||||
from ahriman.application.handlers.triggers import Triggers
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.package import Package
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.ahriman import _parser
|
||||
from ahriman.application.handlers import UnsafeCommands
|
||||
from ahriman.application.handlers.unsafe_commands import UnsafeCommands
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
must run command
|
||||
"""
|
||||
args = _default_args(args)
|
||||
commands_mock = mocker.patch("ahriman.application.handlers.UnsafeCommands.get_unsafe_commands",
|
||||
commands_mock = mocker.patch("ahriman.application.handlers.unsafe_commands.UnsafeCommands.get_unsafe_commands",
|
||||
return_value=["command"])
|
||||
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
|
||||
@ -44,9 +44,9 @@ def test_run_check(args: argparse.Namespace, configuration: Configuration, mocke
|
||||
"""
|
||||
args = _default_args(args)
|
||||
args.subcommand = ["clean"]
|
||||
commands_mock = mocker.patch("ahriman.application.handlers.UnsafeCommands.get_unsafe_commands",
|
||||
commands_mock = mocker.patch("ahriman.application.handlers.unsafe_commands.UnsafeCommands.get_unsafe_commands",
|
||||
return_value=["command"])
|
||||
check_mock = mocker.patch("ahriman.application.handlers.UnsafeCommands.check_unsafe")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.unsafe_commands.UnsafeCommands.check_unsafe")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
UnsafeCommands.run(args, repository_id, configuration, report=False)
|
||||
@ -58,7 +58,7 @@ def test_check_unsafe(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must check if command is unsafe
|
||||
"""
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
UnsafeCommands.check_unsafe(["service-clean"], ["service-clean"], _parser())
|
||||
check_mock.assert_called_once_with(True, False)
|
||||
|
||||
@ -67,7 +67,7 @@ def test_check_unsafe_safe(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must check if command is safe
|
||||
"""
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
UnsafeCommands.check_unsafe(["package-status"], ["service-clean"], _parser())
|
||||
check_mock.assert_called_once_with(True, True)
|
||||
|
||||
|
@ -5,7 +5,7 @@ from pytest_mock import MockerFixture
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Update
|
||||
from ahriman.application.handlers.update import Update
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.package import Package
|
||||
@ -49,7 +49,7 @@ def test_run(args: argparse.Namespace, package_ahriman: Package, configuration:
|
||||
result.add_updated(package_ahriman)
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.update", return_value=result)
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
dependencies_mock = mocker.patch("ahriman.application.application.Application.with_dependencies",
|
||||
return_value=[package_ahriman])
|
||||
updates_mock = mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
|
||||
@ -81,7 +81,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
|
||||
args.dry_run = True
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.application.Application.updates", return_value=[])
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Update.run(args, repository_id, configuration, report=False)
|
||||
@ -101,7 +101,7 @@ def test_run_update_empty_exception(args: argparse.Namespace, package_ahriman: P
|
||||
mocker.patch("ahriman.application.application.Application.with_dependencies", return_value=[package_ahriman])
|
||||
mocker.patch("ahriman.application.application.Application.print_updates")
|
||||
mocker.patch("ahriman.application.application.Application.changes")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Update.run(args, repository_id, configuration, report=False)
|
||||
@ -117,7 +117,7 @@ def test_run_dry_run(args: argparse.Namespace, package_ahriman: Package, configu
|
||||
args.dry_run = True
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.update")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
updates_mock = mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
|
||||
changes_mock = mocker.patch("ahriman.application.application.Application.changes")
|
||||
|
||||
@ -140,7 +140,7 @@ def test_run_no_changes(args: argparse.Namespace, configuration: Configuration,
|
||||
args.changes = False
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
mocker.patch("ahriman.application.application.Application.update")
|
||||
mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
mocker.patch("ahriman.application.application.Application.updates")
|
||||
changes_mock = mocker.patch("ahriman.application.application.Application.changes")
|
||||
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.application.handlers import Users
|
||||
from ahriman.application.handlers.users import Users
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.exceptions import PasswordError
|
||||
@ -42,7 +42,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, database: S
|
||||
packager_id=args.packager, key=args.key)
|
||||
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
|
||||
mocker.patch("ahriman.models.user.User.hash_password", return_value=user)
|
||||
create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user)
|
||||
create_user_mock = mocker.patch("ahriman.application.handlers.users.Users.user_create", return_value=user)
|
||||
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -60,7 +60,7 @@ def test_run_empty_salt(args: argparse.Namespace, configuration: Configuration,
|
||||
user = User(username=args.username, password=args.password, access=args.role,
|
||||
packager_id=args.packager, key=args.key)
|
||||
mocker.patch("ahriman.models.user.User.hash_password", return_value=user)
|
||||
create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user)
|
||||
create_user_mock = mocker.patch("ahriman.application.handlers.users.Users.user_create", return_value=user)
|
||||
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -80,7 +80,7 @@ def test_run_empty_salt_without_password(args: argparse.Namespace, configuration
|
||||
packager_id=args.packager, key=args.key)
|
||||
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
|
||||
mocker.patch("ahriman.models.user.User.hash_password", return_value=user)
|
||||
create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user)
|
||||
create_user_mock = mocker.patch("ahriman.application.handlers.users.Users.user_create", return_value=user)
|
||||
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -97,7 +97,7 @@ def test_run_list(args: argparse.Namespace, configuration: Configuration, databa
|
||||
args = _default_args(args)
|
||||
args.action = Action.List
|
||||
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
list_mock = mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[user])
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
@ -116,7 +116,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
|
||||
args.exit_code = True
|
||||
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
|
||||
mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[])
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Users.run(args, repository_id, configuration, report=False)
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Validate
|
||||
from ahriman.application.handlers.validate import Validate
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.configuration.schema import CONFIGURATION_SCHEMA
|
||||
from ahriman.core.configuration.validator import Validator
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.application.handlers import Versions
|
||||
from ahriman.application.handlers.versions import Versions
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
"""
|
||||
must run command
|
||||
"""
|
||||
application_mock = mocker.patch("ahriman.application.handlers.Versions.package_dependencies")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.versions.Versions.package_dependencies")
|
||||
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
|
@ -3,7 +3,7 @@ import pytest
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.handlers import Web
|
||||
from ahriman.application.handlers.web import Web
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.log_handler import LogHandler
|
||||
@ -43,7 +43,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
stop_mock = mocker.patch("ahriman.core.spawn.Spawn.stop")
|
||||
join_mock = mocker.patch("ahriman.core.spawn.Spawn.join")
|
||||
_, repository_id = configuration.check_loaded()
|
||||
mocker.patch("ahriman.application.handlers.Handler.repositories_extract", return_value=[repository_id])
|
||||
mocker.patch("ahriman.application.handlers.handler.Handler.repositories_extract", return_value=[repository_id])
|
||||
|
||||
Web.run(args, repository_id, configuration, report=False)
|
||||
setup_mock.assert_called_once_with(configuration, pytest.helpers.anyvar(int), [repository_id])
|
||||
|
@ -5,7 +5,7 @@ from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application import ahriman
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.action import Action
|
||||
from ahriman.models.build_status import BuildStatusEnum
|
||||
|
25
tests/ahriman/core/test_module_loader.py
Normal file
25
tests/ahriman/core/test_module_loader.py
Normal file
@ -0,0 +1,25 @@
|
||||
import ahriman.web.views
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from ahriman.core.module_loader import _modules, implementations
|
||||
from ahriman.web.views.base import BaseView
|
||||
|
||||
|
||||
def test_implementations() -> None:
|
||||
"""
|
||||
must load implementations from the package
|
||||
"""
|
||||
routes = list(implementations(ahriman.web.views, BaseView))
|
||||
assert routes
|
||||
assert all(isinstance(view, type) for view in routes)
|
||||
assert all(issubclass(view, BaseView) for view in routes)
|
||||
|
||||
|
||||
def test_modules() -> None:
|
||||
"""
|
||||
must load modules
|
||||
"""
|
||||
modules = list(_modules(Path(__file__).parent.parent, "ahriman.web.views"))
|
||||
assert modules
|
||||
assert all(not module.ispkg for module in modules)
|
@ -1,14 +1,9 @@
|
||||
import pytest
|
||||
|
||||
from aiohttp.web import Application
|
||||
from importlib.machinery import ModuleSpec
|
||||
from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from types import ModuleType
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.utils import walk
|
||||
from ahriman.web.routes import _dynamic_routes, _module, _modules, setup_routes
|
||||
from ahriman.web.routes import _dynamic_routes, setup_routes
|
||||
|
||||
|
||||
def test_dynamic_routes(resource_path_root: Path, configuration: Configuration) -> None:
|
||||
@ -22,54 +17,11 @@ def test_dynamic_routes(resource_path_root: Path, configuration: Configuration)
|
||||
if file.suffix == ".py" and file.name not in ("__init__.py", "base.py", "status_view_guard.py")
|
||||
]
|
||||
|
||||
routes = _dynamic_routes(views_root, configuration)
|
||||
routes = _dynamic_routes(configuration)
|
||||
assert all(isinstance(view, type) for view in routes.values())
|
||||
assert len(set(routes.values())) == len(expected_views)
|
||||
|
||||
|
||||
def test_module(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must load module
|
||||
"""
|
||||
exec_mock = mocker.patch("importlib.machinery.SourceFileLoader.exec_module")
|
||||
module_info = next(_modules(Path(__file__).parent))
|
||||
|
||||
module = _module(module_info)
|
||||
assert isinstance(module, ModuleType)
|
||||
exec_mock.assert_called_once_with(pytest.helpers.anyvar(int))
|
||||
|
||||
|
||||
def test_module_no_spec(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must raise ValueError if spec is not available
|
||||
"""
|
||||
mocker.patch("importlib.machinery.FileFinder.find_spec", return_value=None)
|
||||
module_info = next(_modules(Path(__file__).parent))
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
_module(module_info)
|
||||
|
||||
|
||||
def test_module_no_loader(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must raise ValueError if loader is not available
|
||||
"""
|
||||
mocker.patch("importlib.machinery.FileFinder.find_spec", return_value=ModuleSpec("name", None))
|
||||
module_info = next(_modules(Path(__file__).parent))
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
_module(module_info)
|
||||
|
||||
|
||||
def test_modules() -> None:
|
||||
"""
|
||||
must load modules
|
||||
"""
|
||||
modules = list(_modules(Path(__file__).parent.parent))
|
||||
assert modules
|
||||
assert all(not module.ispkg for module in modules)
|
||||
|
||||
|
||||
def test_setup_routes(application: Application, configuration: Configuration) -> None:
|
||||
"""
|
||||
must generate non-empty list of routes
|
||||
|
@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from aiohttp.test_utils import TestClient
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.views.static import StaticView
|
||||
@ -31,12 +32,12 @@ async def test_get(client_with_auth: TestClient) -> None:
|
||||
assert response.headers["Location"] == "/static/favicon.ico"
|
||||
|
||||
|
||||
async def test_get_not_found(client_with_auth: TestClient) -> None:
|
||||
async def test_get_not_found(client_with_auth: TestClient, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must raise not found if path is invalid
|
||||
"""
|
||||
for route in client_with_auth.app.router.routes():
|
||||
if hasattr(route.handler, "ROUTES"):
|
||||
route.handler.ROUTES = []
|
||||
print([route.handler for route in client_with_auth.app.router.routes()])
|
||||
static_route = next(route for route in client_with_auth.app.router.routes() if route.handler == StaticView)
|
||||
mocker.patch.object(static_route.handler, "ROUTES", [])
|
||||
response = await client_with_auth.get("/favicon.ico", allow_redirects=False)
|
||||
assert response.status == 404
|
||||
|
4
tox.ini
4
tox.ini
@ -27,8 +27,6 @@ description = Run common checks like linter, mypy, etc
|
||||
deps =
|
||||
{[tox]dependencies}
|
||||
-e .[check]
|
||||
allowlist_externals =
|
||||
bash
|
||||
setenv =
|
||||
MYPYPATH=src
|
||||
commands =
|
||||
@ -36,7 +34,7 @@ commands =
|
||||
pylint --rcfile=.pylintrc "src/{[tox]project_name}"
|
||||
bandit -c .bandit.yml -r "src/{[tox]project_name}"
|
||||
bandit -c .bandit-test.yml -r "tests/{[tox]project_name}"
|
||||
bash -c 'mypy {[mypy]flags} -p "{[tox]project_name}" --install-types --non-interactive || mypy {[mypy]flags} -p "{[tox]project_name}"'
|
||||
mypy {[mypy]flags} -p "{[tox]project_name}" --install-types --non-interactive
|
||||
|
||||
[testenv:docs]
|
||||
description = Generate source files for documentation
|
||||
|
Reference in New Issue
Block a user