Docstring update (#58)

* migrate docstrings from reST to google format

* add raises note

Also change behaviour of the `from_option` method to fallback to
disabled instead of raising exception on unknown option

* fix part of warnings for sphinx

* make identation a bit more readable

* review fixes

* add verbose description for properties to make them parsed by sphinx extenstion

* add demo sphinx generator
This commit is contained in:
Evgenii Alekseev 2022-04-17 20:25:28 +03:00 committed by GitHub
parent 06bd29b78d
commit 4daff81d5f
203 changed files with 5246 additions and 1636 deletions

View File

@ -1,4 +1,4 @@
.PHONY: architecture archive archive_directory archlinux check clean directory man push tests version .PHONY: architecture archive archive_directory archlinux check clean directory docs docs-source man push tests version
.DEFAULT_GOAL := archlinux .DEFAULT_GOAL := archlinux
PROJECT := ahriman PROJECT := ahriman
@ -32,14 +32,22 @@ check: clean
clean: clean:
find . -type f -name "$(PROJECT)-*-src.tar.xz" -delete find . -type f -name "$(PROJECT)-*-src.tar.xz" -delete
rm -rf "$(PROJECT)" rm -rf "$(PROJECT)"
find docs/source -type f -name "$(PROJECT)*.rst" -delete
rm -rf docs/html docs/source/modules.rst
directory: clean directory: clean
mkdir "$(PROJECT)" mkdir "$(PROJECT)"
docs: docs-source
sphinx-build -b html -a -j auto docs/source docs/html
docs-source: clean
SPHINX_APIDOC_OPTIONS=members,no-undoc-members,show-inheritance sphinx-apidoc --force --private -o docs/source src
man: man:
cd src && PYTHONPATH=. argparse-manpage --module ahriman.application.ahriman --function _parser --author "ahriman team" --project-name ahriman --author-email "" --url https://github.com/arcan1s/ahriman --output ../docs/ahriman.1 cd src && PYTHONPATH=. argparse-manpage --module ahriman.application.ahriman --function _parser --author "ahriman team" --project-name ahriman --author-email "" --url https://github.com/arcan1s/ahriman --output ../docs/ahriman.1
push: architecture man archlinux push: architecture docs-source man archlinux
git add package/archlinux/PKGBUILD src/ahriman/version.py docs/ahriman-architecture.svg docs/ahriman.1 git add package/archlinux/PKGBUILD src/ahriman/version.py docs/ahriman-architecture.svg docs/ahriman.1
git commit -m "Release $(VERSION)" git commit -m "Release $(VERSION)"
git tag "$(VERSION)" git tag "$(VERSION)"

View File

@ -0,0 +1,50 @@
ahriman.application.application package
=======================================
Submodules
----------
ahriman.application.application.application module
--------------------------------------------------
.. automodule:: ahriman.application.application.application
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.application.packages module
-----------------------------------------------
.. automodule:: ahriman.application.application.packages
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.application.properties module
-------------------------------------------------
.. automodule:: ahriman.application.application.properties
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.application.repository module
-------------------------------------------------
.. automodule:: ahriman.application.application.repository
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.application.application
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,221 @@
ahriman.application.handlers package
====================================
Submodules
----------
ahriman.application.handlers.add module
---------------------------------------
.. automodule:: ahriman.application.handlers.add
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.backup module
------------------------------------------
.. automodule:: ahriman.application.handlers.backup
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.clean module
-----------------------------------------
.. automodule:: ahriman.application.handlers.clean
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.dump module
----------------------------------------
.. automodule:: ahriman.application.handlers.dump
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.handler module
-------------------------------------------
.. automodule:: ahriman.application.handlers.handler
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.help module
----------------------------------------
.. automodule:: ahriman.application.handlers.help
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.key\_import module
-----------------------------------------------
.. automodule:: ahriman.application.handlers.key_import
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.patch module
-----------------------------------------
.. automodule:: ahriman.application.handlers.patch
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.rebuild module
-------------------------------------------
.. automodule:: ahriman.application.handlers.rebuild
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.remove module
------------------------------------------
.. automodule:: ahriman.application.handlers.remove
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.remove\_unknown module
---------------------------------------------------
.. automodule:: ahriman.application.handlers.remove_unknown
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.report module
------------------------------------------
.. automodule:: ahriman.application.handlers.report
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.restore module
-------------------------------------------
.. automodule:: ahriman.application.handlers.restore
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.search module
------------------------------------------
.. automodule:: ahriman.application.handlers.search
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.setup module
-----------------------------------------
.. automodule:: ahriman.application.handlers.setup
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.sign module
----------------------------------------
.. automodule:: ahriman.application.handlers.sign
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.status module
------------------------------------------
.. automodule:: ahriman.application.handlers.status
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.status\_update module
--------------------------------------------------
.. automodule:: ahriman.application.handlers.status_update
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.sync module
----------------------------------------
.. automodule:: ahriman.application.handlers.sync
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.unsafe\_commands module
----------------------------------------------------
.. automodule:: ahriman.application.handlers.unsafe_commands
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.update module
------------------------------------------
.. automodule:: ahriman.application.handlers.update
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.user module
----------------------------------------
.. automodule:: ahriman.application.handlers.user
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.handlers.web module
---------------------------------------
.. automodule:: ahriman.application.handlers.web
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.application.handlers
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,41 @@
ahriman.application package
===========================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.application.application
ahriman.application.handlers
Submodules
----------
ahriman.application.ahriman module
----------------------------------
.. automodule:: ahriman.application.ahriman
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.application.lock module
-------------------------------
.. automodule:: ahriman.application.lock
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.application
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,41 @@
ahriman.core.alpm.remote package
================================
Submodules
----------
ahriman.core.alpm.remote.aur module
-----------------------------------
.. automodule:: ahriman.core.alpm.remote.aur
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.alpm.remote.official module
----------------------------------------
.. automodule:: ahriman.core.alpm.remote.official
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.alpm.remote.remote module
--------------------------------------
.. automodule:: ahriman.core.alpm.remote.remote
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.alpm.remote
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,40 @@
ahriman.core.alpm package
=========================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.core.alpm.remote
Submodules
----------
ahriman.core.alpm.pacman module
-------------------------------
.. automodule:: ahriman.core.alpm.pacman
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.alpm.repo module
-----------------------------
.. automodule:: ahriman.core.alpm.repo
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.alpm
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,50 @@
ahriman.core.auth package
=========================
Submodules
----------
ahriman.core.auth.auth module
-----------------------------
.. automodule:: ahriman.core.auth.auth
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.auth.helpers module
--------------------------------
.. automodule:: ahriman.core.auth.helpers
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.auth.mapping module
--------------------------------
.. automodule:: ahriman.core.auth.mapping
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.auth.oauth module
------------------------------
.. automodule:: ahriman.core.auth.oauth
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.auth
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,32 @@
ahriman.core.build\_tools package
=================================
Submodules
----------
ahriman.core.build\_tools.sources module
----------------------------------------
.. automodule:: ahriman.core.build_tools.sources
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.build\_tools.task module
-------------------------------------
.. automodule:: ahriman.core.build_tools.task
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.build_tools
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,41 @@
ahriman.core.database.data package
==================================
Submodules
----------
ahriman.core.database.data.package\_statuses module
---------------------------------------------------
.. automodule:: ahriman.core.database.data.package_statuses
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.database.data.patches module
-----------------------------------------
.. automodule:: ahriman.core.database.data.patches
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.database.data.users module
---------------------------------------
.. automodule:: ahriman.core.database.data.users
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.database.data
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,23 @@
ahriman.core.database.migrations package
========================================
Submodules
----------
ahriman.core.database.migrations.m000\_initial module
-----------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m000_initial
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.database.migrations
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,59 @@
ahriman.core.database.operations package
========================================
Submodules
----------
ahriman.core.database.operations.auth\_operations module
--------------------------------------------------------
.. automodule:: ahriman.core.database.operations.auth_operations
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.database.operations.build\_operations module
---------------------------------------------------------
.. automodule:: ahriman.core.database.operations.build_operations
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.database.operations.operations module
--------------------------------------------------
.. automodule:: ahriman.core.database.operations.operations
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.database.operations.package\_operations module
-----------------------------------------------------------
.. automodule:: ahriman.core.database.operations.package_operations
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.database.operations.patch\_operations module
---------------------------------------------------------
.. automodule:: ahriman.core.database.operations.patch_operations
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.database.operations
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,33 @@
ahriman.core.database package
=============================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.core.database.data
ahriman.core.database.migrations
ahriman.core.database.operations
Submodules
----------
ahriman.core.database.sqlite module
-----------------------------------
.. automodule:: ahriman.core.database.sqlite
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.database
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,95 @@
ahriman.core.formatters package
===============================
Submodules
----------
ahriman.core.formatters.aur\_printer module
-------------------------------------------
.. automodule:: ahriman.core.formatters.aur_printer
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.formatters.build\_printer module
---------------------------------------------
.. automodule:: ahriman.core.formatters.build_printer
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.formatters.configuration\_printer module
-----------------------------------------------------
.. automodule:: ahriman.core.formatters.configuration_printer
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.formatters.package\_printer module
-----------------------------------------------
.. automodule:: ahriman.core.formatters.package_printer
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.formatters.printer module
--------------------------------------
.. automodule:: ahriman.core.formatters.printer
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.formatters.status\_printer module
----------------------------------------------
.. automodule:: ahriman.core.formatters.status_printer
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.formatters.string\_printer module
----------------------------------------------
.. automodule:: ahriman.core.formatters.string_printer
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.formatters.update\_printer module
----------------------------------------------
.. automodule:: ahriman.core.formatters.update_printer
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.formatters.user\_printer module
--------------------------------------------
.. automodule:: ahriman.core.formatters.user_printer
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.formatters
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,68 @@
ahriman.core.report package
===========================
Submodules
----------
ahriman.core.report.console module
----------------------------------
.. automodule:: ahriman.core.report.console
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.report.email module
--------------------------------
.. automodule:: ahriman.core.report.email
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.report.html module
-------------------------------
.. automodule:: ahriman.core.report.html
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.report.jinja\_template module
------------------------------------------
.. automodule:: ahriman.core.report.jinja_template
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.report.report module
---------------------------------
.. automodule:: ahriman.core.report.report
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.report.telegram module
-----------------------------------
.. automodule:: ahriman.core.report.telegram
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.report
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,59 @@
ahriman.core.repository package
===============================
Submodules
----------
ahriman.core.repository.cleaner module
--------------------------------------
.. automodule:: ahriman.core.repository.cleaner
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.repository.executor module
---------------------------------------
.. automodule:: ahriman.core.repository.executor
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.repository.properties module
-----------------------------------------
.. automodule:: ahriman.core.repository.properties
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.repository.repository module
-----------------------------------------
.. automodule:: ahriman.core.repository.repository
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.repository.update\_handler module
----------------------------------------------
.. automodule:: ahriman.core.repository.update_handler
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.repository
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,76 @@
ahriman.core package
====================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.core.alpm
ahriman.core.auth
ahriman.core.build_tools
ahriman.core.database
ahriman.core.formatters
ahriman.core.report
ahriman.core.repository
ahriman.core.sign
ahriman.core.status
ahriman.core.upload
Submodules
----------
ahriman.core.configuration module
---------------------------------
.. automodule:: ahriman.core.configuration
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.exceptions module
------------------------------
.. automodule:: ahriman.core.exceptions
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.spawn module
-------------------------
.. automodule:: ahriman.core.spawn
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.tree module
------------------------
.. automodule:: ahriman.core.tree
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.util module
------------------------
.. automodule:: ahriman.core.util
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,23 @@
ahriman.core.sign package
=========================
Submodules
----------
ahriman.core.sign.gpg module
----------------------------
.. automodule:: ahriman.core.sign.gpg
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.sign
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,41 @@
ahriman.core.status package
===========================
Submodules
----------
ahriman.core.status.client module
---------------------------------
.. automodule:: ahriman.core.status.client
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.status.watcher module
----------------------------------
.. automodule:: ahriman.core.status.watcher
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.status.web\_client module
--------------------------------------
.. automodule:: ahriman.core.status.web_client
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.status
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,59 @@
ahriman.core.upload package
===========================
Submodules
----------
ahriman.core.upload.github module
---------------------------------
.. automodule:: ahriman.core.upload.github
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.upload.http\_upload module
---------------------------------------
.. automodule:: ahriman.core.upload.http_upload
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.upload.rsync module
--------------------------------
.. automodule:: ahriman.core.upload.rsync
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.upload.s3 module
-----------------------------
.. automodule:: ahriman.core.upload.s3
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.core.upload.upload module
---------------------------------
.. automodule:: ahriman.core.upload.upload
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.core.upload
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,203 @@
ahriman.models package
======================
Submodules
----------
ahriman.models.action module
----------------------------
.. automodule:: ahriman.models.action
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.aur\_package module
----------------------------------
.. automodule:: ahriman.models.aur_package
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.auth\_settings module
------------------------------------
.. automodule:: ahriman.models.auth_settings
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.build\_status module
-----------------------------------
.. automodule:: ahriman.models.build_status
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.counters module
------------------------------
.. automodule:: ahriman.models.counters
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.internal\_status module
--------------------------------------
.. automodule:: ahriman.models.internal_status
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.migration module
-------------------------------
.. automodule:: ahriman.models.migration
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.migration\_result module
---------------------------------------
.. automodule:: ahriman.models.migration_result
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.package module
-----------------------------
.. automodule:: ahriman.models.package
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.package\_description module
------------------------------------------
.. automodule:: ahriman.models.package_description
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.package\_source module
-------------------------------------
.. automodule:: ahriman.models.package_source
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.property module
------------------------------
.. automodule:: ahriman.models.property
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.report\_settings module
--------------------------------------
.. automodule:: ahriman.models.report_settings
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.repository\_paths module
---------------------------------------
.. automodule:: ahriman.models.repository_paths
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.result module
----------------------------
.. automodule:: ahriman.models.result
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.sign\_settings module
------------------------------------
.. automodule:: ahriman.models.sign_settings
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.smtp\_ssl\_settings module
-----------------------------------------
.. automodule:: ahriman.models.smtp_ssl_settings
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.upload\_settings module
--------------------------------------
.. automodule:: ahriman.models.upload_settings
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.user module
--------------------------
.. automodule:: ahriman.models.user
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.user\_access module
----------------------------------
.. automodule:: ahriman.models.user_access
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.models.user\_identity module
------------------------------------
.. automodule:: ahriman.models.user_identity
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.models
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

34
docs/source/ahriman.rst Normal file
View File

@ -0,0 +1,34 @@
ahriman package
===============
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.application
ahriman.core
ahriman.models
ahriman.web
Submodules
----------
ahriman.version module
----------------------
.. automodule:: ahriman.version
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,32 @@
ahriman.web.middlewares package
===============================
Submodules
----------
ahriman.web.middlewares.auth\_handler module
--------------------------------------------
.. automodule:: ahriman.web.middlewares.auth_handler
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.web.middlewares.exception\_handler module
-------------------------------------------------
.. automodule:: ahriman.web.middlewares.exception_handler
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.web.middlewares
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,41 @@
ahriman.web package
===================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.web.middlewares
ahriman.web.views
Submodules
----------
ahriman.web.routes module
-------------------------
.. automodule:: ahriman.web.routes
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.web.web module
----------------------
.. automodule:: ahriman.web.web
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.web
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,42 @@
ahriman.web.views package
=========================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.web.views.service
ahriman.web.views.status
ahriman.web.views.user
Submodules
----------
ahriman.web.views.base module
-----------------------------
.. automodule:: ahriman.web.views.base
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.web.views.index module
------------------------------
.. automodule:: ahriman.web.views.index
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.web.views
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,50 @@
ahriman.web.views.service package
=================================
Submodules
----------
ahriman.web.views.service.add module
------------------------------------
.. automodule:: ahriman.web.views.service.add
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.web.views.service.remove module
---------------------------------------
.. automodule:: ahriman.web.views.service.remove
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.web.views.service.request module
----------------------------------------
.. automodule:: ahriman.web.views.service.request
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.web.views.service.search module
---------------------------------------
.. automodule:: ahriman.web.views.service.search
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.web.views.service
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,50 @@
ahriman.web.views.status package
================================
Submodules
----------
ahriman.web.views.status.ahriman module
---------------------------------------
.. automodule:: ahriman.web.views.status.ahriman
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.web.views.status.package module
---------------------------------------
.. automodule:: ahriman.web.views.status.package
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.web.views.status.packages module
----------------------------------------
.. automodule:: ahriman.web.views.status.packages
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.web.views.status.status module
--------------------------------------
.. automodule:: ahriman.web.views.status.status
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.web.views.status
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

View File

@ -0,0 +1,32 @@
ahriman.web.views.user package
==============================
Submodules
----------
ahriman.web.views.user.login module
-----------------------------------
.. automodule:: ahriman.web.views.user.login
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
ahriman.web.views.user.logout module
------------------------------------
.. automodule:: ahriman.web.views.user.logout
:members:
:no-undoc-members:
:show-inheritance:
:private-members:
Module contents
---------------
.. automodule:: ahriman.web.views.user
:members:
:no-undoc-members:
:show-inheritance:
:private-members:

73
docs/source/conf.py Normal file
View File

@ -0,0 +1,73 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath("."))
# -- Project information -----------------------------------------------------
project = "ahriman"
copyright = "2022, ahriman team"
author = "ahriman team"
# The full version, including alpha/beta/rc tags
release = "2021-2022"
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named "sphinx.ext.*") or your custom
# ones.
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = "en"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "alabaster"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
# -- Extension configuration -------------------------------------------------
autodoc_member_order = "groupwise"
autodoc_default_options = {
"no-undoc-members": True,
}

