mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-06-28 06:41:43 +00:00
feat: use split packages (#135)
* move argument parsers to handlers themselves
* use hatchling instead of flit
* Revert "use hatchling instead of flit"
This reverts commit d18d146d79
.
* add package-splitt script
* replace simplify walk method
* split packages
* explicitly install packages
* separate support triggers from main package
* add docs examples
* sort actions
* docs update
* add metapackage
* review fixes
This commit is contained in:
51
docs/advanced-usage/handlers.rst
Normal file
51
docs/advanced-usage/handlers.rst
Normal file
@ -0,0 +1,51 @@
|
||||
Writing own handler
|
||||
===================
|
||||
|
||||
It is possible to extend the application by adding own custom commands. To do so it is required to implement class, which derives from ``ahriman.application.handlers.handler.Handler`` and put it to the ``ahriman.application.handlers`` package. The class later will be loaded automatically and included to each command run.
|
||||
|
||||
Let's imagine, that the new class implements ``help-web``, which prints server information to the stdout. To do so, we need to implement base ``ahriman.application.handlers.handler.Handler.run`` method which is entry point for all subcommands:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
|
||||
|
||||
class HelpWeb(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
# load application instance
|
||||
# report is set to True to make sure that web client is loaded
|
||||
application = Application(repository_id, configuration, report=True)
|
||||
# extract web client
|
||||
client = application.repository.reporter
|
||||
|
||||
# send request to the server
|
||||
response = client.make_request("GET", f"{client.address}/api/v1/info")
|
||||
result = response.json()
|
||||
print(result)
|
||||
|
||||
The main functionality of the class is already described, but command is still not available yet. To do so, it is required to set ``arguments`` property, which is the list of the functions, each of them which takes argument parser object, creates new subcommand and returns the modified parser, e.g.:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import argparse
|
||||
|
||||
from ahriman.application.handlers.handler import SubParserAction
|
||||
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def set_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
parser = root.add_parser("help-web", help="get web server status",
|
||||
description="request server info and print it to stdout")
|
||||
|
||||
arguments = set_parser
|
||||
|
||||
In addition, ``ahriman.application.handlers.handler.Handler.ALLOW_MULTI_ARCHITECTURE_RUN`` can be set to ``False`` in order to disable multiprocess run (e.g. in case if there are conflicting operations, like writting to stdout).
|
||||
|
||||
Save the file above as ``/usr/lib/python3.12/site-packages/ahriman/application/handlers/help_web.py`` (replace ``python3.12`` with actual python version) and you are set.
|
||||
|
||||
For more examples and details, please check builtin handlers and classes documentations.
|
@ -1,6 +1,12 @@
|
||||
Advanced usage
|
||||
==============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
handlers
|
||||
views
|
||||
|
||||
Depending on the goal the package can be used in different ways. Nevertheless, in the most cases you will need some basic classes
|
||||
|
||||
.. code-block:: python
|
41
docs/advanced-usage/views.rst
Normal file
41
docs/advanced-usage/views.rst
Normal file
@ -0,0 +1,41 @@
|
||||
Writing own API endpoint
|
||||
========================
|
||||
|
||||
The web service loads views dynamically, thus it is possible to add custom API endpoint or even web page. The view must be derived from ``ahriman.web.views.base.BaseView`` and should implement desired HTTP methods. The API specification will be also loaded automatically if available, but optional. The implementation must be saved into the ``ahriman.web.views`` package
|
||||
|
||||
Let's consider example of API endpoint which always returns 204 with no response:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aiohttp.web import Response, HTTPNoContent
|
||||
|
||||
from ahriman.web.views.base import BaseView
|
||||
|
||||
class PingView(BaseView):
|
||||
|
||||
async def get(self) -> Response:
|
||||
# do nothing, just raise 204 response
|
||||
# check public methods of the BaseView class for all available controls
|
||||
raise HTTPNoContent
|
||||
|
||||
The ``get()`` method can be decorated by ``aiohttp_apispec`` methods, but we will leave it for a self-study, please, consider to check examples of usages in the main package.
|
||||
|
||||
In order to view to be added to the route list correctly, few more properties are required to be set. First of all, it is required to specify ``ROUTES`` (list of strings), which contains list of all available routes, e.g.:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
...
|
||||
|
||||
ROUTES = ["/api/v1/ping"]
|
||||
|
||||
In addition, it is also recommended to specify permission level for using this endpoint. Since this endpoint neither does anything nor returns sensitive information, it can be set to ``UserAccess.Unauthorized``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
...
|
||||
|
||||
GET_PERMISSION = UserAccess.Unauthorized
|
||||
|
||||
That's all. Just save the file as ``/usr/lib/python3.12/site-packages/ahriman/web/views/ping.py`` (replace ``python3.12`` with actual python version) and restart web server.
|
||||
|
||||
For more examples and details, please check builtin handlers and classes documentations.
|
@ -228,6 +228,14 @@ ahriman.application.handlers.triggers module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.triggers\_support module
|
||||
-----------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.application.handlers.triggers_support
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.unsafe\_commands module
|
||||
----------------------------------------------------
|
||||
|
||||
|
@ -36,6 +36,14 @@ ahriman.core.exceptions module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.module\_loader module
|
||||
----------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.module_loader
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.spawn module
|
||||
-------------------------
|
||||
|
||||
|
@ -18,7 +18,7 @@ Full dependency diagram:
|
||||
``ahriman.application`` package
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This package contains application (aka executable) related classes and everything for it. It also contains package called ``ahriman.application.handlers`` in which all available subcommands are described as separated classes derived from the base ``ahriman.application.handlers.Handler`` class.
|
||||
This package contains application (aka executable) related classes and everything for it. It also contains package called ``ahriman.application.handlers`` in which all available subcommands are described as separated classes derived from the base ``ahriman.application.handlers.handler.Handler`` class.
|
||||
|
||||
``ahriman.application.application.Application`` (god class) is used for any interaction from parsers with repository. It is divided into multiple traits by functions (package related and repository related) in the same package.
|
||||
|
||||
@ -52,8 +52,10 @@ This package contains everything required for the most of application actions an
|
||||
This package also provides some generic functions and classes which may be used by other packages:
|
||||
|
||||
* ``ahriman.core.exceptions`` provides custom exceptions.
|
||||
* ``ahriman.core.module_loader`` provides ``implementations`` method which can be used for dynamic classes load. In particular, this method is used for web views and application handlers loading.
|
||||
* ``ahriman.core.spawn.Spawn`` is a tool which can spawn another ``ahriman`` process. This feature is used by web application.
|
||||
* ``ahriman.core.tree`` is a dependency tree implementation.
|
||||
* ``ahriman.core.types`` are an additional global types for mypy checks.
|
||||
|
||||
``ahriman.models`` package
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -436,6 +438,9 @@ REST API supports only JSON data.
|
||||
Different APIs are separated into different packages:
|
||||
|
||||
* ``ahriman.web.views.api`` not a real API, but some views which provide OpenAPI support.
|
||||
* ``ahriman.web.views.*.auditlog`` provides event log API.
|
||||
* ``ahriman.web.views.*.distributed`` is an API for builders interaction for multi-node setup.
|
||||
* ``ahriman.web.views.*.packages`` contains views which provide information about existing packages.
|
||||
* ``ahriman.web.views.*.service`` provides views for application controls.
|
||||
* ``ahriman.web.views.*.status`` package provides REST API for application reporting.
|
||||
* ``ahriman.web.views.*.user`` package provides login and logout methods which can be called without authorization.
|
||||
|
@ -311,6 +311,12 @@ Automatic worker nodes discovery
|
||||
|
||||
Instead of setting ``${build:workers}`` option explicitly it is also possible to configure services to load worker list dynamically. To do so, the ``ahriman.core.distributed.WorkerLoaderTrigger`` and ``ahriman.core.distributed.WorkerTrigger`` must be used for **master** and **worker** nodes respectively. See recipes for more details.
|
||||
|
||||
Those triggers have to be installed as a separate package:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S ahriman-triggers
|
||||
|
||||
Known limitations
|
||||
"""""""""""""""""
|
||||
|
||||
|
@ -13,7 +13,7 @@ TL;DR
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S ahriman
|
||||
yay -S ahriman-core
|
||||
ahriman -a x86_64 -r aur service-setup --packager "ahriman bot <ahriman@example.com>"
|
||||
systemctl enable --now ahriman@x86_64-aur.timer
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
Maintenance packages
|
||||
--------------------
|
||||
|
||||
Those features require extensions package to be installed before, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S ahriman-triggers
|
||||
|
||||
Generate keyring package
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -5,11 +5,11 @@ How to setup web service
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
#.
|
||||
Install dependencies:
|
||||
Install web service:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S --asdeps python-aiohttp python-aiohttp-jinja2 python-aiohttp-apispec>=3.0.0 python-aiohttp-cors
|
||||
yay -S ahriman-web
|
||||
|
||||
#.
|
||||
Configure service:
|
||||
|
@ -36,6 +36,6 @@ Contents
|
||||
faq/index
|
||||
migrations/index
|
||||
architecture
|
||||
advanced-usage
|
||||
advanced-usage/index
|
||||
triggers
|
||||
modules
|
||||
|
@ -2,7 +2,7 @@ Initial setup
|
||||
=============
|
||||
|
||||
#.
|
||||
Install package as usual.
|
||||
Install package(s) as usual. At least, ``ahriman-core`` package is required; other features can be installed separately. Alternatively, it is possible to install meta-package, which includes everything.
|
||||
#.
|
||||
Change settings if required, see :doc:`configuration reference <configuration>` for more details.
|
||||
#.
|
||||
|
Reference in New Issue
Block a user