mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
Compare commits
8 Commits
b7eef41b39
...
a1281989f3
Author | SHA1 | Date | |
---|---|---|---|
a1281989f3 | |||
440d7785d2 | |||
3d97490c11 | |||
89d8227ba6 | |||
fca9239cd2 | |||
be57045972 | |||
6fe77eb465 | |||
7c6c24a46d |
2
.github/workflows/setup.sh
vendored
2
.github/workflows/setup.sh
vendored
@ -30,7 +30,7 @@ mv dist/ahriman-*.tar.gz package/archlinux
|
||||
chmod +777 package/archlinux # because fuck you that's why
|
||||
cd package/archlinux
|
||||
sudo -u nobody -- makepkg -cf --skipchecksums --noconfirm
|
||||
sudo -u nobody -- makepkg --packagelist | grep -v -- -debug- | pacman -U --noconfirm -
|
||||
sudo -u nobody -- makepkg --packagelist | grep -v -- -debug- | pacman -U --noconfirm --nodeps -
|
||||
# create machine-id which is required by build tools
|
||||
systemd-machine-id-setup
|
||||
|
||||
|
@ -79,7 +79,8 @@ RUN cd "/home/build/ahriman" && \
|
||||
tox -e archive && \
|
||||
cp ./dist/*.tar.gz "package/archlinux" && \
|
||||
cd "package/archlinux" && \
|
||||
runuser -u build -- makepkg --noconfirm --install --skipchecksums && \
|
||||
runuser -u build -- makepkg --noconfirm --skipchecksums && \
|
||||
runuser -u build -- makepkg --packagelist | grep -v -- -debug- | pacman -U --noconfirm --nodeps - && \
|
||||
cd / && rm -r "/home/build/ahriman"
|
||||
|
||||
# cleanup unused
|
||||
|
@ -4,7 +4,7 @@ set -e
|
||||
[ -n "$AHRIMAN_DEBUG" ] && set -x
|
||||
|
||||
# configuration tune
|
||||
cat <<EOF > "/etc/ahriman.ini.d/00-docker.ini"
|
||||
cat <<EOF > "/etc/ahriman.ini.d/01-docker.ini"
|
||||
[repository]
|
||||
root = $AHRIMAN_REPOSITORY_ROOT
|
||||
|
||||
|
@ -12,6 +12,14 @@ ahriman.core.configuration.configuration module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.configuration.configuration\_multi\_dict module
|
||||
------------------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.configuration.configuration_multi_dict
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.configuration.schema module
|
||||
----------------------------------------
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -13,7 +13,27 @@ There are two variable types which have been added to default ones, they are pat
|
||||
* By default, it splits value by spaces excluding empty elements.
|
||||
* In case if quotation mark (``"`` or ``'``) will be found, any spaces inside will be ignored.
|
||||
* In order to use quotation mark inside value it is required to put it to another quotation mark, e.g. ``wor"'"d "with quote"`` will be parsed as ``["wor'd", "with quote"]`` and vice versa.
|
||||
* Unclosed quotation mark is not allowed and will rise an exception.
|
||||
* Unclosed quotation mark is not allowed and will raise an exception.
|
||||
|
||||
It is also possible to split list option between multiple declarations. To do so, append key name with ``[]`` (like PHP, sorry!), e.g.:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[section]
|
||||
list[] = value1
|
||||
list[] = value2
|
||||
|
||||
will lead to ``${section:list}`` value to be set to ``value1 value2``. The values will be set in order of appearance, meaning that values which appear in different include files will be set in alphabetical order of file names. In order to reset list values, set option to empty string, e.g.:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[section]
|
||||
list[] = value1
|
||||
list[] =
|
||||
list[] = value2
|
||||
list[] = value3
|
||||
|
||||
will set option ``${section:list}`` to ``value2 value3``. Alternatively, setting the original option (e.g. ``list`` in the example above) will also reset value, though the subsequent options with leading ``[]`` will append the previous value.
|
||||
|
||||
Path values, except for casting to ``pathlib.Path`` type, will be also expanded to absolute paths relative to the configuration path. E.g. if path is set to ``ahriman.ini.d/logging.ini`` and root configuration path is ``/etc/ahriman.ini``, the value will be expanded to ``/etc/ahriman.ini.d/logging.ini``. In order to disable path expand, use the full path, e.g. ``/etc/ahriman.ini.d/logging.ini``.
|
||||
|
||||
@ -22,7 +42,7 @@ Configuration allows string interpolation from the same configuration file, e.g.
|
||||
.. code-block:: ini
|
||||
|
||||
[section]
|
||||
key = ${anoher_key}
|
||||
key = ${another_key}
|
||||
another_key = value
|
||||
|
||||
will read value for the ``key`` option from ``another_key`` in the same section. In case if the cross-section reference is required, the ``${section:another_key}`` notation must be used. It also allows string interpolation from environment variables, e.g.:
|
||||
|
@ -1,51 +1,81 @@
|
||||
# Maintainer: Evgeniy Alekseev
|
||||
|
||||
pkgname='ahriman'
|
||||
pkgbase='ahriman'
|
||||
pkgname=('ahriman' 'ahriman-triggers' 'ahriman-web')
|
||||
pkgver=2.15.2
|
||||
pkgrel=1
|
||||
pkgdesc="ArcH linux ReposItory MANager"
|
||||
arch=('any')
|
||||
url="https://github.com/arcan1s/ahriman"
|
||||
license=('GPL3')
|
||||
url="https://ahriman.readthedocs.io/"
|
||||
license=('GPL-3.0-or-later')
|
||||
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-bcrypt' 'python-inflection' 'python-pyelftools' 'python-requests')
|
||||
makedepends=('python-build' 'python-flit' 'python-installer' 'python-wheel')
|
||||
optdepends=('python-aioauth-client: web server with OAuth2 authorization'
|
||||
'python-aiohttp: web server'
|
||||
'python-aiohttp-apispec>=3.0.0: web server'
|
||||
'python-aiohttp-cors: web server'
|
||||
'python-aiohttp-jinja2: web server'
|
||||
'python-aiohttp-security: web server with authorization'
|
||||
'python-aiohttp-session: web server with authorization'
|
||||
'python-boto3: sync to s3'
|
||||
'python-cerberus: configuration validator'
|
||||
'python-cryptography: web server with authorization'
|
||||
'python-matplotlib: usage statistics chart'
|
||||
'python-requests-unixsocket2: client report to web server by unix socket'
|
||||
'python-jinja: html report generation'
|
||||
'python-systemd: journal support'
|
||||
'rsync: sync by using rsync')
|
||||
source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgname-$pkgver.tar.gz"
|
||||
'ahriman.sysusers'
|
||||
'ahriman.tmpfiles')
|
||||
install="$pkgname.install"
|
||||
backup=('etc/ahriman.ini'
|
||||
'etc/ahriman.ini.d/logging.ini')
|
||||
source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgbase-$pkgver.tar.gz"
|
||||
"$pkgbase.sysusers"
|
||||
"$pkgbase.tmpfiles")
|
||||
|
||||
build() {
|
||||
cd "$pkgname-$pkgver"
|
||||
cd "$pkgbase-$pkgver"
|
||||
|
||||
python -m build --wheel --no-isolation
|
||||
python -m build --wheel --no-isolation
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$pkgname-$pkgver"
|
||||
package_ahriman() {
|
||||
pkgname='ahriman'
|
||||
optdepends=('ahriman-triggers: additional extensions for the application'
|
||||
'ahriman-web: web server'
|
||||
'python-boto3: sync to s3'
|
||||
'python-cerberus: configuration validator'
|
||||
'python-matplotlib: usage statistics chart'
|
||||
'python-requests-unixsocket2: client report to web server by unix socket'
|
||||
'python-jinja: html report generation'
|
||||
'python-systemd: journal support'
|
||||
'rsync: sync by using rsync')
|
||||
install="$pkgname.install"
|
||||
backup=('etc/ahriman.ini'
|
||||
'etc/ahriman.ini.d/logging.ini')
|
||||
|
||||
python -m installer --destdir="$pkgdir" "dist/$pkgname-$pkgver-py3-none-any.whl"
|
||||
cd "$pkgbase-$pkgver"
|
||||
|
||||
# keep usr/share configs as reference and copy them to /etc
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini" "$pkgdir/etc/ahriman.ini"
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini.d/logging.ini" "$pkgdir/etc/ahriman.ini.d/logging.ini"
|
||||
python -m installer --destdir="$pkgdir" "dist/$pkgbase-$pkgver-py3-none-any.whl"
|
||||
python subpackages.py "$pkgdir" "$pkgname"
|
||||
|
||||
install -Dm644 "$srcdir/$pkgname.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgname.conf"
|
||||
install -Dm644 "$srcdir/$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf"
|
||||
# keep usr/share configs as reference and copy them to /etc
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgbase/settings/ahriman.ini" "$pkgdir/etc/ahriman.ini"
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgbase/settings/ahriman.ini.d/logging.ini" "$pkgdir/etc/ahriman.ini.d/logging.ini"
|
||||
|
||||
install -Dm644 "$srcdir/$pkgbase.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgbase.conf"
|
||||
install -Dm644 "$srcdir/$pkgbase.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgbase.conf"
|
||||
}
|
||||
|
||||
package_ahriman-triggers() {
|
||||
pkgname='ahriman-triggers'
|
||||
pkgdesc="ArcH linux ReposItory MANager, additional extensions"
|
||||
depends=("$pkgbase=$pkgver")
|
||||
backup=('etc/ahriman.ini.d/00-triggers.ini')
|
||||
|
||||
cd "$pkgbase-$pkgver"
|
||||
|
||||
python -m installer --destdir="$pkgdir" "dist/$pkgbase-$pkgver-py3-none-any.whl"
|
||||
python subpackages.py "$pkgdir" "$pkgname"
|
||||
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgbase/settings/ahriman.ini.d/00-triggers.ini" "$pkgdir/etc/ahriman.ini.d/00-triggers.ini"
|
||||
}
|
||||
|
||||
package_ahriman-web() {
|
||||
pkgname='ahriman-web'
|
||||
pkgdesc="ArcH linux ReposItory MANager, web server"
|
||||
depends=("$pkgbase=$pkgver" 'python-aiohttp-apispec>=3.0.0' 'python-aiohttp-cors' 'python-aiohttp-jinja2')
|
||||
optdepends=('python-aioauth-client: OAuth2 authorization support'
|
||||
'python-aiohttp-security: authorization support'
|
||||
'python-aiohttp-session: authorization support'
|
||||
'python-cryptography: authorization support')
|
||||
backup=('etc/ahriman.ini.d/00-web.ini')
|
||||
|
||||
cd "$pkgbase-$pkgver"
|
||||
|
||||
python -m installer --destdir="$pkgdir" "dist/$pkgbase-$pkgver-py3-none-any.whl"
|
||||
python subpackages.py "$pkgdir" "$pkgname"
|
||||
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgbase/settings/ahriman.ini.d/00-web.ini" "$pkgdir/etc/ahriman.ini.d/00-web.ini"
|
||||
}
|
||||
|
@ -23,32 +23,6 @@ sync_files_database = yes
|
||||
; as additional option for some subcommands). If set to no, databases must be synchronized manually.
|
||||
use_ahriman_cache = yes
|
||||
|
||||
[auth]
|
||||
; Authentication provider, must be one of disabled, configuration, pam, oauth.
|
||||
target = disabled
|
||||
; Allow read-only endpoint to be called without authentication.
|
||||
allow_read_only = yes
|
||||
; OAuth2 application client ID and secret. Required if oauth is used.
|
||||
;client_id =
|
||||
;client_secret =
|
||||
; Cookie secret key to be used for cookies encryption. Must be valid 32 bytes URL-safe base64-encoded string.
|
||||
; If not set, it will be generated automatically.
|
||||
;cookie_secret_key =
|
||||
; Name of the secondary group to be used as admin group in the service. Required if pam is used.
|
||||
;full_access_group = wheel
|
||||
; Authentication cookie expiration in seconds.
|
||||
;max_age = 604800
|
||||
; OAuth2 provider icon for the web interface.
|
||||
;oauth_icon = google
|
||||
; OAuth2 provider class name, one of provided by aioauth-client. Required if oauth is used.
|
||||
;oauth_provider = GoogleClient
|
||||
; Scopes list for OAuth2 provider. Required if oauth is used.
|
||||
;oauth_scopes = https://www.googleapis.com/auth/userinfo.email
|
||||
; Allow login as root user (only applicable if PAM is used).
|
||||
;permit_root_login = no
|
||||
; Optional password salt.
|
||||
;salt =
|
||||
|
||||
[build]
|
||||
; List of additional flags passed to archbuild command.
|
||||
;archbuild_flags =
|
||||
@ -65,15 +39,17 @@ makepkg_flags = --nocolor --ignorearch
|
||||
; List of paths to be used for implicit dependency scan. Regular expressions are supported.
|
||||
scan_paths = ^usr/lib(?!/cmake).*$
|
||||
; List of enabled triggers in the order of calls.
|
||||
triggers = ahriman.core.gitremote.RemotePullTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.gitremote.RemotePushTrigger
|
||||
triggers[] = ahriman.core.gitremote.RemotePullTrigger
|
||||
triggers[] = ahriman.core.report.ReportTrigger
|
||||
triggers[] = ahriman.core.upload.UploadTrigger
|
||||
triggers[] = ahriman.core.gitremote.RemotePushTrigger
|
||||
; List of well-known triggers. Used only for configuration purposes.
|
||||
triggers_known = ahriman.core.distributed.WorkerLoaderTrigger ahriman.core.distributed.WorkerRegisterTrigger ahriman.core.distributed.WorkerTrigger ahriman.core.distributed.WorkerUnregisterTrigger ahriman.core.gitremote.RemotePullTrigger ahriman.core.gitremote.RemotePushTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.support.KeyringTrigger ahriman.core.support.MirrorlistTrigger
|
||||
triggers_known[] = ahriman.core.gitremote.RemotePullTrigger
|
||||
triggers_known[] = ahriman.core.gitremote.RemotePushTrigger
|
||||
triggers_known[] = ahriman.core.report.ReportTrigger
|
||||
triggers_known[] = ahriman.core.upload.UploadTrigger
|
||||
; Maximal age in seconds of the VCS packages before their version will be updated with its remote source.
|
||||
;vcs_allowed_age = 604800
|
||||
; List of worker nodes addresses used for build process, e.g.:
|
||||
; workers = http://10.0.0.1:8080 http://10.0.0.3:8080
|
||||
; Empty list means run on the local instance.
|
||||
;workers =
|
||||
|
||||
[repository]
|
||||
; Application root.
|
||||
@ -102,79 +78,6 @@ suppress_http_log_errors = yes
|
||||
; Optional username for authentication (if enabled).
|
||||
;username =
|
||||
|
||||
[web]
|
||||
; External address of the web service. Will be used for some features like OAuth. If none set will be generated as
|
||||
; address = http://${web:host}:${web:port}
|
||||
;address = http://${web:host}:${web:port}
|
||||
; Enable file upload endpoint used by some triggers.
|
||||
;enable_archive_upload = no
|
||||
; Address to bind the server.
|
||||
host = 127.0.0.1
|
||||
; Full URL to the repository index page used by templates.
|
||||
;index_url =
|
||||
; Max file size in bytes which can be uploaded to the server. Requires ${web:enable_archive_upload} to be enabled.
|
||||
;max_body_size =
|
||||
; Port to listen. Must be set, if the web service is enabled.
|
||||
;port =
|
||||
; Disable status (e.g. package status, logs, etc) endpoints. Useful for build only modes.
|
||||
;service_only = no
|
||||
; Path to directory with static files.
|
||||
static_path = ${templates}/static
|
||||
; List of directories with templates.
|
||||
templates = ${prefix}/share/ahriman/templates
|
||||
; Path to unix socket. If none set, unix socket will be disabled.
|
||||
;unix_socket =
|
||||
; Allow unix socket to be world readable.
|
||||
;unix_socket_unsafe = yes
|
||||
; Maximum amount of time in seconds to be waited before lock will be free, used by spawned processes (0 is infinite).
|
||||
;wait_timeout =
|
||||
|
||||
[keyring]
|
||||
; List of configuration section names for keyring generator plugin, e.g.:
|
||||
; target = keyring-trigger
|
||||
target =
|
||||
|
||||
; Keyring generator trigger sample.
|
||||
;[keyring-trigger]
|
||||
; Generator type name.
|
||||
;type = keyring-generator
|
||||
; Optional keyring package description.
|
||||
;description=
|
||||
; Optional URL to the repository homepage.
|
||||
;homepage=
|
||||
; Keyring package licenses list.
|
||||
;license = Unlicense
|
||||
; Optional keyring package name.
|
||||
;package =
|
||||
; Optional packager PGP keys list. If none set, it will read from database.
|
||||
;packagers =
|
||||
; List of revoked PGP keys.
|
||||
;revoked =
|
||||
; List of master PGP keys. If none set, the sign.key value will be used.
|
||||
;trusted =
|
||||
|
||||
[mirrorlist]
|
||||
; List of configuration section names for mirrorlist generator plugin, e.g.:
|
||||
; target = mirrorlist-trigger
|
||||
target =
|
||||
|
||||
; Mirror list generator trigger sample.
|
||||
;[mirrorlist-trigger]
|
||||
; Generator type name.
|
||||
;type = mirrorlist-generator
|
||||
; Optional mirrorlist package description.
|
||||
;description=
|
||||
; Optional URL to the repository homepage.
|
||||
;homepage=
|
||||
; Mirrorlist package licenses list.
|
||||
;license = Unlicense
|
||||
; Optional mirrorlist package name.
|
||||
;package =
|
||||
; Absolute path to generated mirrorlist file, usually path inside /etc/pacman.d directory.
|
||||
;path =
|
||||
; List of repository mirrors.
|
||||
;servers =
|
||||
|
||||
[remote-pull]
|
||||
; List of configuration section names for git remote pull plugin, e.g.:
|
||||
; target = remote-pull-trigger
|
||||
@ -246,7 +149,7 @@ template = email-index.jinja2
|
||||
; Template name to be used for full packages list generation (same as HTML report).
|
||||
;template_full =
|
||||
; List of directories with templates.
|
||||
templates = ${prefix}/share/ahriman/templates
|
||||
templates[] = ${prefix}/share/ahriman/templates
|
||||
; SMTP user.
|
||||
;user =
|
||||
|
||||
@ -265,7 +168,7 @@ templates = ${prefix}/share/ahriman/templates
|
||||
; Template name to be used.
|
||||
template = repo-index.jinja2
|
||||
; List of directories with templates.
|
||||
templates = ${prefix}/share/ahriman/templates
|
||||
templates[] = ${prefix}/share/ahriman/templates
|
||||
|
||||
; Remote service callback trigger configuration sample.
|
||||
[remote-call]
|
||||
@ -295,7 +198,7 @@ templates = ${prefix}/share/ahriman/templates
|
||||
; Template name to be used.
|
||||
template = rss.jinja2
|
||||
; List of directories with templates.
|
||||
templates = ${prefix}/share/ahriman/templates
|
||||
templates[] = ${prefix}/share/ahriman/templates
|
||||
|
||||
; Telegram reporting trigger configuration sample.
|
||||
[telegram]
|
||||
@ -316,7 +219,7 @@ template = telegram-index.jinja2
|
||||
; Telegram specific template mode, one of MarkdownV2, HTML or Markdown.
|
||||
;template_type = HTML
|
||||
; List of directories with templates.
|
||||
templates = ${prefix}/share/ahriman/templates
|
||||
templates[] = ${prefix}/share/ahriman/templates
|
||||
; HTTP request timeout in seconds.
|
||||
;timeout = 30
|
||||
|
||||
|
56
package/share/ahriman/settings/ahriman.ini.d/00-triggers.ini
Normal file
56
package/share/ahriman/settings/ahriman.ini.d/00-triggers.ini
Normal file
@ -0,0 +1,56 @@
|
||||
[build]
|
||||
; List of well-known triggers. Used only for configuration purposes.
|
||||
triggers_known[] = ahriman.core.distributed.WorkerLoaderTrigger
|
||||
triggers_known[] = ahriman.core.distributed.WorkerTrigger
|
||||
triggers_known[] = ahriman.core.support.KeyringTrigger
|
||||
triggers_known[] = ahriman.core.support.MirrorlistTrigger
|
||||
; List of worker nodes addresses used for build process, e.g.:
|
||||
; workers = http://10.0.0.1:8080 http://10.0.0.3:8080
|
||||
; Empty list means run on the local instance.
|
||||
;workers =
|
||||
|
||||
[keyring]
|
||||
; List of configuration section names for keyring generator plugin, e.g.:
|
||||
; target = keyring-trigger
|
||||
target =
|
||||
|
||||
; Keyring generator trigger sample.
|
||||
;[keyring-trigger]
|
||||
; Generator type name.
|
||||
;type = keyring-generator
|
||||
; Optional keyring package description.
|
||||
;description=
|
||||
; Optional URL to the repository homepage.
|
||||
;homepage=
|
||||
; Keyring package licenses list.
|
||||
;license = Unlicense
|
||||
; Optional keyring package name.
|
||||
;package =
|
||||
; Optional packager PGP keys list. If none set, it will read from database.
|
||||
;packagers =
|
||||
; List of revoked PGP keys.
|
||||
;revoked =
|
||||
; List of master PGP keys. If none set, the sign.key value will be used.
|
||||
;trusted =
|
||||
|
||||
[mirrorlist]
|
||||
; List of configuration section names for mirrorlist generator plugin, e.g.:
|
||||
; target = mirrorlist-trigger
|
||||
target =
|
||||
|
||||
; Mirror list generator trigger sample.
|
||||
;[mirrorlist-trigger]
|
||||
; Generator type name.
|
||||
;type = mirrorlist-generator
|
||||
; Optional mirrorlist package description.
|
||||
;description=
|
||||
; Optional URL to the repository homepage.
|
||||
;homepage=
|
||||
; Mirrorlist package licenses list.
|
||||
;license = Unlicense
|
||||
; Optional mirrorlist package name.
|
||||
;package =
|
||||
; Absolute path to generated mirrorlist file, usually path inside /etc/pacman.d directory.
|
||||
;path =
|
||||
; List of repository mirrors.
|
||||
;servers =
|
52
package/share/ahriman/settings/ahriman.ini.d/00-web.ini
Normal file
52
package/share/ahriman/settings/ahriman.ini.d/00-web.ini
Normal file
@ -0,0 +1,52 @@
|
||||
[auth]
|
||||
; Authentication provider, must be one of disabled, configuration, pam, oauth.
|
||||
target = disabled
|
||||
; Allow read-only endpoint to be called without authentication.
|
||||
allow_read_only = yes
|
||||
; OAuth2 application client ID and secret. Required if oauth is used.
|
||||
;client_id =
|
||||
;client_secret =
|
||||
; Cookie secret key to be used for cookies encryption. Must be valid 32 bytes URL-safe base64-encoded string.
|
||||
; If not set, it will be generated automatically.
|
||||
;cookie_secret_key =
|
||||
; Name of the secondary group to be used as admin group in the service. Required if pam is used.
|
||||
;full_access_group = wheel
|
||||
; Authentication cookie expiration in seconds.
|
||||
;max_age = 604800
|
||||
; OAuth2 provider icon for the web interface.
|
||||
;oauth_icon = google
|
||||
; OAuth2 provider class name, one of provided by aioauth-client. Required if oauth is used.
|
||||
;oauth_provider = GoogleClient
|
||||
; Scopes list for OAuth2 provider. Required if oauth is used.
|
||||
;oauth_scopes = https://www.googleapis.com/auth/userinfo.email
|
||||
; Allow login as root user (only applicable if PAM is used).
|
||||
;permit_root_login = no
|
||||
; Optional password salt.
|
||||
;salt =
|
||||
|
||||
[web]
|
||||
; External address of the web service. Will be used for some features like OAuth. If none set will be generated as
|
||||
; address = http://${web:host}:${web:port}
|
||||
;address = http://${web:host}:${web:port}
|
||||
; Enable file upload endpoint used by some triggers.
|
||||
;enable_archive_upload = no
|
||||
; Address to bind the server.
|
||||
host = 127.0.0.1
|
||||
; Full URL to the repository index page used by templates.
|
||||
;index_url =
|
||||
; Max file size in bytes which can be uploaded to the server. Requires ${web:enable_archive_upload} to be enabled.
|
||||
;max_body_size =
|
||||
; Port to listen. Must be set, if the web service is enabled.
|
||||
;port =
|
||||
; Disable status (e.g. package status, logs, etc) endpoints. Useful for build only modes.
|
||||
;service_only = no
|
||||
; Path to directory with static files.
|
||||
static_path = ${templates}/static
|
||||
; List of directories with templates.
|
||||
templates[] = ${prefix}/share/ahriman/templates
|
||||
; Path to unix socket. If none set, unix socket will be disabled.
|
||||
;unix_socket =
|
||||
; Allow unix socket to be world readable.
|
||||
;unix_socket_unsafe = yes
|
||||
; Maximum amount of time in seconds to be waited before lock will be free, used by spawned processes (0 is infinite).
|
||||
;wait_timeout =
|
@ -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:
|
||||
|
@ -95,6 +95,7 @@ include = [
|
||||
"CONTRIBUTING.md",
|
||||
"SECURITY.md",
|
||||
"package",
|
||||
"subpackages.py",
|
||||
"web.png",
|
||||
]
|
||||
exclude = [
|
||||
|
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:
|
||||
"""
|
||||
@ -161,8 +201,8 @@ class Setup(Handler):
|
||||
repository_server(str): url of the repository
|
||||
"""
|
||||
# allow_no_value=True is required because pacman uses boolean configuration in which just keys present
|
||||
# (e.g. NoProgressBar) which will lead to exception
|
||||
configuration = Configuration(allow_no_value=True)
|
||||
# (e.g. NoProgressBar) which will lead to exception. allow_multi_key=False is set just for fun
|
||||
configuration = Configuration(allow_no_value=True, allow_multi_key=False)
|
||||
# preserve case
|
||||
# stupid mypy thinks that it is impossible
|
||||
configuration.optionxform = lambda optionstr: optionstr # type: ignore[method-assign]
|
||||
@ -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"]
|
||||
|
||||
|
@ -25,6 +25,7 @@ from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Any, Self
|
||||
|
||||
from ahriman.core.configuration.configuration_multi_dict import ConfigurationMultiDict
|
||||
from ahriman.core.configuration.shell_interpolator import ShellInterpolator
|
||||
from ahriman.core.exceptions import InitializeError
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
@ -69,21 +70,27 @@ class Configuration(configparser.RawConfigParser):
|
||||
SYSTEM_CONFIGURATION_PATH = Path(sys.prefix) / "share" / "ahriman" / "settings" / "ahriman.ini"
|
||||
converters: dict[str, Callable[[str], Any]] # typing guard
|
||||
|
||||
def __init__(self, allow_no_value: bool = False) -> None:
|
||||
def __init__(self, allow_no_value: bool = False, allow_multi_key: bool = True) -> None:
|
||||
"""
|
||||
Args:
|
||||
allow_no_value(bool, optional): copies :class:`configparser.RawConfigParser` behaviour. In case if it is set
|
||||
to ``True``, the keys without values will be allowed (Default value = False)
|
||||
allow_multi_key(bool, optional): if set to ``False``, then the default dictionary class will be used to
|
||||
store keys internally. Otherwise, the special implementation will be used, which supports arrays
|
||||
(Default value = True)
|
||||
"""
|
||||
configparser.RawConfigParser.__init__(
|
||||
self,
|
||||
dict_type=ConfigurationMultiDict if allow_multi_key else dict, # type: ignore[arg-type]
|
||||
allow_no_value=allow_no_value,
|
||||
strict=False,
|
||||
empty_lines_in_values=not allow_multi_key,
|
||||
interpolation=ShellInterpolator(),
|
||||
converters={
|
||||
"list": shlex.split,
|
||||
"path": self._convert_path,
|
||||
"pathlist": lambda value: [self._convert_path(element) for element in shlex.split(value)],
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.repository_id: RepositoryId | None = None
|
||||
|
91
src/ahriman/core/configuration/configuration_multi_dict.py
Normal file
91
src/ahriman/core/configuration/configuration_multi_dict.py
Normal file
@ -0,0 +1,91 @@
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.exceptions import OptionError
|
||||
|
||||
|
||||
class ConfigurationMultiDict(dict[str, Any]):
|
||||
"""
|
||||
wrapper around :class:`dict` to handle multiple configuration keys as lists if they end with ``[]``.
|
||||
|
||||
Examples:
|
||||
This class is designed to be used only with :class:`configparser.RawConfigParser` class, but idea is that
|
||||
if the key ends with ``[]`` it will be treated as array and the result will be appended to the current value.
|
||||
In addition, if the value is empty, then it will clear previous values, e.g.:
|
||||
|
||||
>>> data = ConfigurationMultiDict()
|
||||
>>>
|
||||
>>> data["single"] = "value" # append normal key
|
||||
>>> print(data) # {"single": "value"}
|
||||
>>>
|
||||
>>> data["array[]"] = ["value1"] # append array value
|
||||
>>> data["array[]"] = ["value2"]
|
||||
>>> print(data) # {"single": "value", "array": ["value1 value2"]}
|
||||
>>>
|
||||
>>> data["array[]"] = [""] # clear previous values
|
||||
>>> data["array[]"] = ["value3"]
|
||||
>>> print(data) # {"single": "value", "array": ["value3"]}
|
||||
"""
|
||||
|
||||
def _set_array_value(self, key: str, value: Any) -> None:
|
||||
"""
|
||||
set array value. If the key already exists in the dictionary, its value will be prepended to new value
|
||||
|
||||
Args:
|
||||
key(str): key to insert
|
||||
value(Any): value of the related key
|
||||
|
||||
Raises:
|
||||
OptionError: if the key already exists in the dictionary, but not a single value list or a string
|
||||
"""
|
||||
match self.get(key):
|
||||
case [current_value] | str(current_value): # type: ignore[misc]
|
||||
value = f"{current_value} {value}"
|
||||
case None:
|
||||
pass
|
||||
case other:
|
||||
raise OptionError(other)
|
||||
super().__setitem__(key, [value])
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
"""
|
||||
set ``key`` to ``value``. If the value equals to ``[""]`` (array with empty string), then the key
|
||||
will be removed (as expected from :class:`configparser.RawConfigParser`). If the key ends with
|
||||
``[]``, the value will be treated as an array and vice versa.
|
||||
|
||||
Args:
|
||||
key(str): key to insert
|
||||
value(Any): value of the related key
|
||||
|
||||
Raises:
|
||||
OptionError: if ``key`` contains ``[]``, but not at the end of the string (e.g. ``prefix[]suffix``)
|
||||
"""
|
||||
real_key, is_key_array, remaining = key.partition("[]")
|
||||
if remaining:
|
||||
raise OptionError(key)
|
||||
|
||||
match value:
|
||||
case [""]: # empty value key
|
||||
self.pop(real_key, None)
|
||||
case [array_value] if is_key_array: # update array value
|
||||
self._set_array_value(real_key, array_value)
|
||||
case _: # normal key
|
||||
super().__setitem__(real_key, value)
|
@ -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
|
@ -461,7 +461,7 @@ def trim_package(package_name: str) -> str:
|
||||
str: package name without description or version bound
|
||||
"""
|
||||
for symbol in ("<", "=", ">", ":"):
|
||||
package_name = package_name.partition(symbol)[0]
|
||||
package_name, *_ = package_name.split(symbol, maxsplit=1)
|
||||
return package_name
|
||||
|
||||
|
||||
@ -478,7 +478,6 @@ def utcnow() -> datetime.datetime:
|
||||
def walk(directory_path: Path) -> Generator[Path, None, None]:
|
||||
"""
|
||||
list all file paths in given directory
|
||||
Credits to https://stackoverflow.com/a/64915960
|
||||
|
||||
Args:
|
||||
directory_path(Path): root directory path
|
||||
@ -487,18 +486,13 @@ def walk(directory_path: Path) -> Generator[Path, None, None]:
|
||||
Path: all found files in given directory with full path
|
||||
|
||||
Examples:
|
||||
Since the :mod:`pathlib` module does not provide an alternative to :func:`os.walk()`, this wrapper
|
||||
can be used instead::
|
||||
Wrapper around :func:`pathlib.Path.walk`, which yields only files instead::
|
||||
|
||||
>>> from pathlib import Path
|
||||
>>>
|
||||
>>> for file_path in walk(Path.cwd()):
|
||||
>>> print(file_path)
|
||||
|
||||
Note, however, that unlike the original method, it does not yield directories.
|
||||
"""
|
||||
for element in directory_path.iterdir():
|
||||
if element.is_dir():
|
||||
yield from walk(element)
|
||||
continue
|
||||
yield element
|
||||
for root, _, files in directory_path.walk(follow_symlinks=True):
|
||||
for file in files:
|
||||
yield root / file
|
||||
|
@ -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)
|
||||
|
132
subpackages.py
Normal file
132
subpackages.py
Normal file
@ -0,0 +1,132 @@
|
||||
#
|
||||
# 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 argparse
|
||||
import shutil
|
||||
import site
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
prefix = Path(sys.prefix).relative_to("/")
|
||||
site_packages = Path(site.getsitepackages()[0]).relative_to("/")
|
||||
SUBPACKAGES = {
|
||||
"ahriman": [
|
||||
prefix / "bin",
|
||||
prefix / "lib" / "systemd",
|
||||
prefix / "share",
|
||||
site_packages / "ahriman",
|
||||
],
|
||||
"ahriman-triggers": [
|
||||
prefix / "share" / "ahriman" / "settings" / "ahriman.ini.d" / "00-triggers.ini",
|
||||
site_packages / "ahriman" / "core" / "distributed",
|
||||
site_packages / "ahriman" / "core" / "support",
|
||||
],
|
||||
"ahriman-web": [
|
||||
prefix / "lib" / "systemd" / "system" / "ahriman-web.service",
|
||||
prefix / "lib" / "systemd" / "system" / "ahriman-web@.service",
|
||||
prefix / "share" / "ahriman" / "settings" / "ahriman.ini.d" / "00-web.ini",
|
||||
prefix / "share" / "ahriman" / "templates" / "api.jinja2",
|
||||
prefix / "share" / "ahriman" / "templates" / "build-status",
|
||||
prefix / "share" / "ahriman" / "templates" / "build-status.jinja2",
|
||||
prefix / "share" / "ahriman" / "templates" / "error.jinja2",
|
||||
site_packages / "ahriman" / "application" / "handlers" / "web.py",
|
||||
site_packages / "ahriman" / "core" / "auth",
|
||||
site_packages / "ahriman" / "web",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def subpackages(root: Path) -> dict[str, list[Path]]:
|
||||
"""
|
||||
extend list of subpackages
|
||||
|
||||
Args:
|
||||
root(Path): root directory
|
||||
|
||||
Returns:
|
||||
dict[str, list[Path]]: extended list of files which belong to a specific package
|
||||
"""
|
||||
for package, paths in SUBPACKAGES.items():
|
||||
new_paths = []
|
||||
for path in paths:
|
||||
full_path = root / path
|
||||
|
||||
match path.suffix:
|
||||
case ".py":
|
||||
pycache_path = full_path.parent / "__pycache__"
|
||||
new_paths.extend(
|
||||
new_path.relative_to(root) for new_path in pycache_path.glob(f"{full_path.stem}.*.pyc")
|
||||
)
|
||||
|
||||
SUBPACKAGES[package].extend(new_paths)
|
||||
|
||||
return SUBPACKAGES
|
||||
|
||||
|
||||
def process(root: Path, include: list[Path], exclude: list[Path]) -> None:
|
||||
"""
|
||||
remove files based on patterns
|
||||
|
||||
Args:
|
||||
root(Path): root directory
|
||||
include(list[Path]): list of files to include to the subpackage
|
||||
exclude(list[Path]): list of files to exclude from the subpackage
|
||||
"""
|
||||
for subdirectory, _, files in root.walk(top_down=False):
|
||||
for file in files:
|
||||
full_path = subdirectory / file
|
||||
relative_path = full_path.relative_to(root)
|
||||
|
||||
if not any(relative_path.is_relative_to(path) for path in include):
|
||||
full_path.unlink()
|
||||
elif any(relative_path.is_relative_to(path) for path in exclude):
|
||||
full_path.unlink()
|
||||
|
||||
content = list(subdirectory.iterdir())
|
||||
if not content:
|
||||
shutil.rmtree(subdirectory)
|
||||
|
||||
|
||||
def run() -> None:
|
||||
"""
|
||||
run application
|
||||
"""
|
||||
parser = argparse.ArgumentParser(description="Split package into subpackages")
|
||||
parser.add_argument("root", help="package root", type=Path)
|
||||
parser.add_argument("subpackage", help="subpackage name", choices=SUBPACKAGES.keys())
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
full_subpackages = subpackages(args.root)
|
||||
include = full_subpackages[args.subpackage]
|
||||
exclude = [
|
||||
path
|
||||
for subpackage, portion in full_subpackages.items()
|
||||
if subpackage != args.subpackage
|
||||
for path in portion
|
||||
if not any(include_path.is_relative_to(path) for include_path in include)
|
||||
]
|
||||
|
||||
process(args.root, include, exclude)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
@ -139,7 +139,7 @@ def test_add_remote(application_packages: ApplicationPackages, package_descripti
|
||||
|
||||
def test_add_remote_missing(application_packages: ApplicationPackages, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must add package from remote source
|
||||
must raise UnknownPackageError if remote package wasn't found
|
||||
"""
|
||||
mocker.patch("requests.get", side_effect=Exception())
|
||||
with pytest.raises(UnknownPackageError):
|
||||
|
@ -79,7 +79,7 @@ def test_clean_packages(application_repository: ApplicationRepository, mocker: M
|
||||
|
||||
def test_clean_pacman(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must clean packages directory
|
||||
must clean pacman directory
|
||||
"""
|
||||
clear_mock = mocker.patch("ahriman.core.repository.Repository.clear_pacman")
|
||||
application_repository.clean(cache=False, chroot=False, manual=False, packages=False, pacman=True)
|
||||
|
@ -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")
|
||||
@ -171,7 +171,7 @@ def test_repositories_extract_repository(args: argparse.Namespace, configuration
|
||||
def test_repositories_extract_repository_legacy(args: argparse.Namespace, configuration: Configuration,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must generate list of available repositories based on flags and tree
|
||||
must generate list of available repositories based on flags and tree (legacy mode)
|
||||
"""
|
||||
args.architecture = "arch"
|
||||
args.configuration = configuration.path
|
||||
|
@ -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)
|
||||
@ -190,7 +191,7 @@ def test_extract_packages_by_status(application: Application, mocker: MockerFixt
|
||||
|
||||
def test_extract_packages_from_database(application: Application, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must extract packages from database
|
||||
must extract packages from database from database
|
||||
"""
|
||||
packages_mock = mocker.patch("ahriman.core.database.SQLite.packages_get")
|
||||
Rebuild.extract_packages(application, None, from_database=True)
|
||||
|
@ -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
|
||||
|
||||
@ -40,7 +40,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
def test_run_eval(args: argparse.Namespace, configuration: Configuration, repository: Repository,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must run command
|
||||
must run command via eval
|
||||
"""
|
||||
args = _default_args(args)
|
||||
args.code = """print("hello world")"""
|
||||
|
@ -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
|
||||
|
@ -60,7 +60,7 @@ def test_remote_git_url(aur_package_ahriman: AURPackage) -> None:
|
||||
|
||||
def test_remote_web_url(aur_package_ahriman: AURPackage) -> None:
|
||||
"""
|
||||
must generate package git url
|
||||
must generate package web url
|
||||
"""
|
||||
web_url = AUR.remote_web_url(aur_package_ahriman.package_base)
|
||||
assert web_url.startswith(AUR.DEFAULT_AUR_URL)
|
||||
|
@ -87,7 +87,7 @@ def test_database_copy_skip(pacman: Pacman, mocker: MockerFixture) -> None:
|
||||
|
||||
def test_database_copy_no_directory(pacman: Pacman, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must do not copy database if local cache already exists
|
||||
must do not copy database if directory does not exist
|
||||
"""
|
||||
database = next(db for db in pacman.handle.get_syncdbs() if db.name == "core")
|
||||
path = Path("randomname")
|
||||
|
@ -1,4 +1,6 @@
|
||||
import configparser
|
||||
from io import StringIO
|
||||
|
||||
import pytest
|
||||
|
||||
from pathlib import Path
|
||||
@ -180,6 +182,32 @@ def test_getlist_unmatched_quote(configuration: Configuration) -> None:
|
||||
configuration.getlist("build", "test_list")
|
||||
|
||||
|
||||
def test_getlist_append() -> None:
|
||||
"""
|
||||
must correctly append list values
|
||||
"""
|
||||
configuration = Configuration()
|
||||
configuration._read(
|
||||
StringIO("""
|
||||
[section]
|
||||
list1[] = value1
|
||||
list1[] = value2
|
||||
|
||||
list2[] = value3
|
||||
list2[] =
|
||||
list2[] = value4
|
||||
list2[] = value5
|
||||
|
||||
list3[] = value6
|
||||
list3 = value7
|
||||
list3[] = value8
|
||||
"""), "io")
|
||||
|
||||
assert configuration.getlist("section", "list1") == ["value1", "value2"]
|
||||
assert configuration.getlist("section", "list2") == ["value4", "value5"]
|
||||
assert configuration.getlist("section", "list3") == ["value7", "value8"]
|
||||
|
||||
|
||||
def test_getpath_absolute_to_absolute(configuration: Configuration) -> None:
|
||||
"""
|
||||
must not change path for absolute path in settings
|
||||
|
@ -0,0 +1,54 @@
|
||||
import pytest
|
||||
|
||||
from ahriman.core.configuration.configuration_multi_dict import ConfigurationMultiDict
|
||||
from ahriman.core.exceptions import OptionError
|
||||
|
||||
|
||||
def test_setitem_non_list() -> None:
|
||||
"""
|
||||
must insert not list correctly
|
||||
"""
|
||||
instance = ConfigurationMultiDict()
|
||||
instance["key"] = "value"
|
||||
assert instance["key"] == "value"
|
||||
|
||||
|
||||
def test_setitem_remove() -> None:
|
||||
"""
|
||||
must remove key
|
||||
"""
|
||||
instance = ConfigurationMultiDict()
|
||||
instance["key"] = "value"
|
||||
instance["key"] = [""]
|
||||
|
||||
assert "key" not in instance
|
||||
|
||||
|
||||
def test_setitem_array() -> None:
|
||||
"""
|
||||
must set array correctly
|
||||
"""
|
||||
instance = ConfigurationMultiDict()
|
||||
instance["key[]"] = ["value1"]
|
||||
instance["key[]"] = ["value2"]
|
||||
|
||||
assert instance["key"] == ["value1 value2"]
|
||||
|
||||
|
||||
def test_setitem_array_exception() -> None:
|
||||
"""
|
||||
must raise exception if the current value is not a single value array
|
||||
"""
|
||||
instance = ConfigurationMultiDict()
|
||||
instance["key[]"] = ["value1", "value2"]
|
||||
with pytest.raises(OptionError):
|
||||
instance["key[]"] = ["value3"]
|
||||
|
||||
|
||||
def test_setitem_exception() -> None:
|
||||
"""
|
||||
must raise exception on invalid key
|
||||
"""
|
||||
instance = ConfigurationMultiDict()
|
||||
with pytest.raises(OptionError):
|
||||
instance["prefix[]suffix"] = "value"
|
@ -44,7 +44,7 @@ def test_patches_list_filter(database: SQLite, package_ahriman: Package, package
|
||||
def test_patches_list_filter_by_variable(database: SQLite, package_ahriman: Package,
|
||||
package_python_schedule: Package) -> None:
|
||||
"""
|
||||
must list all patches filtered by package name (same as get)
|
||||
must list all patches filtered by variable (same as get)
|
||||
"""
|
||||
database.patches_insert(package_ahriman.base, [PkgbuildPatch(None, "patch1")])
|
||||
database.patches_insert(package_ahriman.base, [PkgbuildPatch("key", "patch2")])
|
||||
|
@ -63,7 +63,7 @@ def test_in_package_context(database: SQLite, package_ahriman: Package, mocker:
|
||||
|
||||
def test_in_package_context_empty_version(database: SQLite, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must set package log context
|
||||
must set package log context with empty version
|
||||
"""
|
||||
set_mock = mocker.patch("ahriman.core.log.LazyLogging._package_logger_set")
|
||||
reset_mock = mocker.patch("ahriman.core.log.LazyLogging._package_logger_reset")
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user