20
docs/source/index.rst Normal file
View File

@ -0,0 +1,20 @@
.. ahriman documentation master file, created by
sphinx-quickstart on Sun Apr 17 18:05:36 2022.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to ahriman's documentation!
===================================
.. toctree::
:maxdepth: 2
:caption: Contents:
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

7
docs/source/modules.rst Normal file
View File

@ -0,0 +1,7 @@
src
===
.. toctree::
:maxdepth: 4
ahriman

View File

@ -43,8 +43,12 @@ SubParserAction = TypeVar("SubParserAction", bound="argparse._SubParsersAction[a
def _formatter(prog: str) -> argparse.HelpFormatter: def _formatter(prog: str) -> argparse.HelpFormatter:
""" """
formatter for the help message formatter for the help message
:param prog: application name
:return: formatter used by default Args:
prog(str): application name
Returns:
argparse.HelpFormatter: formatter used by default
""" """
return argparse.ArgumentDefaultsHelpFormatter(prog, width=120) return argparse.ArgumentDefaultsHelpFormatter(prog, width=120)
@ -52,7 +56,9 @@ def _formatter(prog: str) -> argparse.HelpFormatter:
def _parser() -> argparse.ArgumentParser: def _parser() -> argparse.ArgumentParser:
""" """
command line parser generator command line parser generator
:return: command line parser for the application
Returns:
argparse.ArgumentParser: command line parser for the application
""" """
parser = argparse.ArgumentParser(prog="ahriman", description="ArcH Linux ReposItory MANager", parser = argparse.ArgumentParser(prog="ahriman", description="ArcH Linux ReposItory MANager",
epilog="Argument list can also be read from file by using @ prefix.", epilog="Argument list can also be read from file by using @ prefix.",
@ -107,8 +113,12 @@ def _parser() -> argparse.ArgumentParser:
def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for AUR search subcommand add parser for AUR search subcommand
:param root: subparsers for the commands
:return: created argument parser 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", parser = root.add_parser("aur-search", aliases=["search"], help="search for package",
description="search for package in AUR using API", formatter_class=_formatter) description="search for package in AUR using API", formatter_class=_formatter)
@ -126,8 +136,12 @@ def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for listing help subcommand add parser for listing help subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("help", help="show help message", parser = root.add_parser("help", help="show help message",
description="show help message for application or command and exit", description="show help message for application or command and exit",
@ -141,8 +155,12 @@ def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for listing unsafe commands add parser for listing unsafe commands
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("help-commands-unsafe", help="list unsafe commands", parser = root.add_parser("help-commands-unsafe", help="list unsafe commands",
description="list unsafe commands as defined in default args", formatter_class=_formatter) description="list unsafe commands as defined in default args", formatter_class=_formatter)
@ -156,8 +174,12 @@ def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.Argument
def _set_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for key import subcommand add parser for key import subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("key-import", help="import PGP key", parser = root.add_parser("key-import", help="import PGP key",
description="import PGP key from public sources to the repository user", description="import PGP key from public sources to the repository user",
@ -175,8 +197,12 @@ def _set_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_package_add_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_package_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for package addition subcommand add parser for package addition subcommand
:param root: subparsers for the commands
:return: created argument parser 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", parser = root.add_parser("package-add", aliases=["add", "package-update"], help="add package",
description="add existing or new package to the build queue", description="add existing or new package to the build queue",
@ -204,8 +230,12 @@ def _set_package_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_package_remove_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_package_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for package removal subcommand add parser for package removal subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("package-remove", aliases=["remove"], help="remove package", parser = root.add_parser("package-remove", aliases=["remove"], help="remove package",
description="remove package from the repository", formatter_class=_formatter) description="remove package from the repository", formatter_class=_formatter)
@ -217,8 +247,12 @@ def _set_package_remove_parser(root: SubParserAction) -> argparse.ArgumentParser
def _set_package_status_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_package_status_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for package status subcommand add parser for package status subcommand
:param root: subparsers for the commands
:return: created argument parser 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", parser = root.add_parser("package-status", aliases=["status"], help="get package status",
description="request status of the package", description="request status of the package",
@ -237,8 +271,12 @@ def _set_package_status_parser(root: SubParserAction) -> argparse.ArgumentParser
def _set_package_status_remove_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_package_status_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for package status remove subcommand add parser for package status remove subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("package-status-remove", help="remove package status", parser = root.add_parser("package-status-remove", help="remove package status",
description="remove the package from the status page", description="remove the package from the status page",
@ -254,8 +292,12 @@ def _set_package_status_remove_parser(root: SubParserAction) -> argparse.Argumen
def _set_package_status_update_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_package_status_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for package status update subcommand add parser for package status update subcommand
:param root: subparsers for the commands
:return: created argument parser 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", parser = root.add_parser("package-status-update", aliases=["status-update"], help="update package status",
description="update package status on the status page", formatter_class=_formatter) description="update package status on the status page", formatter_class=_formatter)
@ -272,8 +314,12 @@ def _set_package_status_update_parser(root: SubParserAction) -> argparse.Argumen
def _set_patch_add_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_patch_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for new patch subcommand add parser for new patch subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("patch-add", help="add patch set", description="create or update source patches", parser = root.add_parser("patch-add", help="add patch set", description="create or update source patches",
epilog="In order to add a patch set for the package you will need to clone " epilog="In order to add a patch set for the package you will need to clone "
@ -292,8 +338,12 @@ def _set_patch_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_patch_list_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_patch_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for list patches subcommand add parser for list patches subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("patch-list", help="list patch sets", parser = root.add_parser("patch-list", help="list patch sets",
description="list available patches for the package", formatter_class=_formatter) description="list available patches for the package", formatter_class=_formatter)
@ -306,8 +356,12 @@ def _set_patch_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_patch_remove_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_patch_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for remove patches subcommand add parser for remove patches subcommand
:param root: subparsers for the commands
:return: created argument parser 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 = root.add_parser("patch-remove", help="remove patch set", description="remove patches for the package",
formatter_class=_formatter) formatter_class=_formatter)
@ -319,8 +373,12 @@ def _set_patch_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_backup_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_backup_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for repository backup subcommand add parser for repository backup subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-backup", help="backup repository data", parser = root.add_parser("repo-backup", help="backup repository data",
description="backup settings and database", formatter_class=_formatter) description="backup settings and database", formatter_class=_formatter)
@ -332,8 +390,12 @@ def _set_repo_backup_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_check_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_check_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for repository check subcommand add parser for repository check subcommand
:param root: subparsers for the commands
:return: created argument parser 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", parser = root.add_parser("repo-check", aliases=["check"], help="check for updates",
description="check for packages updates. Same as update --dry-run --no-manual", description="check for packages updates. Same as update --dry-run --no-manual",
@ -348,8 +410,12 @@ def _set_repo_check_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_clean_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_clean_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for repository clean subcommand add parser for repository clean subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-clean", aliases=["clean"], help="clean local caches", parser = root.add_parser("repo-clean", aliases=["clean"], help="clean local caches",
description="remove local caches", description="remove local caches",
@ -368,8 +434,12 @@ def _set_repo_clean_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_config_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_config_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for config subcommand add parser for config subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-config", aliases=["config"], help="dump configuration", parser = root.add_parser("repo-config", aliases=["config"], help="dump configuration",
description="dump configuration for the specified architecture", description="dump configuration for the specified architecture",
@ -381,8 +451,12 @@ def _set_repo_config_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_rebuild_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_rebuild_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for repository rebuild subcommand add parser for repository rebuild subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-rebuild", aliases=["rebuild"], help="rebuild repository", parser = root.add_parser("repo-rebuild", aliases=["rebuild"], help="rebuild repository",
description="force rebuild whole repository", formatter_class=_formatter) description="force rebuild whole repository", formatter_class=_formatter)
@ -403,8 +477,12 @@ def _set_repo_rebuild_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_remove_unknown_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_remove_unknown_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for remove unknown packages subcommand add parser for remove unknown packages subcommand
:param root: subparsers for the commands
:return: created argument parser 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", parser = root.add_parser("repo-remove-unknown", aliases=["remove-unknown"], help="remove unknown packages",
description="remove packages which are missing in AUR and do not have local PKGBUILDs", description="remove packages which are missing in AUR and do not have local PKGBUILDs",
@ -418,8 +496,12 @@ def _set_repo_remove_unknown_parser(root: SubParserAction) -> argparse.ArgumentP
def _set_repo_report_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_report_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for report subcommand add parser for report subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-report", aliases=["report"], help="generate report", parser = root.add_parser("repo-report", aliases=["report"], help="generate report",
description="generate repository report according to current settings", description="generate repository report according to current settings",
@ -433,8 +515,12 @@ def _set_repo_report_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for repository restore subcommand add parser for repository restore subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-restore", help="restore repository data", parser = root.add_parser("repo-restore", help="restore repository data",
description="restore settings and database", formatter_class=_formatter) description="restore settings and database", formatter_class=_formatter)
@ -447,8 +533,12 @@ def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_setup_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for setup subcommand add parser for setup subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-setup", aliases=["init", "repo-init", "setup"], help="initial service configuration", parser = root.add_parser("repo-setup", aliases=["init", "repo-init", "setup"], help="initial service configuration",
description="create initial service configuration, requires root", description="create initial service configuration, requires root",
@ -472,8 +562,12 @@ def _set_repo_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_sign_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_sign_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for sign subcommand add parser for sign subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-sign", aliases=["sign"], help="sign packages", parser = root.add_parser("repo-sign", aliases=["sign"], help="sign packages",
description="(re-)sign packages and repository database according to current settings", description="(re-)sign packages and repository database according to current settings",
@ -487,8 +581,12 @@ def _set_repo_sign_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_status_update_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_status_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for repository status update subcommand add parser for repository status update subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-status-update", help="update repository status", parser = root.add_parser("repo-status-update", help="update repository status",
description="update repository status on the status page", formatter_class=_formatter) description="update repository status on the status page", formatter_class=_formatter)
@ -502,8 +600,12 @@ def _set_repo_status_update_parser(root: SubParserAction) -> argparse.ArgumentPa
def _set_repo_sync_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_sync_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for repository sync subcommand add parser for repository sync subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-sync", aliases=["sync"], help="sync repository", parser = root.add_parser("repo-sync", aliases=["sync"], help="sync repository",
description="sync repository files to remote server according to current settings", description="sync repository files to remote server according to current settings",
@ -517,8 +619,12 @@ def _set_repo_sync_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_repo_update_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for repository update subcommand add parser for repository update subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("repo-update", aliases=["update"], help="update packages", parser = root.add_parser("repo-update", aliases=["update"], help="update packages",
description="check for packages updates and run build process if requested", description="check for packages updates and run build process if requested",
@ -537,8 +643,12 @@ def _set_repo_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for create user subcommand add parser for create user subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("user-add", help="create or update user", parser = root.add_parser("user-add", help="create or update user",
description="update user for web services with the given password and role. " description="update user for web services with the given password and role. "
@ -559,8 +669,12 @@ def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for user list subcommand add parser for user list subcommand
:param root: subparsers for the commands
:return: created argument parser 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", parser = root.add_parser("user-list", help="user known users and their access",
description="list users from the user mapping and their roles", description="list users from the user mapping and their roles",
@ -576,8 +690,12 @@ def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for user removal subcommand add parser for user removal subcommand
:param root: subparsers for the commands
:return: created argument parser Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
""" """
parser = root.add_parser("user-remove", help="remove user", parser = root.add_parser("user-remove", help="remove user",
description="remove user from the user mapping and update the configuration", description="remove user from the user mapping and update the configuration",
@ -592,8 +710,12 @@ def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
def _set_web_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_web_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for web subcommand add parser for web subcommand
:param root: subparsers for the commands
:return: created argument parser 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", formatter_class=_formatter) parser = root.add_parser("web", help="web server", description="start web server", formatter_class=_formatter)
parser.set_defaults(handler=handlers.Web, lock=None, no_report=True, parser=_parser) parser.set_defaults(handler=handlers.Web, lock=None, no_report=True, parser=_parser)

View File

@ -32,7 +32,9 @@ class Application(Packages, Repository):
def _finalize(self, result: Result) -> None: def _finalize(self, result: Result) -> None:
""" """
generate report and sync to remote server generate report and sync to remote server
:param result: build result
Args:
result(Result): build result
""" """
self.report([], result) self.report([], result)
self.sync([], result.success) self.sync([], result.success)
@ -40,7 +42,9 @@ class Application(Packages, Repository):
def _known_packages(self) -> Set[str]: def _known_packages(self) -> Set[str]:
""" """
load packages from repository and pacman repositories load packages from repository and pacman repositories
:return: list of known packages
Returns:
Set[str]: list of known packages
""" """
known_packages: Set[str] = set() known_packages: Set[str] = set()
# local set # local set

View File

@ -39,21 +39,33 @@ class Packages(Properties):
def _finalize(self, result: Result) -> None: def _finalize(self, result: Result) -> None:
""" """
generate report and sync to remote server generate report and sync to remote server
:param result: build result
Args:
result(Result): build result
Raises:
NotImplementedError: not implemented method
""" """
raise NotImplementedError raise NotImplementedError
def _known_packages(self) -> Set[str]: def _known_packages(self) -> Set[str]:
""" """
load packages from repository and pacman repositories load packages from repository and pacman repositories
:return: list of known packages
Returns:
Set[str]: list of known packages
Raises:
NotImplementedError: not implemented method
""" """
raise NotImplementedError raise NotImplementedError
def _add_archive(self, source: str, *_: Any) -> None: def _add_archive(self, source: str, *_: Any) -> None:
""" """
add package from archive add package from archive
:param source: path to package archive
Args:
source(str): path to package archive
""" """
local_path = Path(source) local_path = Path(source)
dst = self.repository.paths.packages / local_path.name dst = self.repository.paths.packages / local_path.name
@ -62,9 +74,11 @@ class Packages(Properties):
def _add_aur(self, source: str, known_packages: Set[str], without_dependencies: bool) -> None: def _add_aur(self, source: str, known_packages: Set[str], without_dependencies: bool) -> None:
""" """
add package from AUR add package from AUR
:param source: package base name
:param known_packages: list of packages which are known by the service Args:
:param without_dependencies: if set, dependency check will be disabled source(str): package base name
known_packages(Set[str]): list of packages which are known by the service
without_dependencies(bool): if set, dependency check will be disabled
""" """
package = Package.load(source, PackageSource.AUR, self.repository.pacman, self.repository.aur_url) package = Package.load(source, PackageSource.AUR, self.repository.pacman, self.repository.aur_url)
@ -77,7 +91,9 @@ class Packages(Properties):
def _add_directory(self, source: str, *_: Any) -> None: def _add_directory(self, source: str, *_: Any) -> None:
""" """
add packages from directory add packages from directory
:param source: path to local directory
Args:
source(str): path to local directory
""" """
local_path = Path(source) local_path = Path(source)
for full_path in filter(package_like, local_path.iterdir()): for full_path in filter(package_like, local_path.iterdir()):
@ -86,9 +102,11 @@ class Packages(Properties):
def _add_local(self, source: str, known_packages: Set[str], without_dependencies: bool) -> None: def _add_local(self, source: str, known_packages: Set[str], without_dependencies: bool) -> None:
""" """
add package from local PKGBUILDs add package from local PKGBUILDs
:param source: path to directory with local source files
:param known_packages: list of packages which are known by the service Args:
:param without_dependencies: if set, dependency check will be disabled source(str): path to directory with local source files
known_packages(Set[str]): list of packages which are known by the service
without_dependencies(bool): if set, dependency check will be disabled
""" """
package = Package.load(source, PackageSource.Local, self.repository.pacman, self.repository.aur_url) package = Package.load(source, PackageSource.Local, self.repository.pacman, self.repository.aur_url)
cache_dir = self.repository.paths.cache_for(package.base) cache_dir = self.repository.paths.cache_for(package.base)
@ -102,7 +120,9 @@ class Packages(Properties):
def _add_remote(self, source: str, *_: Any) -> None: def _add_remote(self, source: str, *_: Any) -> None:
""" """
add package from remote sources (e.g. HTTP) add package from remote sources (e.g. HTTP)
:param remote_url: remote URL to the package archive
Args:
source(str): remote URL of the package archive
""" """
dst = self.repository.paths.packages / Path(source).name # URL is path, is not it? dst = self.repository.paths.packages / Path(source).name # URL is path, is not it?
response = requests.get(source, stream=True) response = requests.get(source, stream=True)
@ -115,9 +135,11 @@ class Packages(Properties):
def _process_dependencies(self, local_path: Path, known_packages: Set[str], without_dependencies: bool) -> None: def _process_dependencies(self, local_path: Path, known_packages: Set[str], without_dependencies: bool) -> None:
""" """
process package dependencies process package dependencies
:param local_path: path to local package sources (i.e. cloned AUR repository)
:param known_packages: list of packages which are known by the service Args:
:param without_dependencies: if set, dependency check will be disabled local_path(Path): path to local package sources (i.e. cloned AUR repository)
known_packages(Set[str]): list of packages which are known by the service
without_dependencies(bool): if set, dependency check will be disabled
""" """
if without_dependencies: if without_dependencies:
return return
@ -128,9 +150,11 @@ class Packages(Properties):
def add(self, names: Iterable[str], source: PackageSource, without_dependencies: bool) -> None: def add(self, names: Iterable[str], source: PackageSource, without_dependencies: bool) -> None:
""" """
add packages for the next build add packages for the next build
:param names: list of package bases to add
:param source: package source to add Args:
:param without_dependencies: if set, dependency check will be disabled names(Iterable[str]): list of package bases to add
source(PackageSource): package source to add
without_dependencies(bool): if set, dependency check will be disabled
""" """
known_packages = self._known_packages() # speedup dependencies processing known_packages = self._known_packages() # speedup dependencies processing
@ -142,7 +166,9 @@ class Packages(Properties):
def remove(self, names: Iterable[str]) -> None: def remove(self, names: Iterable[str]) -> None:
""" """
remove packages from repository remove packages from repository
:param names: list of packages (either base or name) to remove
Args:
names(Iterable[str]): list of packages (either base or name) to remove
""" """
self.repository.process_remove(names) self.repository.process_remove(names)
self._finalize(Result()) self._finalize(Result())

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,8 +34,10 @@ from ahriman.models.repository_paths import RepositoryPaths
class Handler: class Handler:
""" """
base handler class for command callbacks base handler class for command callbacks
:cvar ALLOW_AUTO_ARCHITECTURE_RUN: allow to define architecture from existing repositories
:cvar ALLOW_MULTI_ARCHITECTURE_RUN: allow to run with multiple architectures Attributes:
ALLOW_AUTO_ARCHITECTURE_RUN(bool): (class attribute) allow defining architecture from existing repositories
ALLOW_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
""" """
ALLOW_AUTO_ARCHITECTURE_RUN = True ALLOW_AUTO_ARCHITECTURE_RUN = True
@ -45,8 +47,15 @@ class Handler:
def architectures_extract(cls: Type[Handler], args: argparse.Namespace) -> List[str]: def architectures_extract(cls: Type[Handler], args: argparse.Namespace) -> List[str]:
""" """
get known architectures get known architectures
:param args: command line args
:return: list of architectures for which tree is created Args:
args(argparse.Namespace): command line args
Returns:
List[str]: list of architectures for which tree is created
Raises:
MissingArchitecture: if no architecture set and automatic detection is not allowed or failed
""" """
if not cls.ALLOW_AUTO_ARCHITECTURE_RUN and args.architecture is None: if not cls.ALLOW_AUTO_ARCHITECTURE_RUN and args.architecture is None:
# for some parsers (e.g. config) we need to run with specific architecture # for some parsers (e.g. config) we need to run with specific architecture
@ -69,9 +78,13 @@ class Handler:
def call(cls: Type[Handler], args: argparse.Namespace, architecture: str) -> bool: def call(cls: Type[Handler], args: argparse.Namespace, architecture: str) -> bool:
""" """
additional function to wrap all calls for multiprocessing library additional function to wrap all calls for multiprocessing library
:param args: command line args
:param architecture: repository architecture Args:
:return: True on success, False otherwise args(argparse.Namespace): command line args
architecture(str): repository architecture
Returns:
bool: True on success, False otherwise
""" """
try: try:
configuration = Configuration.from_path(args.configuration, architecture, args.quiet) configuration = Configuration.from_path(args.configuration, architecture, args.quiet)
@ -89,8 +102,15 @@ class Handler:
def execute(cls: Type[Handler], args: argparse.Namespace) -> int: def execute(cls: Type[Handler], args: argparse.Namespace) -> int:
""" """
execute function for all aru execute function for all aru
:param args: command line args
:return: 0 on success, 1 otherwise Args:
args(argparse.Namespace): command line args
Returns:
int: 0 on success, 1 otherwise
Raises:
MultipleArchitectures: if more than one architecture supplied and no multi architecture supported
""" """
architectures = cls.architectures_extract(args) architectures = cls.architectures_extract(args)
@ -112,11 +132,16 @@ class Handler:
configuration: Configuration, no_report: bool, unsafe: bool) -> None: configuration: Configuration, no_report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
:param args: command line args
:param architecture: repository architecture Args:
:param configuration: configuration instance args(argparse.Namespace): command line args
:param no_report: force disable reporting architecture(str): repository architecture
:param unsafe: if set no user check will be performed before path creation configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
Raises:
NotImplementedError: not implemented method
""" """
raise NotImplementedError raise NotImplementedError
@ -124,8 +149,13 @@ class Handler:
def check_if_empty(enabled: bool, predicate: bool) -> None: def check_if_empty(enabled: bool, predicate: bool) -> None:
""" """
check condition and flag and raise ExitCode exception in case if it is enabled and condition match check condition and flag and raise ExitCode exception in case if it is enabled and condition match
:param enabled: if False no check will be performed
:param predicate: indicates condition on which exception should be thrown Args:
enabled(bool): if False no check will be performed
predicate(bool): indicates condition on which exception should be thrown
Raises:
ExitCode: if result is empty and check is enabled
""" """
if enabled and predicate: if enabled and predicate:
raise ExitCode() raise ExitCode()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -31,10 +31,12 @@ from ahriman.models.repository_paths import RepositoryPaths
class Setup(Handler): class Setup(Handler):
""" """
setup handler setup handler
:cvar ARCHBUILD_COMMAND_PATH: default devtools command
:cvar BIN_DIR_PATH: directory for custom binaries Attributes:
:cvar MIRRORLIST_PATH: path to pacman default mirrorlist (used by multilib repository) ARCHBUILD_COMMAND_PATH(Path): (class attribute) default devtools command
:cvar SUDOERS_PATH: path to sudoers.d include configuration BIN_DIR_PATH(Path): (class attribute) directory for custom binaries
MIRRORLIST_PATH(Path): (class attribute) path to pacman default mirrorlist (used by multilib repository)
SUDOERS_PATH(Path): (class attribute) path to sudoers.d include configuration
""" """
ALLOW_AUTO_ARCHITECTURE_RUN = False ALLOW_AUTO_ARCHITECTURE_RUN = False
@ -49,11 +51,13 @@ class Setup(Handler):
configuration: Configuration, no_report: bool, unsafe: bool) -> None: configuration: Configuration, no_report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
:param args: command line args
:param architecture: repository architecture Args:
:param configuration: configuration instance args(argparse.Namespace): command line args
:param no_report: force disable reporting architecture(str): repository architecture
:param unsafe: if set no user check will be performed before path creation configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
Setup.configuration_create_ahriman(args, architecture, args.repository, configuration.include) Setup.configuration_create_ahriman(args, architecture, args.repository, configuration.include)
configuration.reload() configuration.reload()
@ -72,9 +76,13 @@ class Setup(Handler):
def build_command(prefix: str, architecture: str) -> Path: def build_command(prefix: str, architecture: str) -> Path:
""" """
generate build command name generate build command name
:param prefix: command prefix in {prefix}-{architecture}-build
:param architecture: repository architecture Args:
:return: valid devtools command name prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
Returns:
Path: valid devtools command name
""" """
return Setup.BIN_DIR_PATH / f"{prefix}-{architecture}-build" return Setup.BIN_DIR_PATH / f"{prefix}-{architecture}-build"
@ -83,10 +91,12 @@ class Setup(Handler):
include_path: Path) -> None: include_path: Path) -> None:
""" """
create service specific configuration create service specific configuration
:param args: command line args
:param architecture: repository architecture Args:
:param repository: repository name args(argparse.Namespace): command line args
:param include_path: path to directory with configuration includes architecture(str): repository architecture
repository(str): repository name
include_path(Path): path to directory with configuration includes
""" """
configuration = Configuration() configuration = Configuration()
@ -114,12 +124,14 @@ class Setup(Handler):
no_multilib: bool, repository: str, paths: RepositoryPaths) -> None: no_multilib: bool, repository: str, paths: RepositoryPaths) -> None:
""" """
create configuration for devtools based on `source` configuration create configuration for devtools based on `source` configuration
:param prefix: command prefix in {prefix}-{architecture}-build
:param architecture: repository architecture Args:
:param source: path to source configuration file prefix(str): command prefix in {prefix}-{architecture}-build
:param no_multilib: do not add multilib repository architecture(str): repository architecture
:param repository: repository name source(Path): path to source configuration file
:param paths: repository paths instance no_multilib(bool): do not add multilib repository
repository(str): repository name
paths(RepositoryPaths): repository paths instance
""" """
configuration = Configuration() configuration = Configuration()
# preserve case # preserve case
@ -149,8 +161,10 @@ class Setup(Handler):
def configuration_create_makepkg(packager: str, paths: RepositoryPaths) -> None: def configuration_create_makepkg(packager: str, paths: RepositoryPaths) -> None:
""" """
create configuration for makepkg create configuration for makepkg
:param packager: packager identifier (e.g. name, email)
:param paths: repository paths instance Args:
packager(str): packager identifier (e.g. name, email)
paths(RepositoryPaths): repository paths instance
""" """
(paths.root / ".makepkg.conf").write_text(f"PACKAGER='{packager}'\n", encoding="utf8") (paths.root / ".makepkg.conf").write_text(f"PACKAGER='{packager}'\n", encoding="utf8")
@ -158,8 +172,10 @@ class Setup(Handler):
def configuration_create_sudo(prefix: str, architecture: str) -> None: def configuration_create_sudo(prefix: str, architecture: str) -> None:
""" """
create configuration to run build command with sudo without password create configuration to run build command with sudo without password
:param prefix: command prefix in {prefix}-{architecture}-build
:param architecture: repository architecture Args:
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
""" """
command = Setup.build_command(prefix, architecture) command = Setup.build_command(prefix, architecture)
Setup.SUDOERS_PATH.write_text(f"ahriman ALL=(ALL) NOPASSWD: {command} *\n", encoding="utf8") Setup.SUDOERS_PATH.write_text(f"ahriman ALL=(ALL) NOPASSWD: {command} *\n", encoding="utf8")
@ -169,8 +185,10 @@ class Setup(Handler):
def executable_create(prefix: str, architecture: str) -> None: def executable_create(prefix: str, architecture: str) -> None:
""" """
create executable for the service create executable for the service
:param prefix: command prefix in {prefix}-{architecture}-build
:param architecture: repository architecture Args:
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
""" """
command = Setup.build_command(prefix, architecture) command = Setup.build_command(prefix, architecture)
command.unlink(missing_ok=True) command.unlink(missing_ok=True)

View File

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

View File

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

View File

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

View File

@ -28,7 +28,7 @@ from ahriman.core.configuration import Configuration
class Sync(Handler): class Sync(Handler):
""" """
remove sync handler remote sync handler
""" """
@classmethod @classmethod
@ -36,10 +36,12 @@ class Sync(Handler):
configuration: Configuration, no_report: bool, unsafe: bool) -> None: configuration: Configuration, no_report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
:param args: command line args
:param architecture: repository architecture Args:
:param configuration: configuration instance args(argparse.Namespace): command line args
:param no_report: force disable reporting architecture(str): repository architecture
:param unsafe: if set no user check will be performed before path creation configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
Application(architecture, configuration, no_report, unsafe).sync(args.target, []) Application(architecture, configuration, no_report, unsafe).sync(args.target, [])

View File

@ -24,7 +24,6 @@ from typing import List, Type
from ahriman.application.handlers.handler import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import ExitCode
from ahriman.core.formatters.string_printer import StringPrinter from ahriman.core.formatters.string_printer import StringPrinter
@ -40,11 +39,13 @@ class UnsafeCommands(Handler):
configuration: Configuration, no_report: bool, unsafe: bool) -> None: configuration: Configuration, no_report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
:param args: command line args
:param architecture: repository architecture Args:
:param configuration: configuration instance args(argparse.Namespace): command line args
:param no_report: force disable reporting architecture(str): repository architecture
:param unsafe: if set no user check will be performed before path creation configuration(Configuration): configuration instance
no_report(bool): force disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
parser = args.parser() parser = args.parser()
unsafe_commands = UnsafeCommands.get_unsafe_commands(parser) unsafe_commands = UnsafeCommands.get_unsafe_commands(parser)
@ -58,20 +59,25 @@ class UnsafeCommands(Handler):
def check_unsafe(command: str, unsafe_commands: List[str], parser: argparse.ArgumentParser) -> None: def check_unsafe(command: str, unsafe_commands: List[str], parser: argparse.ArgumentParser) -> None:
""" """
check if command is unsafe check if command is unsafe
:param command: command to check
:param unsafe_commands: list of unsafe commands Args:
:param parser: generated argument parser command(str): command to check
unsafe_commands(List[str]): list of unsafe commands
parser(argparse.ArgumentParser): generated argument parser
""" """
args = parser.parse_args(shlex.split(command)) args = parser.parse_args(shlex.split(command))
if args.command in unsafe_commands: UnsafeCommands.check_if_empty(True, args.command in unsafe_commands)
raise ExitCode()
@staticmethod @staticmethod
def get_unsafe_commands(parser: argparse.ArgumentParser) -> List[str]: def get_unsafe_commands(parser: argparse.ArgumentParser) -> List[str]:
""" """
extract unsafe commands from argument parser extract unsafe commands from argument parser
:param parser: generated argument parser
:return: list of commands with default unsafe flag Args:
parser(argparse.ArgumentParser): generated argument parser
Returns:
List[str]: list of commands with default unsafe flag
""" """
# pylint: disable=protected-access # pylint: disable=protected-access
subparser = next(action for action in parser._actions if isinstance(action, argparse._SubParsersAction)) subparser = next(action for action in parser._actions if isinstance(action, argparse._SubParsersAction))

View File

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

View File

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

View File

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

View File

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

View File

@ -26,13 +26,17 @@ from ahriman.core.configuration import Configuration
class Pacman: class Pacman:
""" """
alpm wrapper alpm wrapper
:ivar handle: pyalpm root `Handle`
Attributes:
handle(Handle): pyalpm root `Handle`
""" """
def __init__(self, configuration: Configuration) -> None: def __init__(self, configuration: Configuration) -> None:
""" """
default constructor default constructor
:param configuration: configuration instance
Args:
configuration(Configuration): configuration instance
""" """
root = configuration.get("alpm", "root") root = configuration.get("alpm", "root")
pacman_root = configuration.getpath("alpm", "database") pacman_root = configuration.getpath("alpm", "database")
@ -43,7 +47,9 @@ class Pacman:
def all_packages(self) -> Set[str]: def all_packages(self) -> Set[str]:
""" """
get list of packages known for alpm get list of packages known for alpm
:return: list of package names
Returns:
Set[str]: list of package names
""" """
result: Set[str] = set() result: Set[str] = set()
for database in self.handle.get_syncdbs(): for database in self.handle.get_syncdbs():

View File

@ -30,10 +30,12 @@ from ahriman.models.aur_package import AURPackage
class AUR(Remote): class AUR(Remote):
""" """
AUR RPC wrapper AUR RPC wrapper
:cvar DEFAULT_RPC_URL: default AUR RPC url
:cvar DEFAULT_RPC_VERSION: default AUR RPC version Attributes:
:ivar rpc_url: AUR RPC url DEFAULT_RPC_URL(str): (class attribute) default AUR RPC url
:ivar rpc_version: AUR RPC version DEFAULT_RPC_VERSION(str): (class attribute) default AUR RPC version
rpc_url(str): AUR RPC url
rpc_version(str): AUR RPC version
""" """
DEFAULT_RPC_URL = "https://aur.archlinux.org/rpc" DEFAULT_RPC_URL = "https://aur.archlinux.org/rpc"
@ -42,8 +44,10 @@ class AUR(Remote):
def __init__(self, rpc_url: Optional[str] = None, rpc_version: Optional[str] = None) -> None: def __init__(self, rpc_url: Optional[str] = None, rpc_version: Optional[str] = None) -> None:
""" """
default constructor default constructor
:param rpc_url: AUR RPC url
:param rpc_version: AUR RPC version Args:
rpc_url(Optional[str], optional): AUR RPC url (Default value = None)
rpc_version(Optional[str], optional): AUR RPC version (Default value = None)
""" """
Remote.__init__(self) Remote.__init__(self)
self.rpc_url = rpc_url or self.DEFAULT_RPC_URL self.rpc_url = rpc_url or self.DEFAULT_RPC_URL
@ -53,8 +57,15 @@ class AUR(Remote):
def parse_response(response: Dict[str, Any]) -> List[AURPackage]: def parse_response(response: Dict[str, Any]) -> List[AURPackage]:
""" """
parse RPC response to package list parse RPC response to package list
:param response: RPC response json
:return: list of parsed packages Args:
response(Dict[str, Any]): RPC response json
Returns:
List[AURPackage]: list of parsed packages
Raises:
InvalidPackageInfo: for error API response
""" """
response_type = response["type"] response_type = response["type"]
if response_type == "error": if response_type == "error":
@ -65,10 +76,14 @@ class AUR(Remote):
def make_request(self, request_type: str, *args: str, **kwargs: str) -> List[AURPackage]: def make_request(self, request_type: str, *args: str, **kwargs: str) -> List[AURPackage]:
""" """
perform request to AUR RPC perform request to AUR RPC
:param request_type: AUR request type, e.g. search, info
:param args: list of arguments to be passed as args query parameter Args:
:param kwargs: list of additional named parameters like by request_type(str): AUR request type, e.g. search, info
:return: response parsed to package list *args(str): list of arguments to be passed as args query parameter
**kwargs(str): list of additional named parameters like by
Returns:
List[AURPackage]: response parsed to package list
""" """
query: Dict[str, Any] = { query: Dict[str, Any] = {
"type": request_type, "type": request_type,
@ -98,8 +113,12 @@ class AUR(Remote):
def package_info(self, package_name: str) -> AURPackage: def package_info(self, package_name: str) -> AURPackage:
""" """
get package info by its name get package info by its name
:param package_name: package name to search
:return: package which match the package name Args:
package_name(str): package name to search
Returns:
AURPackage: package which match the package name
""" """
packages = self.make_request("info", package_name) packages = self.make_request("info", package_name)
return next(package for package in packages if package.name == package_name) return next(package for package in packages if package.name == package_name)
@ -107,7 +126,11 @@ class AUR(Remote):
def package_search(self, *keywords: str) -> List[AURPackage]: def package_search(self, *keywords: str) -> List[AURPackage]:
""" """
search package in AUR web search package in AUR web
:param keywords: keywords to search
:return: list of packages which match the criteria Args:
*keywords(str): keywords to search
Returns:
List[AURPackage]: list of packages which match the criteria
""" """
return self.make_request("search", *keywords, by="name-desc") return self.make_request("search", *keywords, by="name-desc")

View File

@ -30,8 +30,10 @@ from ahriman.models.aur_package import AURPackage
class Official(Remote): class Official(Remote):
""" """
official repository RPC wrapper official repository RPC wrapper
:cvar DEFAULT_RPC_URL: default AUR RPC url
:ivar rpc_url: AUR RPC url Attributes:
DEFAULT_RPC_URL(str): (class attribute) default AUR RPC url
rpc_url(str): AUR RPC url
""" """
DEFAULT_RPC_URL = "https://archlinux.org/packages/search/json" DEFAULT_RPC_URL = "https://archlinux.org/packages/search/json"
@ -39,7 +41,9 @@ class Official(Remote):
def __init__(self, rpc_url: Optional[str] = None) -> None: def __init__(self, rpc_url: Optional[str] = None) -> None:
""" """
default constructor default constructor
:param rpc_url: AUR RPC url
Args:
rpc_url(Optional[str], optional): AUR RPC url (Default value = None)
""" """
Remote.__init__(self) Remote.__init__(self)
self.rpc_url = rpc_url or self.DEFAULT_RPC_URL self.rpc_url = rpc_url or self.DEFAULT_RPC_URL
@ -48,8 +52,15 @@ class Official(Remote):
def parse_response(response: Dict[str, Any]) -> List[AURPackage]: def parse_response(response: Dict[str, Any]) -> List[AURPackage]:
""" """
parse RPC response to package list parse RPC response to package list
:param response: RPC response json
:return: list of parsed packages Args:
response(Dict[str, Any]): RPC response json
Returns:
List[AURPackage]: list of parsed packages
Raises:
InvalidPackageInfo: for error API response
""" """
if not response["valid"]: if not response["valid"]:
raise InvalidPackageInfo("API validation error") raise InvalidPackageInfo("API validation error")
@ -58,9 +69,13 @@ class Official(Remote):
def make_request(self, *args: str, by: str) -> List[AURPackage]: def make_request(self, *args: str, by: str) -> List[AURPackage]:
""" """
perform request to official repositories RPC perform request to official repositories RPC
:param args: list of arguments to be passed as args query parameter
:param by: search by the field Args:
:return: response parsed to package list *args(str): list of arguments to be passed as args query parameter
by(str): search by the field
Returns:
List[AURPackage]: response parsed to package list
""" """
try: try:
response = requests.get(self.rpc_url, params={by: args}) response = requests.get(self.rpc_url, params={by: args})
@ -76,8 +91,12 @@ class Official(Remote):
def package_info(self, package_name: str) -> AURPackage: def package_info(self, package_name: str) -> AURPackage:
""" """
get package info by its name get package info by its name
:param package_name: package name to search
:return: package which match the package name Args:
package_name(str): package name to search
Returns:
AURPackage: package which match the package name
""" """
packages = self.make_request(package_name, by="name") packages = self.make_request(package_name, by="name")
return next(package for package in packages if package.name == package_name) return next(package for package in packages if package.name == package_name)
@ -85,7 +104,11 @@ class Official(Remote):
def package_search(self, *keywords: str) -> List[AURPackage]: def package_search(self, *keywords: str) -> List[AURPackage]:
""" """
search package in AUR web search package in AUR web
:param keywords: keywords to search
:return: list of packages which match the criteria Args:
*keywords(str): keywords to search
Returns:
List[AURPackage]: list of packages which match the criteria
""" """
return self.make_request(*keywords, by="q") return self.make_request(*keywords, by="q")

View File

@ -29,7 +29,9 @@ from ahriman.models.aur_package import AURPackage
class Remote: class Remote:
""" """
base class for remote package search base class for remote package search
:ivar logger: class logger
Attributes:
logger(logging.Logger): class logger
""" """
def __init__(self) -> None: def __init__(self) -> None:
@ -42,8 +44,12 @@ class Remote:
def info(cls: Type[Remote], package_name: str) -> AURPackage: def info(cls: Type[Remote], package_name: str) -> AURPackage:
""" """
get package info by its name get package info by its name
:param package_name: package name to search
:return: package which match the package name Args:
package_name(str): package name to search
Returns:
AURPackage: package which match the package name
""" """
return cls().package_info(package_name) return cls().package_info(package_name)
@ -52,8 +58,12 @@ class Remote:
""" """
search in remote repository by using API with multiple words. This method is required in order to handle search in remote repository by using API with multiple words. This method is required in order to handle
https://bugs.archlinux.org/task/49133. In addition, short words will be dropped https://bugs.archlinux.org/task/49133. In addition, short words will be dropped
:param keywords: search terms, e.g. "ahriman", "is", "cool"
:return: list of packages each of them matches all search terms Args:
*keywords(str): search terms, e.g. "ahriman", "is", "cool"
Returns:
List[AURPackage]: list of packages each of them matches all search terms
""" """
instance = cls() instance = cls()
packages: Dict[str, AURPackage] = {} packages: Dict[str, AURPackage] = {}
@ -70,23 +80,41 @@ class Remote:
def search(cls: Type[Remote], *keywords: str) -> List[AURPackage]: def search(cls: Type[Remote], *keywords: str) -> List[AURPackage]:
""" """
search package in AUR web search package in AUR web
:param keywords: keywords to search
:return: list of packages which match the criteria Args:
*keywords(str): search terms, e.g. "ahriman", "is", "cool"
Returns:
List[AURPackage]: list of packages which match the criteria
""" """
return cls().package_search(*keywords) return cls().package_search(*keywords)
def package_info(self, package_name: str) -> AURPackage: def package_info(self, package_name: str) -> AURPackage:
""" """
get package info by its name get package info by its name
:param package_name: package name to search
:return: package which match the package name Args:
package_name(str): package name to search
Returns:
AURPackage: package which match the package name
Raises:
NotImplementedError: not implemented method
""" """
raise NotImplementedError raise NotImplementedError
def package_search(self, *keywords: str) -> List[AURPackage]: def package_search(self, *keywords: str) -> List[AURPackage]:
""" """
search package in AUR web search package in AUR web
:param keywords: keywords to search
:return: list of packages which match the criteria Args:
*keywords(str): keywords to search
Returns:
List[AURPackage]: list of packages which match the criteria
Raises:
NotImplementedError: not implemented method
""" """
raise NotImplementedError raise NotImplementedError

View File

@ -30,11 +30,13 @@ from ahriman.models.repository_paths import RepositoryPaths
class Repo: class Repo:
""" """
repo-add and repo-remove wrapper repo-add and repo-remove wrapper
:ivar logger: class logger
:ivar name: repository name Attributes:
:ivar paths: repository paths instance logger(logging.Logger): class logger
:ivar sign_args: additional args which have to be used to sign repository archive name(str): repository name
:ivar uid: uid of the repository owner user paths(RepositoryPaths): repository paths instance
sign_args(List[str]): additional args which have to be used to sign repository archive
uid(int): uid of the repository owner user
""" """
_check_output = check_output _check_output = check_output
@ -42,9 +44,11 @@ class Repo:
def __init__(self, name: str, paths: RepositoryPaths, sign_args: List[str]) -> None: def __init__(self, name: str, paths: RepositoryPaths, sign_args: List[str]) -> None:
""" """
default constructor default constructor
:param name: repository name
:param paths: repository paths instance Args:
:param sign_args: additional args which have to be used to sign repository archive name(str): repository name
paths(RepositoryPaths): repository paths instance
sign_args(List[str]): additional args which have to be used to sign repository archive
""" """
self.logger = logging.getLogger("build_details") self.logger = logging.getLogger("build_details")
self.name = name self.name = name
@ -55,14 +59,19 @@ class Repo:
@property @property
def repo_path(self) -> Path: def repo_path(self) -> Path:
""" """
:return: path to repository database get full path to the repository database
Returns:
Path: path to repository database
""" """
return self.paths.repository / f"{self.name}.db.tar.gz" return self.paths.repository / f"{self.name}.db.tar.gz"
def add(self, path: Path) -> None: def add(self, path: Path) -> None:
""" """
add new package to repository add new package to repository
:param path: path to archive to add
Args:
path(Path): path to archive to add
""" """
Repo._check_output( Repo._check_output(
"repo-add", *self.sign_args, "-R", str(self.repo_path), str(path), "repo-add", *self.sign_args, "-R", str(self.repo_path), str(path),
@ -85,8 +94,10 @@ class Repo:
def remove(self, package: str, filename: Path) -> None: def remove(self, package: str, filename: Path) -> None:
""" """
remove package from repository remove package from repository
:param package: package name to remove
:param filename: package filename to remove Args:
package(str): package name to remove
filename(Path): package filename to remove
""" """
# remove package and signature (if any) from filesystem # remove package and signature (if any) from filesystem
for full_path in self.paths.repository.glob(f"{filename}*"): for full_path in self.paths.repository.glob(f"{filename}*"):

View File

@ -32,16 +32,21 @@ from ahriman.models.user_access import UserAccess
class Auth: class Auth:
""" """
helper to deal with user authorization helper to deal with user authorization
:ivar enabled: indicates if authorization is enabled
:ivar max_age: session age in seconds. It will be used for both client side and server side checks Attributes:
:ivar safe_build_status: allow read only access to the index page enabled(bool): indicates if authorization is enabled
logger(logging.Logger): class logger
max_age(int): session age in seconds. It will be used for both client side and server side checks
safe_build_status(bool): allow read only access to the index page
""" """
def __init__(self, configuration: Configuration, provider: AuthSettings = AuthSettings.Disabled) -> None: def __init__(self, configuration: Configuration, provider: AuthSettings = AuthSettings.Disabled) -> None:
""" """
default constructor default constructor
:param configuration: configuration instance
:param provider: authorization type definition Args:
configuration(Configuration): configuration instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Disabled)
""" """
self.logger = logging.getLogger("http") self.logger = logging.getLogger("http")
@ -57,7 +62,9 @@ class Auth:
In case of internal authentication it must provide an interface (modal form) to login with button sends POST In case of internal authentication it must provide an interface (modal form) to login with button sends POST
request. But for an external providers behaviour can be different: e.g. OAuth provider requires sending GET request. But for an external providers behaviour can be different: e.g. OAuth provider requires sending GET
request to external resource request to external resource
:return: login control as html code to insert
Returns:
str: login control as html code to insert
""" """
return """<button type="button" class="btn btn-link" data-bs-toggle="modal" data-bs-target="#loginForm" style="text-decoration: none">login</button>""" return """<button type="button" class="btn btn-link" data-bs-toggle="modal" data-bs-target="#loginForm" style="text-decoration: none">login</button>"""
@ -65,9 +72,13 @@ class Auth:
def load(cls: Type[Auth], configuration: Configuration, database: SQLite) -> Auth: def load(cls: Type[Auth], configuration: Configuration, database: SQLite) -> Auth:
""" """
load authorization module from settings load authorization module from settings
:param configuration: configuration instance
:param database: database instance Args:
:return: authorization module according to current settings configuration(Configuration): configuration instance
database(SQLite): database instance
Returns:
Auth: authorization module according to current settings
""" """
provider = AuthSettings.from_option(configuration.get("auth", "target", fallback="disabled")) provider = AuthSettings.from_option(configuration.get("auth", "target", fallback="disabled"))
if provider == AuthSettings.Configuration: if provider == AuthSettings.Configuration:
@ -81,9 +92,13 @@ class Auth:
async def check_credentials(self, username: Optional[str], password: Optional[str]) -> bool: # pylint: disable=no-self-use async def check_credentials(self, username: Optional[str], password: Optional[str]) -> bool: # pylint: disable=no-self-use
""" """
validate user password validate user password
:param username: username
:param password: entered password Args:
:return: True in case if password matches, False otherwise username(Optional[str]): username
password(Optional[str]): entered password
Returns:
bool: True in case if password matches, False otherwise
""" """
del username, password del username, password
return True return True
@ -91,8 +106,12 @@ class Auth:
async def known_username(self, username: Optional[str]) -> bool: # pylint: disable=no-self-use async def known_username(self, username: Optional[str]) -> bool: # pylint: disable=no-self-use
""" """
check if user is known check if user is known
:param username: username
:return: True in case if user is known and can be authorized and False otherwise Args:
username(Optional[str]): username
Returns:
bool: True in case if user is known and can be authorized and False otherwise
""" """
del username del username
return True return True
@ -100,10 +119,14 @@ class Auth:
async def verify_access(self, username: str, required: UserAccess, context: Optional[str]) -> bool: # pylint: disable=no-self-use async def verify_access(self, username: str, required: UserAccess, context: Optional[str]) -> bool: # pylint: disable=no-self-use
""" """
validate if user has access to requested resource validate if user has access to requested resource
:param username: username
:param required: required access level Args:
:param context: URI request path username(str): username
:return: True in case if user is allowed to do this request and False otherwise required(UserAccess): required access level
context(Optional[str]): URI request path
Returns:
bool: True in case if user is allowed to do this request and False otherwise
""" """
del username, required, context del username, required, context
return True return True

View File

@ -29,8 +29,12 @@ except ImportError:
async def authorized_userid(*args: Any) -> Any: async def authorized_userid(*args: Any) -> Any:
""" """
handle aiohttp security methods handle aiohttp security methods
:param args: argument list as provided by authorized_userid function
:return: None in case if no aiohttp_security module found and function call otherwise Args:
*args(Any): argument list as provided by authorized_userid function
Returns:
Any: None in case if no aiohttp_security module found and function call otherwise
""" """
if _has_aiohttp_security: if _has_aiohttp_security:
return await aiohttp_security.authorized_userid(*args) # pylint: disable=no-value-for-parameter return await aiohttp_security.authorized_userid(*args) # pylint: disable=no-value-for-parameter
@ -40,8 +44,12 @@ async def authorized_userid(*args: Any) -> Any:
async def check_authorized(*args: Any) -> Any: async def check_authorized(*args: Any) -> Any:
""" """
handle aiohttp security methods handle aiohttp security methods
:param args: argument list as provided by check_authorized function
:return: None in case if no aiohttp_security module found and function call otherwise Args:
*args(Any): argument list as provided by check_authorized function
Returns:
Any: None in case if no aiohttp_security module found and function call otherwise
""" """
if _has_aiohttp_security: if _has_aiohttp_security:
return await aiohttp_security.check_authorized(*args) # pylint: disable=no-value-for-parameter return await aiohttp_security.check_authorized(*args) # pylint: disable=no-value-for-parameter
@ -51,8 +59,12 @@ async def check_authorized(*args: Any) -> Any:
async def forget(*args: Any) -> Any: async def forget(*args: Any) -> Any:
""" """
handle aiohttp security methods handle aiohttp security methods
:param args: argument list as provided by forget function
:return: None in case if no aiohttp_security module found and function call otherwise Args:
*args(Any): argument list as provided by forget function
Returns:
Any: None in case if no aiohttp_security module found and function call otherwise
""" """
if _has_aiohttp_security: if _has_aiohttp_security:
return await aiohttp_security.forget(*args) # pylint: disable=no-value-for-parameter return await aiohttp_security.forget(*args) # pylint: disable=no-value-for-parameter
@ -62,8 +74,12 @@ async def forget(*args: Any) -> Any:
async def remember(*args: Any) -> Any: async def remember(*args: Any) -> Any:
""" """
handle disabled auth handle disabled auth
:param args: argument list as provided by remember function
:return: None in case if no aiohttp_security module found and function call otherwise Args:
*args(Any): argument list as provided by remember function
Returns:
Any: None in case if no aiohttp_security module found and function call otherwise
""" """
if _has_aiohttp_security: if _has_aiohttp_security:
return await aiohttp_security.remember(*args) # pylint: disable=no-value-for-parameter return await aiohttp_security.remember(*args) # pylint: disable=no-value-for-parameter

View File

@ -31,17 +31,21 @@ from ahriman.models.user_access import UserAccess
class Mapping(Auth): class Mapping(Auth):
""" """
user authorization based on mapping from configuration file user authorization based on mapping from configuration file
:ivar salt: random generated string to salt passwords
:ivar database: database instance Attributes:
salt(str): random generated string to salt passwords
database(SQLite): database instance
""" """
def __init__(self, configuration: Configuration, database: SQLite, def __init__(self, configuration: Configuration, database: SQLite,
provider: AuthSettings = AuthSettings.Configuration) -> None: provider: AuthSettings = AuthSettings.Configuration) -> None:
""" """
default constructor default constructor
:param configuration: configuration instance
:param database: database instance Args:
:param provider: authorization type definition configuration(Configuration): configuration instance
database(SQLite): database instance
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Configuration)
""" """
Auth.__init__(self, configuration, provider) Auth.__init__(self, configuration, provider)
self.database = database self.database = database
@ -50,9 +54,13 @@ class Mapping(Auth):
async def check_credentials(self, username: Optional[str], password: Optional[str]) -> bool: async def check_credentials(self, username: Optional[str], password: Optional[str]) -> bool:
""" """
validate user password validate user password
:param username: username
:param password: entered password Args:
:return: True in case if password matches, False otherwise username(Optional[str]): username
password(Optional[str]): entered password
Returns:
bool: True in case if password matches, False otherwise
""" """
if username is None or password is None: if username is None or password is None:
return False # invalid data supplied return False # invalid data supplied
@ -62,26 +70,38 @@ class Mapping(Auth):
def get_user(self, username: str) -> Optional[User]: def get_user(self, username: str) -> Optional[User]:
""" """
retrieve user from in-memory mapping retrieve user from in-memory mapping
:param username: username
:return: user descriptor if username is known and None otherwise Args:
username(str): username
Returns:
Optional[User]: user descriptor if username is known and None otherwise
""" """
return self.database.user_get(username) return self.database.user_get(username)
async def known_username(self, username: Optional[str]) -> bool: async def known_username(self, username: Optional[str]) -> bool:
""" """
check if user is known check if user is known
:param username: username
:return: True in case if user is known and can be authorized and False otherwise Args:
username(Optional[str]): username
Returns:
bool: True in case if user is known and can be authorized and False otherwise
""" """
return username is not None and self.get_user(username) is not None return username is not None and self.get_user(username) is not None
async def verify_access(self, username: str, required: UserAccess, context: Optional[str]) -> bool: async def verify_access(self, username: str, required: UserAccess, context: Optional[str]) -> bool:
""" """
validate if user has access to requested resource validate if user has access to requested resource
:param username: username
:param required: required access level Args:
:param context: URI request path username(str): username
:return: True in case if user is allowed to do this request and False otherwise required(UserAccess): required access level
context(Optional[str]): URI request path
Returns:
bool: True in case if user is allowed to do this request and False otherwise
""" """
user = self.get_user(username) user = self.get_user(username)
return user is not None and user.verify_access(required) return user is not None and user.verify_access(required)

View File

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

View File

@ -28,7 +28,9 @@ from ahriman.core.util import check_output
class Sources: class Sources:
""" """
helper to download package sources (PKGBUILD etc) helper to download package sources (PKGBUILD etc)
:cvar logger: class logger
Attributes:
logger(logging.Logger): (class attribute) class logger
""" """
logger = logging.getLogger("build_details") logger = logging.getLogger("build_details")
@ -40,8 +42,10 @@ class Sources:
def add(sources_dir: Path, *pattern: str) -> None: def add(sources_dir: Path, *pattern: str) -> None:
""" """
track found files via git track found files via git
:param sources_dir: local path to git repository
:param pattern: glob patterns Args:
sources_dir(Path): local path to git repository
*pattern(str): glob patterns
""" """
# glob directory to find files which match the specified patterns # glob directory to find files which match the specified patterns
found_files: List[Path] = [] found_files: List[Path] = []
@ -59,8 +63,12 @@ class Sources:
def diff(sources_dir: Path) -> str: def diff(sources_dir: Path) -> str:
""" """
generate diff from the current version and write it to the output file generate diff from the current version and write it to the output file
:param sources_dir: local path to git repository
:return: patch as plain string Args:
sources_dir(Path): local path to git repository
Returns:
str: patch as plain string
""" """
return Sources._check_output("git", "diff", exception=None, cwd=sources_dir, logger=Sources.logger) return Sources._check_output("git", "diff", exception=None, cwd=sources_dir, logger=Sources.logger)
@ -68,8 +76,10 @@ class Sources:
def fetch(sources_dir: Path, remote: Optional[str]) -> None: def fetch(sources_dir: Path, remote: Optional[str]) -> None:
""" """
either clone repository or update it to origin/`branch` either clone repository or update it to origin/`branch`
:param sources_dir: local path to fetch
:param remote: remote target (from where to fetch) Args:
sources_dir(Path): local path to fetch
remote(Optional[str]): remote target (from where to fetch)
""" """
# local directory exists and there is .git directory # local directory exists and there is .git directory
is_initialized_git = (sources_dir / ".git").is_dir() is_initialized_git = (sources_dir / ".git").is_dir()
@ -98,8 +108,12 @@ class Sources:
def has_remotes(sources_dir: Path) -> bool: def has_remotes(sources_dir: Path) -> bool:
""" """
check if there are remotes for the repository check if there are remotes for the repository
:param sources_dir: local path to git repository
:return: True in case if there is any remote and false otherwise Args:
sources_dir(Path): local path to git repository
Returns:
bool: True in case if there is any remote and false otherwise
""" """
remotes = Sources._check_output("git", "remote", exception=None, cwd=sources_dir, logger=Sources.logger) remotes = Sources._check_output("git", "remote", exception=None, cwd=sources_dir, logger=Sources.logger)
return bool(remotes) return bool(remotes)
@ -108,7 +122,9 @@ class Sources:
def init(sources_dir: Path) -> None: def init(sources_dir: Path) -> None:
""" """
create empty git repository at the specified path create empty git repository at the specified path
:param sources_dir: local path to sources
Args:
sources_dir(Path): local path to sources
""" """
Sources._check_output("git", "init", "--initial-branch", Sources._branch, Sources._check_output("git", "init", "--initial-branch", Sources._branch,
exception=None, cwd=sources_dir, logger=Sources.logger) exception=None, cwd=sources_dir, logger=Sources.logger)
@ -117,9 +133,11 @@ class Sources:
def load(sources_dir: Path, remote: str, patch: Optional[str]) -> None: def load(sources_dir: Path, remote: str, patch: Optional[str]) -> None:
""" """
fetch sources from remote and apply patches fetch sources from remote and apply patches
:param sources_dir: local path to fetch
:param remote: remote target (from where to fetch) Args:
:param patch: optional patch to be applied sources_dir(Path): local path to fetch
remote(str): remote target (from where to fetch)
patch(Optional[str]): optional patch to be applied
""" """
Sources.fetch(sources_dir, remote) Sources.fetch(sources_dir, remote)
if patch is None: if patch is None:
@ -131,8 +149,10 @@ class Sources:
def patch_apply(sources_dir: Path, patch: str) -> None: def patch_apply(sources_dir: Path, patch: str) -> None:
""" """
apply patches if any apply patches if any
:param sources_dir: local path to directory with git sources
:param patch: patch to be applied Args:
sources_dir(Path): local path to directory with git sources
patch(str): patch to be applied
""" """
# create patch # create patch
Sources.logger.info("apply patch from database") Sources.logger.info("apply patch from database")
@ -143,9 +163,13 @@ class Sources:
def patch_create(sources_dir: Path, *pattern: str) -> str: def patch_create(sources_dir: Path, *pattern: str) -> str:
""" """
create patch set for the specified local path create patch set for the specified local path
:param sources_dir: local path to git repository
:param pattern: glob patterns Args:
:return: patch as plain text sources_dir(Path): local path to git repository
*pattern(str): glob patterns
Returns:
str: patch as plain text
""" """
Sources.add(sources_dir, *pattern) Sources.add(sources_dir, *pattern)
diff = Sources.diff(sources_dir) diff = Sources.diff(sources_dir)

View File

@ -35,11 +35,13 @@ from ahriman.models.repository_paths import RepositoryPaths
class Task: class Task:
""" """
base package build task base package build task
:ivar build_logger: logger for build process
:ivar logger: class logger Attributes:
:ivar package: package definitions build_logger(logging.Logger): logger for build process
:ivar paths: repository paths instance logger(logging.Logger): class logger
:ivar uid: uid of the repository owner user package(Package): package definitions
paths(RepositoryPaths): repository paths instance
uid(int): uid of the repository owner user
""" """
_check_output = check_output _check_output = check_output
@ -47,9 +49,11 @@ class Task:
def __init__(self, package: Package, configuration: Configuration, paths: RepositoryPaths) -> None: def __init__(self, package: Package, configuration: Configuration, paths: RepositoryPaths) -> None:
""" """
default constructor default constructor
:param package: package definitions
:param configuration: configuration instance Args:
:param paths: repository paths instance package(Package): package definitions
configuration(Configuration): configuration instance
paths(RepositoryPaths): repository paths instance
""" """
self.logger = logging.getLogger("root") self.logger = logging.getLogger("root")
self.build_logger = logging.getLogger("build_details") self.build_logger = logging.getLogger("build_details")
@ -65,8 +69,12 @@ class Task:
def build(self, sources_path: Path) -> List[Path]: def build(self, sources_path: Path) -> List[Path]:
""" """
run package build run package build
:param sources_path: path to where sources are
:return: paths of produced packages Args:
sources_path(Path): path to where sources are
Returns:
List[Path]: paths of produced packages
""" """
command = [self.build_command, "-r", str(self.paths.chroot)] command = [self.build_command, "-r", str(self.paths.chroot)]
command.extend(self.archbuild_flags) command.extend(self.archbuild_flags)
@ -91,8 +99,10 @@ class Task:
def init(self, path: Path, database: SQLite) -> None: def init(self, path: Path, database: SQLite) -> None:
""" """
fetch package from git fetch package from git
:param path: local path to fetch
:param database: database instance Args:
path(Path): local path to fetch
database(SQLite): database instance
""" """
if self.paths.cache_for(self.package.base).is_dir(): if self.paths.cache_for(self.package.base).is_dir():
# no need to clone whole repository, just copy from cache first # no need to clone whole repository, just copy from cache first

View File

@ -34,12 +34,15 @@ from ahriman.models.repository_paths import RepositoryPaths
class Configuration(configparser.RawConfigParser): class Configuration(configparser.RawConfigParser):
""" """
extension for built-in configuration parser extension for built-in configuration parser
:ivar architecture: repository architecture
:ivar path: path to root configuration file Attributes:
:cvar ARCHITECTURE_SPECIFIC_SECTIONS: known sections which can be architecture specific (required by dump) ARCHITECTURE_SPECIFIC_SECTIONS(List[str]): (class attribute) known sections which can be architecture specific.
:cvar DEFAULT_LOG_FORMAT: default log format (in case of fallback) Required by dump and merging functions
:cvar DEFAULT_LOG_LEVEL: default log level (in case of fallback) DEFAULT_LOG_FORMAT(str): (class attribute) default log format (in case of fallback)
:cvar SYSTEM_CONFIGURATION_PATH: default system configuration path distributed by package DEFAULT_LOG_LEVEL(int): (class attribute) default log level (in case of fallback)
SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package
architecture(Optional[str]): repository architecture
path(Optional[Path]): path to root configuration file
""" """
DEFAULT_LOG_FORMAT = "[%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s" DEFAULT_LOG_FORMAT = "[%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s"
@ -62,21 +65,30 @@ class Configuration(configparser.RawConfigParser):
@property @property
def include(self) -> Path: def include(self) -> Path:
""" """
:return: path to directory with configuration includes get full path to include directory
Returns:
Path: path to directory with configuration includes
""" """
return self.getpath("settings", "include") return self.getpath("settings", "include")
@property @property
def logging_path(self) -> Path: def logging_path(self) -> Path:
""" """
:return: path to logging configuration get full path to logging configuration
Returns:
Path: path to logging configuration
""" """
return self.getpath("settings", "logging") return self.getpath("settings", "logging")
@property @property
def repository_paths(self) -> RepositoryPaths: def repository_paths(self) -> RepositoryPaths:
""" """
:return: repository paths instance construct RepositoryPaths instance based on the configuration
Returns:
RepositoryPaths: repository paths instance
""" """
_, architecture = self.check_loaded() _, architecture = self.check_loaded()
return RepositoryPaths(self.getpath("repository", "root"), architecture) return RepositoryPaths(self.getpath("repository", "root"), architecture)
@ -85,10 +97,14 @@ class Configuration(configparser.RawConfigParser):
def from_path(cls: Type[Configuration], path: Path, architecture: str, quiet: bool) -> Configuration: def from_path(cls: Type[Configuration], path: Path, architecture: str, quiet: bool) -> Configuration:
""" """
constructor with full object initialization constructor with full object initialization
:param path: path to root configuration file
:param architecture: repository architecture Args:
:param quiet: force disable any log messages path(Path): path to root configuration file
:return: configuration instance architecture(str): repository architecture
quiet(bool): force disable any log messages
Returns:
Configuration: configuration instance
""" """
config = cls() config = cls()
config.load(path) config.load(path)
@ -100,8 +116,15 @@ class Configuration(configparser.RawConfigParser):
def __convert_list(value: str) -> List[str]: def __convert_list(value: str) -> List[str]:
""" """
convert string value to list of strings convert string value to list of strings
:param value: string configuration value
:return: list of string from the parsed string Args:
value(str): string configuration value
Returns:
List[str]: list of string from the parsed string
Raises:
ValueError: in case if option value contains unclosed quotes
""" """
def generator() -> Generator[str, None, None]: def generator() -> Generator[str, None, None]:
quote_mark = None quote_mark = None
@ -111,7 +134,7 @@ class Configuration(configparser.RawConfigParser):
quote_mark = char quote_mark = char
elif char == quote_mark: # quoted part ended, reset quotation elif char == quote_mark: # quoted part ended, reset quotation
quote_mark = None quote_mark = None
elif char == " " and quote_mark is None: # found space outside of the quotation, yield the word elif char == " " and quote_mark is None: # found space outside the quotation, yield the word
yield word yield word
word = "" word = ""
else: # append character to the buffer else: # append character to the buffer
@ -126,17 +149,25 @@ class Configuration(configparser.RawConfigParser):
def section_name(section: str, suffix: str) -> str: def section_name(section: str, suffix: str) -> str:
""" """
generate section name for sections which depends on context generate section name for sections which depends on context
:param section: section name
:param suffix: session suffix, e.g. repository architecture Args:
:return: correct section name for repository specific section section(str): section name
suffix(str): session suffix, e.g. repository architecture
Returns:
str: correct section name for repository specific section
""" """
return f"{section}:{suffix}" return f"{section}:{suffix}"
def __convert_path(self, value: str) -> Path: def __convert_path(self, value: str) -> Path:
""" """
convert string value to path object convert string value to path object
:param value: string configuration value
:return: path object which represents the configuration value Args:
value(str): string configuration value
Returns:
Path: path object which represents the configuration value
""" """
path = Path(value) path = Path(value)
if self.path is None or path.is_absolute(): if self.path is None or path.is_absolute():
@ -146,7 +177,12 @@ class Configuration(configparser.RawConfigParser):
def check_loaded(self) -> Tuple[Path, str]: def check_loaded(self) -> Tuple[Path, str]:
""" """
check if service was actually loaded check if service was actually loaded
:return: configuration root path and architecture if loaded
Returns:
Tuple[Path, str]: configuration root path and architecture if loaded
Raises:
InitializeException: in case if architecture and/or path are not set
""" """
if self.path is None or self.architecture is None: if self.path is None or self.architecture is None:
raise InitializeException("Configuration path and/or architecture are not set") raise InitializeException("Configuration path and/or architecture are not set")
@ -155,7 +191,9 @@ class Configuration(configparser.RawConfigParser):
def dump(self) -> Dict[str, Dict[str, str]]: def dump(self) -> Dict[str, Dict[str, str]]:
""" """
dump configuration to dictionary dump configuration to dictionary
:return: configuration dump for specific architecture
Returns:
Dict[str, Dict[str, str]]: configuration dump for specific architecture
""" """
return { return {
section: dict(self[section]) section: dict(self[section])
@ -172,9 +210,16 @@ class Configuration(configparser.RawConfigParser):
""" """
get type variable with fallback to old logic get type variable with fallback to old logic
Despite the fact that it has same semantics as other get* methods, but it has different argument list Despite the fact that it has same semantics as other get* methods, but it has different argument list
:param section: section name
:param architecture: repository architecture Args:
:return: section name and found type name section(str): section name
architecture(str): repository architecture
Returns:
Tuple[str, str]: section name and found type name
Raises:
configparser.NoSectionError: in case if no section found
""" """
group_type = self.get(section, "type", fallback=None) # new-style logic group_type = self.get(section, "type", fallback=None) # new-style logic
if group_type is not None: if group_type is not None:
@ -191,7 +236,9 @@ class Configuration(configparser.RawConfigParser):
def load(self, path: Path) -> None: def load(self, path: Path) -> None:
""" """
fully load configuration fully load configuration
:param path: path to root configuration file
Args:
path(Path): path to root configuration file
""" """
if not path.is_file(): # fallback to the system file if not path.is_file(): # fallback to the system file
path = self.SYSTEM_CONFIGURATION_PATH path = self.SYSTEM_CONFIGURATION_PATH
@ -214,7 +261,9 @@ class Configuration(configparser.RawConfigParser):
def load_logging(self, quiet: bool) -> None: def load_logging(self, quiet: bool) -> None:
""" """
setup logging settings from configuration setup logging settings from configuration
:param quiet: force disable any log messages
Args:
quiet(bool): force disable any log messages
""" """
try: try:
path = self.logging_path path = self.logging_path
@ -229,7 +278,9 @@ class Configuration(configparser.RawConfigParser):
def merge_sections(self, architecture: str) -> None: def merge_sections(self, architecture: str) -> None:
""" """
merge architecture specific sections into main configuration merge architecture specific sections into main configuration
:param architecture: repository architecture
Args:
architecture(str): repository architecture
""" """
self.architecture = architecture self.architecture = architecture
for section in self.ARCHITECTURE_SPECIFIC_SECTIONS: for section in self.ARCHITECTURE_SPECIFIC_SECTIONS:
@ -260,9 +311,11 @@ class Configuration(configparser.RawConfigParser):
def set_option(self, section: str, option: str, value: Optional[str]) -> None: def set_option(self, section: str, option: str, value: Optional[str]) -> None:
""" """
set option. Unlike default `configparser.RawConfigParser.set` it also creates section if it does not exist set option. Unlike default `configparser.RawConfigParser.set` it also creates section if it does not exist
:param section: section name
:param option: option name Args:
:param value: option value as string in parsable format section(str): section name
option(str): option name
value(Optional[str]): option value as string in parsable format
""" """
if not self.has_section(section): if not self.has_section(section):
self.add_section(section) self.add_section(section)

View File

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

View File

@ -29,8 +29,10 @@ from ahriman.models.repository_paths import RepositoryPaths
def migrate_package_statuses(connection: Connection, paths: RepositoryPaths) -> None: def migrate_package_statuses(connection: Connection, paths: RepositoryPaths) -> None:
""" """
perform migration for package statuses perform migration for package statuses
:param connection: database connection
:param paths: repository paths instance Args:
connection(Connection): database connection
paths(RepositoryPaths): repository paths instance
""" """
def insert_base(metadata: Package, last_status: BuildStatus) -> None: def insert_base(metadata: Package, last_status: BuildStatus) -> None:
connection.execute( connection.execute(

View File

@ -25,8 +25,10 @@ from ahriman.models.repository_paths import RepositoryPaths
def migrate_patches(connection: Connection, paths: RepositoryPaths) -> None: def migrate_patches(connection: Connection, paths: RepositoryPaths) -> None:
""" """
perform migration for patches perform migration for patches
:param connection: database connection
:param paths: repository paths instance Args:
connection(Connection): database connection
paths(RepositoryPaths): repository paths instance
""" """
root = paths.root / "patches" root = paths.root / "patches"
if not root.is_dir(): if not root.is_dir():

View File

@ -25,8 +25,10 @@ from ahriman.core.configuration import Configuration
def migrate_users_data(connection: Connection, configuration: Configuration) -> None: def migrate_users_data(connection: Connection, configuration: Configuration) -> None:
""" """
perform migration for users perform migration for users
:param connection: database connection
:param configuration: configuration instance Args:
connection(Connection): database connection
configuration(Configuration): configuration instance
""" """
for section in configuration.sections(): for section in configuration.sections():
for option, value in configuration[section].items(): for option, value in configuration[section].items():

View File

@ -35,14 +35,18 @@ class Migrations:
""" """
simple migration wrapper for the sqlite simple migration wrapper for the sqlite
idea comes from https://www.ash.dev/blog/simple-migration-system-in-sqlite/ idea comes from https://www.ash.dev/blog/simple-migration-system-in-sqlite/
:ivar connection: database connection
:ivar logger: class logger Attributes:
connection(Connection): database connection
logger(logging.Logger): class logger
""" """
def __init__(self, connection: Connection) -> None: def __init__(self, connection: Connection) -> None:
""" """
default constructor default constructor
:param connection: database connection
Args:
connection(Connection): database connection
""" """
self.connection = connection self.connection = connection
self.logger = logging.getLogger("database") self.logger = logging.getLogger("database")
@ -51,8 +55,12 @@ class Migrations:
def migrate(cls: Type[Migrations], connection: Connection) -> MigrationResult: def migrate(cls: Type[Migrations], connection: Connection) -> MigrationResult:
""" """
perform migrations implicitly perform migrations implicitly
:param connection: database connection
:return: current schema version Args:
connection(Connection): database connection
Returns:
MigrationResult: current schema version
""" """
return cls(connection).run() return cls(connection).run()
@ -61,6 +69,8 @@ class Migrations:
extract all migrations from the current package extract all migrations from the current package
idea comes from https://julienharbulot.com/python-dynamical-import.html idea comes from https://julienharbulot.com/python-dynamical-import.html
Returns:
List[Migration]: list of found migrations
""" """
migrations: List[Migration] = [] migrations: List[Migration] = []
package_dir = Path(__file__).resolve().parent package_dir = Path(__file__).resolve().parent
@ -77,7 +87,9 @@ class Migrations:
def run(self) -> MigrationResult: def run(self) -> MigrationResult:
""" """
perform migrations perform migrations
:return: current schema version
Return:
MigrationResult: current schema version
""" """
migrations = self.migrations() migrations = self.migrations()
current_version = self.user_version() current_version = self.user_version()
@ -118,7 +130,9 @@ class Migrations:
def user_version(self) -> int: def user_version(self) -> int:
""" """
get schema version from sqlite database get schema version from sqlite database
;return: current schema version
Returns:
int: current schema version
""" """
cursor = self.connection.execute("pragma user_version") cursor = self.connection.execute("pragma user_version")
current_version: int = cursor.fetchone()["user_version"] current_version: int = cursor.fetchone()["user_version"]

View File

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

View File

@ -32,7 +32,9 @@ class BuildOperations(Operations):
def build_queue_clear(self, package_base: Optional[str]) -> None: def build_queue_clear(self, package_base: Optional[str]) -> None:
""" """
remove packages from build queue remove packages from build queue
:param package_base: optional filter by package base
Args:
package_base(Optional[str]): optional filter by package base
""" """
def run(connection: Connection) -> None: def run(connection: Connection) -> None:
connection.execute( connection.execute(
@ -47,7 +49,9 @@ class BuildOperations(Operations):
def build_queue_get(self) -> List[Package]: def build_queue_get(self) -> List[Package]:
""" """
retrieve packages from build queue retrieve packages from build queue
:return: list of packages to be built
Return:
List[Package]: list of packages to be built
""" """
def run(connection: Connection) -> List[Package]: def run(connection: Connection) -> List[Package]:
return [ return [
@ -60,7 +64,9 @@ class BuildOperations(Operations):
def build_queue_insert(self, package: Package) -> None: def build_queue_insert(self, package: Package) -> None:
""" """
insert packages to build queue insert packages to build queue
:param package: package to be inserted
Args:
package(Package): package to be inserted
""" """
def run(connection: Connection) -> None: def run(connection: Connection) -> None:
connection.execute( connection.execute(

View File

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

View File

@ -35,8 +35,10 @@ class PackageOperations(Operations):
def _package_remove_package_base(connection: Connection, package_base: str) -> None: def _package_remove_package_base(connection: Connection, package_base: str) -> None:
""" """
remove package base information remove package base information
:param connection: database connection
:param package_base: package base name Args:
connection(Connection): database connection
package_base(str): package base name
""" """
connection.execute("""delete from package_statuses where package_base = :package_base""", connection.execute("""delete from package_statuses where package_base = :package_base""",
{"package_base": package_base}) {"package_base": package_base})
@ -47,9 +49,11 @@ class PackageOperations(Operations):
def _package_remove_packages(connection: Connection, package_base: str, current_packages: Iterable[str]) -> None: def _package_remove_packages(connection: Connection, package_base: str, current_packages: Iterable[str]) -> None:
""" """
remove packages belong to the package base remove packages belong to the package base
:param connection: database connection
:param package_base: package base name Args:
:param current_packages: current packages list which has to be left in database connection(Connection): database connection
package_base(str): package base name
current_packages(Iterable[str]): current packages list which has to be left in database
""" """
packages = [ packages = [
package package
@ -63,8 +67,10 @@ class PackageOperations(Operations):
def _package_update_insert_base(connection: Connection, package: Package) -> None: def _package_update_insert_base(connection: Connection, package: Package) -> None:
""" """
insert base package into table insert base package into table
:param connection: database connection
:param package: package properties Args:
connection(Connection): database connection
package(Package): package properties
""" """
connection.execute( connection.execute(
""" """
@ -81,8 +87,10 @@ class PackageOperations(Operations):
def _package_update_insert_packages(connection: Connection, package: Package) -> None: def _package_update_insert_packages(connection: Connection, package: Package) -> None:
""" """
insert packages into table insert packages into table
:param connection: database connection
:param package: package properties Args:
connection(Connection): database connection
package(Package): package properties
""" """
package_list = [] package_list = []
for name, description in package.packages.items(): for name, description in package.packages.items():
@ -108,9 +116,11 @@ class PackageOperations(Operations):
def _package_update_insert_status(connection: Connection, package_base: str, status: BuildStatus) -> None: def _package_update_insert_status(connection: Connection, package_base: str, status: BuildStatus) -> None:
""" """
insert base package status into table insert base package status into table
:param connection: database connection
:param package_base: package base name Args:
:param status: new build status connection(Connection): database connection
package_base(str): package base name
status(BuildStatus): new build status
""" """
connection.execute( connection.execute(
""" """
@ -126,8 +136,12 @@ class PackageOperations(Operations):
def _packages_get_select_package_bases(connection: Connection) -> Dict[str, Package]: def _packages_get_select_package_bases(connection: Connection) -> Dict[str, Package]:
""" """
select package bases from the table select package bases from the table
:param connection: database connection
:return: map of the package base to its descriptor (without packages themselves) Args:
connection(Connection): database connection
Returns:
Dict[str, Package]: map of the package base to its descriptor (without packages themselves)
""" """
return { return {
row["package_base"]: Package(row["package_base"], row["version"], row["aur_url"], {}) row["package_base"]: Package(row["package_base"], row["version"], row["aur_url"], {})
@ -138,9 +152,13 @@ class PackageOperations(Operations):
def _packages_get_select_packages(connection: Connection, packages: Dict[str, Package]) -> Dict[str, Package]: def _packages_get_select_packages(connection: Connection, packages: Dict[str, Package]) -> Dict[str, Package]:
""" """
select packages from the table select packages from the table
:param connection: database connection
:param packages: packages descriptor map Args:
:return: map of the package base to its descriptor including individual packages connection(Connection): database connection
packages(Dict[str, Package]): packages descriptor map
Returns:
Dict[str, Package]: map of the package base to its descriptor including individual packages
""" """
for row in connection.execute("""select * from packages"""): for row in connection.execute("""select * from packages"""):
if row["package_base"] not in packages: if row["package_base"] not in packages:
@ -152,8 +170,12 @@ class PackageOperations(Operations):
def _packages_get_select_statuses(connection: Connection) -> Dict[str, BuildStatus]: def _packages_get_select_statuses(connection: Connection) -> Dict[str, BuildStatus]:
""" """
select package build statuses from the table select package build statuses from the table
:param connection: database connection
:return: map of the package base to its status Args:
connection(Connection): database connection
Returns:
Dict[str, BuildStatus]: map of the package base to its status
""" """
return { return {
row["package_base"]: BuildStatus.from_json({"status": row["status"], "timestamp": row["last_updated"]}) row["package_base"]: BuildStatus.from_json({"status": row["status"], "timestamp": row["last_updated"]})
@ -163,7 +185,9 @@ class PackageOperations(Operations):
def package_remove(self, package_base: str) -> None: def package_remove(self, package_base: str) -> None:
""" """
remove package from database remove package from database
:param package_base: package base name
Args:
package_base(str): package base name
""" """
def run(connection: Connection) -> None: def run(connection: Connection) -> None:
self._package_remove_packages(connection, package_base, []) self._package_remove_packages(connection, package_base, [])
@ -174,8 +198,10 @@ class PackageOperations(Operations):
def package_update(self, package: Package, status: BuildStatus) -> None: def package_update(self, package: Package, status: BuildStatus) -> None:
""" """
update package status update package status
:param package: package properties
:param status: new build status Args:
package(Package): package properties
status(BuildStatus): new build status
""" """
def run(connection: Connection) -> None: def run(connection: Connection) -> None:
self._package_update_insert_base(connection, package) self._package_update_insert_base(connection, package)
@ -188,7 +214,9 @@ class PackageOperations(Operations):
def packages_get(self) -> List[Tuple[Package, BuildStatus]]: def packages_get(self) -> List[Tuple[Package, BuildStatus]]:
""" """
get package list and their build statuses from database get package list and their build statuses from database
:return: list of package properties and their statuses
Return:
List[Tuple[Package, BuildStatus]]: list of package properties and their statuses
""" """
def run(connection: Connection) -> Generator[Tuple[Package, BuildStatus], None, None]: def run(connection: Connection) -> Generator[Tuple[Package, BuildStatus], None, None]:
packages = self._packages_get_select_package_bases(connection) packages = self._packages_get_select_package_bases(connection)

View File

@ -31,16 +31,22 @@ class PatchOperations(Operations):
def patches_get(self, package_base: str) -> Optional[str]: def patches_get(self, package_base: str) -> Optional[str]:
""" """
retrieve patches for the package retrieve patches for the package
:param package_base: package base to search for patches
:return: plain text patch for the package Args:
package_base(str): package base to search for patches
Returns:
Optional[str]: plain text patch for the package
""" """
return self.patches_list(package_base).get(package_base) return self.patches_list(package_base).get(package_base)
def patches_insert(self, package_base: str, patch: str) -> None: def patches_insert(self, package_base: str, patch: str) -> None:
""" """
insert or update patch in database insert or update patch in database
:param package_base: package base to insert
:param patch: patch content Args:
package_base(str): package base to insert
patch(str): patch content
""" """
def run(connection: Connection) -> None: def run(connection: Connection) -> None:
connection.execute( connection.execute(
@ -59,8 +65,12 @@ class PatchOperations(Operations):
def patches_list(self, package_base: Optional[str]) -> Dict[str, str]: def patches_list(self, package_base: Optional[str]) -> Dict[str, str]:
""" """
extract all patches extract all patches
:param package_base: optional filter by package base
:return: map of package base to patch content Args:
package_base(Optional[str]): optional filter by package base
Returns:
Dict[str, str]: map of package base to patch content
""" """
def run(connection: Connection) -> Dict[str, str]: def run(connection: Connection) -> Dict[str, str]:
return { return {
@ -75,7 +85,9 @@ class PatchOperations(Operations):
def patches_remove(self, package_base: str) -> None: def patches_remove(self, package_base: str) -> None:
""" """
remove patch set remove patch set
:param package_base: package base to clear patches
Args:
package_base(str): package base to clear patches
""" """
def run(connection: Connection) -> None: def run(connection: Connection) -> None:
connection.execute( connection.execute(

View File

@ -44,8 +44,12 @@ class SQLite(AuthOperations, BuildOperations, PackageOperations, PatchOperations
def load(cls: Type[SQLite], configuration: Configuration) -> SQLite: def load(cls: Type[SQLite], configuration: Configuration) -> SQLite:
""" """
construct instance from configuration construct instance from configuration
:param configuration: configuration instance
:return: fully initialized instance of the database Args:
configuration(Configuration): configuration instance
Returns:
SQLite: fully initialized instance of the database
""" """
path = cls.database_path(configuration) path = cls.database_path(configuration)
database = cls(path) database = cls(path)
@ -56,15 +60,21 @@ class SQLite(AuthOperations, BuildOperations, PackageOperations, PatchOperations
def database_path(configuration: Configuration) -> Path: def database_path(configuration: Configuration) -> Path:
""" """
read database from configuration read database from configuration
:param configuration: configuration instance
:return: database path according to the configuration Args:
configuration(Configuration): configuration instance
Returns:
Path: database path according to the configuration
""" """
return configuration.getpath("settings", "database") return configuration.getpath("settings", "database")
def init(self, configuration: Configuration) -> None: def init(self, configuration: Configuration) -> None:
""" """
perform database migrations perform database migrations
:param configuration: configuration instance
Args:
configuration(Configuration): configuration instance
""" """
# custom types support # custom types support
sqlite3.register_adapter(dict, json.dumps) sqlite3.register_adapter(dict, json.dumps)

View File

@ -29,7 +29,9 @@ class BuildFailed(RuntimeError):
def __init__(self, package_base: str) -> None: def __init__(self, package_base: str) -> None:
""" """
default constructor default constructor
:param package_base: package base raised exception
Args:
package_base(str): package base raised exception
""" """
RuntimeError.__init__(self, f"Package {package_base} build failed, check logs for details") RuntimeError.__init__(self, f"Package {package_base} build failed, check logs for details")
@ -61,7 +63,9 @@ class InitializeException(RuntimeError):
def __init__(self, details: str) -> None: def __init__(self, details: str) -> None:
""" """
default constructor default constructor
:param details: details of the exception
Args:
details(str): details of the exception
""" """
RuntimeError.__init__(self, f"Could not load service: {details}") RuntimeError.__init__(self, f"Could not load service: {details}")
@ -74,7 +78,9 @@ class InvalidOption(ValueError):
def __init__(self, value: Any) -> None: def __init__(self, value: Any) -> None:
""" """
default constructor default constructor
:param value: option value
Args:
value(Any): option value
""" """
ValueError.__init__(self, f"Invalid or unknown option value `{value}`") ValueError.__init__(self, f"Invalid or unknown option value `{value}`")
@ -87,8 +93,10 @@ class InvalidPath(ValueError):
def __init__(self, path: Path, root: Path) -> None: def __init__(self, path: Path, root: Path) -> None:
""" """
default constructor default constructor
:param path: path which raised an exception
:param root: repository root (i.e. ahriman home) Args:
path(Path): path which raised an exception
root(Path): repository root (i.e. ahriman home)
""" """
ValueError.__init__(self, f"Path `{path}` does not belong to repository root `{root}`") ValueError.__init__(self, f"Path `{path}` does not belong to repository root `{root}`")
@ -101,7 +109,9 @@ class InvalidPackageInfo(RuntimeError):
def __init__(self, details: Any) -> None: def __init__(self, details: Any) -> None:
""" """
default constructor default constructor
:param details: error details
Args:
details(Any): error details
""" """
RuntimeError.__init__(self, f"There are errors during reading package information: `{details}`") RuntimeError.__init__(self, f"There are errors during reading package information: `{details}`")
@ -114,7 +124,9 @@ class MigrationError(RuntimeError):
def __init__(self, details: str) -> None: def __init__(self, details: str) -> None:
""" """
default constructor default constructor
:param details: error details
Args:
details(str): error details
""" """
RuntimeError.__init__(self, details) RuntimeError.__init__(self, details)
@ -127,7 +139,9 @@ class MissingArchitecture(ValueError):
def __init__(self, command: str) -> None: def __init__(self, command: str) -> None:
""" """
default constructor default constructor
:param command: command name which throws exception
Args:
command(str): command name which throws exception
""" """
ValueError.__init__(self, f"Architecture required for subcommand {command}, but missing") ValueError.__init__(self, f"Architecture required for subcommand {command}, but missing")
@ -140,7 +154,9 @@ class MultipleArchitectures(ValueError):
def __init__(self, command: str) -> None: def __init__(self, command: str) -> None:
""" """
default constructor default constructor
:param command: command name which throws exception
Args:
command(str): command name which throws exception
""" """
ValueError.__init__(self, f"Multiple architectures are not supported by subcommand {command}") ValueError.__init__(self, f"Multiple architectures are not supported by subcommand {command}")
@ -165,7 +181,9 @@ class SuccessFailed(ValueError):
def __init__(self, package_base: str) -> None: def __init__(self, package_base: str) -> None:
""" """
default constructor default constructor
:param package_base: package base name
Args:
package_base(str): package base name
""" """
ValueError.__init__(self, f"Package base {package_base} had status failed, but new status is success") ValueError.__init__(self, f"Package base {package_base} had status failed, but new status is success")
@ -190,7 +208,9 @@ class UnknownPackage(ValueError):
def __init__(self, package_base: str) -> None: def __init__(self, package_base: str) -> None:
""" """
default constructor default constructor
:param package_base: package base name
Args:
package_base(str): package base name
""" """
ValueError.__init__(self, f"Package base {package_base} is unknown") ValueError.__init__(self, f"Package base {package_base} is unknown")
@ -203,8 +223,10 @@ class UnsafeRun(RuntimeError):
def __init__(self, current_uid: int, root_uid: int) -> None: def __init__(self, current_uid: int, root_uid: int) -> None:
""" """
default constructor default constructor
:param current_uid: current user ID
:param root_uid: ID of the owner of root directory Args:
current_uid(int): current user ID
root_uid(int): ID of the owner of root directory
""" """
RuntimeError.__init__(self, f"Current UID {current_uid} differs from root owner {root_uid}. " RuntimeError.__init__(self, f"Current UID {current_uid} differs from root owner {root_uid}. "
f"Note that for the most actions it is unsafe to run application as different user." f"Note that for the most actions it is unsafe to run application as different user."

View File

@ -28,13 +28,17 @@ from ahriman.models.property import Property
class AurPrinter(StringPrinter): class AurPrinter(StringPrinter):
""" """
print content of the AUR package print content of the AUR package
:ivar package: AUR package description
Attributes:
package(AURPackage): AUR package description
""" """
def __init__(self, package: AURPackage) -> None: def __init__(self, package: AURPackage) -> None:
""" """
default constructor default constructor
:param package: AUR package description
Args:
package(AURPackage): AUR package description
""" """
StringPrinter.__init__(self, f"{package.name} {package.version} ({package.num_votes})") StringPrinter.__init__(self, f"{package.name} {package.version} ({package.num_votes})")
self.package = package self.package = package
@ -42,7 +46,9 @@ class AurPrinter(StringPrinter):
def properties(self) -> List[Property]: def properties(self) -> List[Property]:
""" """
convert content into printable data convert content into printable data
:return: list of content properties
Returns:
List[Property]: list of content properties
""" """
return [ return [
Property("Package base", self.package.package_base), Property("Package base", self.package.package_base),

View File

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

View File

@ -26,14 +26,18 @@ from ahriman.models.property import Property
class ConfigurationPrinter(StringPrinter): class ConfigurationPrinter(StringPrinter):
""" """
print content of the configuration section print content of the configuration section
:ivar values: configuration values dictionary
Attributes:
values(Dict[str, str]): configuration values dictionary
""" """
def __init__(self, section: str, values: Dict[str, str]) -> None: def __init__(self, section: str, values: Dict[str, str]) -> None:
""" """
default constructor default constructor
:param section: section name
:param values: configuration values dictionary Args:
section(str): section name
values(Dict[str, str]): configuration values dictionary
""" """
StringPrinter.__init__(self, f"[{section}]") StringPrinter.__init__(self, f"[{section}]")
self.values = values self.values = values
@ -41,7 +45,9 @@ class ConfigurationPrinter(StringPrinter):
def properties(self) -> List[Property]: def properties(self) -> List[Property]:
""" """
convert content into printable data convert content into printable data
:return: list of content properties
Returns:
List[Property]: list of content properties
""" """
return [ return [
Property(key, value, is_required=True) Property(key, value, is_required=True)

View File

@ -28,15 +28,19 @@ from ahriman.models.property import Property
class PackagePrinter(StringPrinter): class PackagePrinter(StringPrinter):
""" """
print content of the internal package object print content of the internal package object
:ivar package: package description
:ivar status: build status Attributes:
package(Package): package description
status(BuildStatus): build status
""" """
def __init__(self, package: Package, status: BuildStatus) -> None: def __init__(self, package: Package, status: BuildStatus) -> None:
""" """
default constructor default constructor
:param package: package description
:param status: build status Args:
package(Package): package description
status(BuildStatus): build status
""" """
StringPrinter.__init__(self, package.pretty_print()) StringPrinter.__init__(self, package.pretty_print())
self.package = package self.package = package
@ -45,7 +49,9 @@ class PackagePrinter(StringPrinter):
def properties(self) -> List[Property]: def properties(self) -> List[Property]:
""" """
convert content into printable data convert content into printable data
:return: list of content properties
Returns:
List[Property]: list of content properties
""" """
return [ return [
Property("Version", self.package.version, is_required=True), Property("Version", self.package.version, is_required=True),

View File

@ -30,9 +30,12 @@ class Printer:
def print(self, verbose: bool, log_fn: Callable[[str], None] = print, separator: str = ": ") -> None: def print(self, verbose: bool, log_fn: Callable[[str], None] = print, separator: str = ": ") -> None:
""" """
print content print content
:param verbose: print all fields
:param log_fn: logger function to log data Args:
:param separator: separator for property name and property value verbose(bool): print all fields
log_fn(Callable[[str]): logger function to log data
None]: (Default value = print)
separator(str, optional): separator for property name and property value (Default value = ": ")
""" """
if (title := self.title()) is not None: if (title := self.title()) is not None:
log_fn(title) log_fn(title)
@ -44,12 +47,16 @@ class Printer:
def properties(self) -> List[Property]: # pylint: disable=no-self-use def properties(self) -> List[Property]: # pylint: disable=no-self-use
""" """
convert content into printable data convert content into printable data
:return: list of content properties
Returns:
List[Property]: list of content properties
""" """
return [] return []
def title(self) -> Optional[str]: def title(self) -> Optional[str]:
""" """
generate entry title from content generate entry title from content
:return: content title if it can be generated and None otherwise
Returns:
Optional[str]: content title if it can be generated and None otherwise
""" """

View File

@ -29,6 +29,8 @@ class StatusPrinter(StringPrinter):
def __init__(self, status: BuildStatus) -> None: def __init__(self, status: BuildStatus) -> None:
""" """
default constructor default constructor
:param status: build status
Args:
status(BuildStatus): build status
""" """
StringPrinter.__init__(self, status.pretty_print()) StringPrinter.__init__(self, status.pretty_print())

View File

@ -30,13 +30,17 @@ class StringPrinter(Printer):
def __init__(self, content: str) -> None: def __init__(self, content: str) -> None:
""" """
default constructor default constructor
:param content: any content string
Args:
content(str): any content string
""" """
self.content = content self.content = content
def title(self) -> Optional[str]: def title(self) -> Optional[str]:
""" """
generate entry title from content generate entry title from content
:return: content title if it can be generated and None otherwise
Returns:
Optional[str]: content title if it can be generated and None otherwise
""" """
return self.content return self.content

View File

@ -27,15 +27,19 @@ from ahriman.models.property import Property
class UpdatePrinter(StringPrinter): class UpdatePrinter(StringPrinter):
""" """
print content of the package update print content of the package update
:ivar package: remote (new) package object
:ivar local_version: local version of the package if any Attributes:
package(Package): remote (new) package object
local_version(Optional[str]): local version of the package if any
""" """
def __init__(self, remote: Package, local_version: Optional[str]) -> None: def __init__(self, remote: Package, local_version: Optional[str]) -> None:
""" """
default constructor default constructor
:param remote: remote (new) package object
:param local_version: local version of the package if any Args:
remote(Package): remote (new) package object
local_version(Optional[str]): local version of the package if any
""" """
StringPrinter.__init__(self, remote.base) StringPrinter.__init__(self, remote.base)
self.package = remote self.package = remote
@ -44,6 +48,8 @@ class UpdatePrinter(StringPrinter):
def properties(self) -> List[Property]: def properties(self) -> List[Property]:
""" """
convert content into printable data convert content into printable data
:return: list of content properties
Returns:
List[Property]: list of content properties
""" """
return [Property(self.local_version, self.package.version, is_required=True)] return [Property(self.local_version, self.package.version, is_required=True)]

View File

@ -27,13 +27,17 @@ from ahriman.models.user import User
class UserPrinter(StringPrinter): class UserPrinter(StringPrinter):
""" """
print properties of user print properties of user
:ivar user: stored user
Attributes:
user(User): stored user
""" """
def __init__(self, user: User) -> None: def __init__(self, user: User) -> None:
""" """
default constructor default constructor
:param user: user to print
Args:
user(User): user to print
""" """
StringPrinter.__init__(self, user.username) StringPrinter.__init__(self, user.username)
self.user = user self.user = user
@ -41,6 +45,8 @@ class UserPrinter(StringPrinter):
def properties(self) -> List[Property]: def properties(self) -> List[Property]:
""" """
convert content into printable data convert content into printable data
:return: list of content properties
Returns:
List[Property]: list of content properties
""" """
return [Property("role", self.user.access.value, is_required=True)] return [Property("role", self.user.access.value, is_required=True)]

View File

@ -29,15 +29,19 @@ from ahriman.models.result import Result
class Console(Report): class Console(Report):
""" """
html report generator html report generator
:ivar use_utf: print utf8 symbols instead of ASCII
Attributes:
use_utf(bool): print utf8 symbols instead of ASCII
""" """
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None: def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
""" """
default constructor default constructor
:param architecture: repository architecture
:param configuration: configuration instance Args:
:param section: settings section name architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
""" """
Report.__init__(self, architecture, configuration) Report.__init__(self, architecture, configuration)
self.use_utf = configuration.getboolean(section, "use_utf", fallback=True) self.use_utf = configuration.getboolean(section, "use_utf", fallback=True)
@ -45,8 +49,10 @@ class Console(Report):
def generate(self, packages: Iterable[Package], result: Result) -> None: def generate(self, packages: Iterable[Package], result: Result) -> None:
""" """
generate report for the specified packages generate report for the specified packages
:param packages: list of packages to generate report
:param result: build result Args:
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
""" """
for package in result.success: for package in result.success:
BuildPrinter(package, is_success=True, use_utf=self.use_utf).print(verbose=True) BuildPrinter(package, is_success=True, use_utf=self.use_utf).print(verbose=True)

View File

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

View File

@ -29,16 +29,20 @@ from ahriman.models.result import Result
class HTML(Report, JinjaTemplate): class HTML(Report, JinjaTemplate):
""" """
html report generator html report generator
:ivar report_path: output path to html report
:ivar template_path: path to template for full package list Attributes:
report_path(Path): output path to html report
template_path(Path): path to template for full package list
""" """
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None: def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
""" """
default constructor default constructor
:param architecture: repository architecture
:param configuration: configuration instance Args:
:param section: settings section name architecture(str): repository architecture
configuration(Configuration): configuration instance
section(str): settings section name
""" """
Report.__init__(self, architecture, configuration) Report.__init__(self, architecture, configuration)
JinjaTemplate.__init__(self, section, configuration) JinjaTemplate.__init__(self, section, configuration)
@ -49,8 +53,10 @@ class HTML(Report, JinjaTemplate):
def generate(self, packages: Iterable[Package], result: Result) -> None: def generate(self, packages: Iterable[Package], result: Result) -> None:
""" """
generate report for the specified packages generate report for the specified packages
:param packages: list of packages to generate report
:param result: build result Args:
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
""" """
html = self.make_html(Result(success=packages), self.template_path) html = self.make_html(Result(success=packages), self.template_path)
self.report_path.write_text(html) self.report_path.write_text(html)

View File

@ -35,11 +35,11 @@ class JinjaTemplate:
It uses jinja2 templates for report generation, the following variables are allowed: It uses jinja2 templates for report generation, the following variables are allowed:
homepage - link to homepage, string, optional * homepage - link to homepage, string, optional
link_path - prefix fo packages to download, string, required * link_path - prefix fo packages to download, string, required
has_package_signed - True in case if package sign enabled, False otherwise, required * has_package_signed - True in case if package sign enabled, False otherwise, required
has_repo_signed - True in case if repository database sign enabled, False otherwise, required * has_repo_signed - True in case if repository database sign enabled, False otherwise, required
packages - sorted list of packages properties, required * packages - sorted list of packages properties, required
* architecture, string * architecture, string
* archive_size, pretty printed size, string * archive_size, pretty printed size, string
* build_date, pretty printed datetime, string * build_date, pretty printed datetime, string
@ -52,21 +52,24 @@ class JinjaTemplate:
* name, string * name, string
* url, string * url, string
* version, string * version, string
pgp_key - default PGP key ID, string, optional * pgp_key - default PGP key ID, string, optional
repository - repository name, string, required * repository - repository name, string, required
:ivar homepage: homepage link if any (for footer) Attributes:
:ivar link_path: prefix fo packages to download homepage(Optional[str]): homepage link if any (for footer)
:ivar name: repository name link_path(str): prefix fo packages to download
:ivar default_pgp_key: default PGP key name(str): repository name
:ivar sign_targets: targets to sign enabled in configuration default_pgp_key(Optional[str]): default PGP key
sign_targets(Set[SignSettings]): targets to sign enabled in configuration
""" """
def __init__(self, section: str, configuration: Configuration) -> None: def __init__(self, section: str, configuration: Configuration) -> None:
""" """
default constructor default constructor
:param section: settings section name
:param configuration: configuration instance Args:
section(str): settings section name
configuration(Configuration): configuration instance
""" """
self.link_path = configuration.get(section, "link_path") self.link_path = configuration.get(section, "link_path")
@ -79,8 +82,10 @@ class JinjaTemplate:
def make_html(self, result: Result, template_path: Path) -> str: def make_html(self, result: Result, template_path: Path) -> str:
""" """
generate report for the specified packages generate report for the specified packages
:param result: build result
:param template_path: path to jinja template Args:
result(Result): build result
template_path(Path): path to jinja template
""" """
# idea comes from https://stackoverflow.com/a/38642558 # idea comes from https://stackoverflow.com/a/38642558
loader = jinja2.FileSystemLoader(searchpath=template_path.parent) loader = jinja2.FileSystemLoader(searchpath=template_path.parent)

View File

@ -33,16 +33,20 @@ from ahriman.models.result import Result
class Report: class Report:
""" """
base report generator base report generator
:ivar architecture: repository architecture
:ivar configuration: configuration instance Attributes:
:ivar logger: class logger architecture(str): repository architecture
configuration(Configuration): configuration instance
logger(logging.Logger): class logger
""" """
def __init__(self, architecture: str, configuration: Configuration) -> None: def __init__(self, architecture: str, configuration: Configuration) -> None:
""" """
default constructor default constructor
:param architecture: repository architecture
:param configuration: configuration instance Args:
architecture(str): repository architecture
configuration(Configuration): configuration instance
""" """
self.logger = logging.getLogger("root") self.logger = logging.getLogger("root")
self.architecture = architecture self.architecture = architecture
@ -52,10 +56,14 @@ class Report:
def load(cls: Type[Report], architecture: str, configuration: Configuration, target: str) -> Report: def load(cls: Type[Report], architecture: str, configuration: Configuration, target: str) -> Report:
""" """
load client from settings load client from settings
:param architecture: repository architecture
:param configuration: configuration instance Args:
:param target: target to generate report aka section name (e.g. html) architecture(str): repository architecture
:return: client according to current settings configuration(Configuration): configuration instance
target(str): target to generate report aka section name (e.g. html)
Returns:
Report: client according to current settings
""" """
section, provider_name = configuration.gettype(target, architecture) section, provider_name = configuration.gettype(target, architecture)
provider = ReportSettings.from_option(provider_name) provider = ReportSettings.from_option(provider_name)
@ -76,15 +84,22 @@ class Report:
def generate(self, packages: Iterable[Package], result: Result) -> None: def generate(self, packages: Iterable[Package], result: Result) -> None:
""" """
generate report for the specified packages generate report for the specified packages
:param packages: list of packages to generate report
:param result: build result Args:
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
""" """
def run(self, packages: Iterable[Package], result: Result) -> None: def run(self, packages: Iterable[Package], result: Result) -> None:
""" """
run report generation run report generation
:param packages: list of packages to generate report
:param result: build result Args:
packages(Iterable[Package]): list of packages to generate report
result(Result): build result
Raises:
ReportFailed: in case of any report unmatched exception
""" """
try: try:
self.generate(packages, result) self.generate(packages, result)

View File

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

View File

@ -33,7 +33,12 @@ class Cleaner(Properties):
def packages_built(self) -> List[Path]: def packages_built(self) -> List[Path]:
""" """
get list of files in built packages directory get list of files in built packages directory
:return: list of filenames from the directory
Returns:
List[Path]: list of filenames from the directory
Raises:
NotImplementedError: not implemented method
""" """
raise NotImplementedError raise NotImplementedError

View File

@ -39,23 +39,39 @@ class Executor(Cleaner):
def load_archives(self, packages: Iterable[Path]) -> List[Package]: def load_archives(self, packages: Iterable[Path]) -> List[Package]:
""" """
load packages from list of archives load packages from list of archives
:param packages: paths to package archives
:return: list of read packages Args:
packages(Iterable[Path]): paths to package archives
Returns:
List[Package]: list of read packages
Raises:
NotImplementedError: not implemented method
""" """
raise NotImplementedError raise NotImplementedError
def packages(self) -> List[Package]: def packages(self) -> List[Package]:
""" """
generate list of repository packages generate list of repository packages
:return: list of packages properties
Returns:
List[Package]: list of packages properties
Raises:
NotImplementedError: not implemented method
""" """
raise NotImplementedError raise NotImplementedError
def process_build(self, updates: Iterable[Package]) -> Result: def process_build(self, updates: Iterable[Package]) -> Result:
""" """
build packages build packages
:param updates: list of packages properties to build
:return: `packages_built` Args:
updates(Iterable[Package]): list of packages properties to build
Returns:
Result: build result
""" """
def build_single(package: Package, local_path: Path) -> None: def build_single(package: Package, local_path: Path) -> None:
self.reporter.set_building(package.base) self.reporter.set_building(package.base)
@ -82,8 +98,12 @@ class Executor(Cleaner):
def process_remove(self, packages: Iterable[str]) -> Path: def process_remove(self, packages: Iterable[str]) -> Path:
""" """
remove packages from list remove packages from list
:param packages: list of package names or bases to remove
:return: path to repository database Args:
packages(Iterable[str]): list of package names or bases to remove
Returns:
Path: path to repository database
""" """
def remove_base(package_base: str) -> None: def remove_base(package_base: str) -> None:
try: try:
@ -126,8 +146,11 @@ class Executor(Cleaner):
def process_report(self, targets: Optional[Iterable[str]], result: Result) -> None: def process_report(self, targets: Optional[Iterable[str]], result: Result) -> None:
""" """
generate reports generate reports
:param targets: list of targets to generate reports. Configuration option will be used if it is not set
:param result: build result Args:
targets(Optional[Iterable[str]]): list of targets to generate reports. Configuration option will be used
if it is not set
result(Result): build result
""" """
if targets is None: if targets is None:
targets = self.configuration.getlist("report", "target") targets = self.configuration.getlist("report", "target")
@ -138,8 +161,11 @@ class Executor(Cleaner):
def process_sync(self, targets: Optional[Iterable[str]], built_packages: Iterable[Package]) -> None: def process_sync(self, targets: Optional[Iterable[str]], built_packages: Iterable[Package]) -> None:
""" """
process synchronization to remote servers process synchronization to remote servers
:param targets: list of targets to sync. Configuration option will be used if it is not set
:param built_packages: list of packages which has just been built Args:
targets(Optional[Iterable[str]]): list of targets to sync. Configuration option will be used
if it is not set
built_packages(Iterable[Package]): list of packages which has just been built
""" """
if targets is None: if targets is None:
targets = self.configuration.getlist("upload", "target") targets = self.configuration.getlist("upload", "target")
@ -150,8 +176,12 @@ class Executor(Cleaner):
def process_update(self, packages: Iterable[Path]) -> Result: def process_update(self, packages: Iterable[Path]) -> Result:
""" """
sign packages, add them to repository and update repository database sign packages, add them to repository and update repository database
:param packages: list of filenames to run
:return: path to repository database Args:
packages(Iterable[Path]): list of filenames to run
Returns:
Result: path to repository database
""" """
def update_single(name: Optional[str], base: str) -> None: def update_single(name: Optional[str], base: str) -> None:
if name is None: if name is None:

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