205 lines
9.3 KiB
ReStructuredText
205 lines
9.3 KiB
ReStructuredText
Development
|
|
===========
|
|
If you want to help with the development of AppDaemon all assistance is gratefully received! Here are a few things you can do to help.
|
|
|
|
Installing a beta version
|
|
-------------------------
|
|
For the adventurous among you, it is possible to run a pre-release version to get a preview of changes before they are released as part of a stable build.
|
|
**Please be aware**: use it at your own risk. Although we try to keep things consistent and functional, we can't guarantee that things won't break.
|
|
However, feedback from brave souls running this pre-release version is always gratefully received!
|
|
|
|
Also, note, that to run a development version you should be using the *Pip install method*. Docker builds are created for dev too, but there is no hass.io support.
|
|
|
|
There are 2 different ways of installing via Pip. If we are running a beta, we will have a number of specific milestone builds.
|
|
The beta version will not install by default using the standard ``pip`` command but can be installed if its exact version is specified to `pip``:
|
|
|
|
.. code:: console
|
|
|
|
$ pip install appdaemon==<beta version>
|
|
|
|
Setting up a development environment
|
|
------------------------------------
|
|
If you want to run the latest code available in the ``dev`` branch, or if you want to run a local version of the application separate from your existing installation, take the following steps:
|
|
|
|
Clone the repository
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
Download a copy of the ``dev`` branch. Run the following command to clone the ``dev`` branch of the official `AppDaemon repository <https://github.com/AppDaemon/appdaemon.git>`_:
|
|
|
|
.. code:: console
|
|
|
|
$ git clone -b dev https://github.com/AppDaemon/appdaemon.git
|
|
|
|
This will create a directory called ``appdaemon``: this is your local Git repository, and all subsequent commands will need to be run from inside it.
|
|
|
|
Requirements
|
|
^^^^^^^^^^^^
|
|
Firstly, it is recommended to create a Python virtual environment (VE) and enable it. The best practice here is to use a VE specifically for the development version.
|
|
In some cases, it is possible that the ``dev`` branch may have updated dependencies that will be incompatible with the latest stable release, and may break it.
|
|
|
|
Make sure you are in the ``appdaemon`` project directory, then run the following commands:
|
|
|
|
1. Install the project dependencies, along with the development dependencies
|
|
|
|
.. code:: console
|
|
|
|
$ pip install -r dev-requirements.txt
|
|
|
|
1. Setup `pre-commit hooks <https://pre-commit.com>`_. This will make sure that modified files are linted and formatted before every commit.
|
|
|
|
.. code:: console
|
|
|
|
$ pre-commit install
|
|
|
|
Running the application
|
|
^^^^^^^^^^^^^^^^^^^^^^^
|
|
Now that you have a local copy of the source code, the next step is to run AppDaemon.
|
|
|
|
Copy the default configuration file (edit it if you need to tweak some settings):
|
|
|
|
.. code:: console
|
|
|
|
$ cp conf/appdaemon.yaml.example conf/appdaemon.yaml
|
|
|
|
Start the application:
|
|
|
|
.. code:: console
|
|
|
|
$ python -m appdaemon -c conf/
|
|
|
|
In most cases, it is possible to share configuration directories with other AppDaemon instances.
|
|
However, you must be aware of AppDaemon apps that use new features as they will likely cause errors for the other pre-existing version.
|
|
It is recommended to use an entirely separate configuration directory for your development environment.
|
|
|
|
Getting the latest changes
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
When there are updates on the ``dev`` branch and you want to pull over the latest changes, run the following command from the ``appdaemon`` directory:
|
|
|
|
.. code:: console
|
|
|
|
$ git pull
|
|
|
|
You can then immediately run the latest version with the commands previously detailed.
|
|
|
|
Building a distribution package
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
To build a Python distribution package (*wheel*), run the following command:
|
|
|
|
.. code:: console
|
|
|
|
$ python -m build
|
|
|
|
It will output the result of the build inside a ``dist/`` folder.
|
|
|
|
The package can be installed directly via pip:
|
|
|
|
.. code:: console
|
|
|
|
$ pip install dist/appdaemon*.whl
|
|
|
|
Project structure
|
|
-----------------
|
|
|
|
The Python project follows the conventional PEP 621, using a ``pyproject.toml`` to define its metadata.
|
|
The repository is divided into various folder:
|
|
|
|
appdaemon
|
|
source code of the Python package
|
|
docs
|
|
source code from which this documentation is built
|
|
tests
|
|
unit tests written with ``pytest``
|
|
conf
|
|
configuration directory, containing some sample files
|
|
|
|
Dependencies management
|
|
^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
This project is published as a Python package, and following the `PEP 631 <https://peps.python.org/pep-0631/>`_ convention
|
|
the dependencies are declared as part of the ``pyproject.toml`` file.
|
|
However since this project is run as an application, as a `recommended practice in Python development <https://caremad.io/posts/2013/07/setup-vs-requirement/>`_, its should clearly specify the version of dependencies the application has been built and tested with,
|
|
to ensure a consistent deployment environment across multiple systems.
|
|
|
|
For this reason, the ``requirements.txt`` files are used to **pin** all the dependencies (both direct and indirect ones) that the application needs, specifying their exact version.
|
|
There are multiple files, each specifying a subset of dependencies (as defined under the ``[project.optional-dependencies]`` key in ``pyproject.toml``)
|
|
|
|
requirements.txt
|
|
The runtime dependencies needed at runtime for AppDaemon
|
|
dev-requirements.txt
|
|
The dependencies needed for a local development environment
|
|
doc-requirements.txt
|
|
The dependencies needed to build the documentation with Sphinx
|
|
|
|
These files are auto-generated using ``pip-compile``, provided by the `pip-tools <https://github.com/jazzband/pip-tools/>`_ package.
|
|
It uses the ``pyproject.toml`` as the source from which to read the project dependencies. The generated files should not be manually changed.
|
|
Each file has the ``pip-compile`` command used to generated them as a reference.
|
|
|
|
The runtime ``requirements.txt`` file is fundamental for efficiently building the ``Docker`` images: thanks to the Docker build cache,
|
|
the dependencies are only installed the first time in the build process, and are re-used from the Docker cache in subsequent builds.
|
|
This improves dramatically the build times, especially when there is the need to compile native dependencies.
|
|
See :ref:`Docker build` for more information.
|
|
|
|
.. _Docker build:
|
|
|
|
Docker build
|
|
^^^^^^^^^^^^
|
|
|
|
To locally build the container, it is required to have installed at least *Docker Engine 23.0*, since it enables `Docker BuildKit <https://docs.docker.com/build/buildkit/>`_ by default,
|
|
with all its useful features used in this build process.
|
|
|
|
- First it is necessary to build the AppDaemon Python package in the project directory (it will then be used as part of the Docker build stage).
|
|
|
|
.. code:: console
|
|
|
|
$ python -m build
|
|
|
|
- Then invoke the usual the docker build command:
|
|
|
|
.. code:: console
|
|
|
|
$ docker build -t appdaemon .
|
|
|
|
|
|
The Docker build makes use of the `multi-stage build <https://docs.docker.com/build/building/multi-stage/>`_ capabilities of Docker.
|
|
This is necessary since the *arm/v6* and *arm/v7* architectures do not provide Python *wheels* for this architectures of the **orjson** and **uvloop** packages, required by this project.
|
|
|
|
For this reason the build is divided in multiple *stages*: a *builder* stage and a *runtime* stage:
|
|
|
|
- The **builder** stage is used to install compile-time dependencies such as ``gcc`` and ``rust`` (to compile C extensions of Python dependencies), in addition to all the dependencies defined in the ``requirements.txt``.
|
|
|
|
By copying only the ``requirements.txt``, **only the dependencies** of AppDameon are installed, so if there is no change in them between two subsequent Docker builds, Docker caches this layer and skip this step.
|
|
- The **runtime stage** copies the built Python packages from the previous stage and install the AppDaemon package in the container, along with its startup scripts and files.
|
|
|
|
Pull Requests
|
|
-------------
|
|
|
|
If you would like to improve AppDaemon, we are pleased to receive Pull Requests in `the official AppDaemon repository <https://github.com/AppDaemon/appdaemon>`_.
|
|
|
|
Please note, if some documentation is required to make sense of the PR, the PR will not be accepted without it.
|
|
|
|
Working on the documentation
|
|
----------------------------
|
|
|
|
Assistance with the docs is always welcome, whether its fixing typos and incorrect information or reorganizing and adding to the docs to make them more helpful.
|
|
To work on the docs, submit a pull request with the changes, and I
|
|
will review and merge them in the usual way.
|
|
I use `Read the Docs <https://readthedocs.org/>`_ to build and host the documentation pages.
|
|
You can easily preview your edits locally, by running the following command:
|
|
|
|
If not already done, install the development dependencies locally.
|
|
The following command downloads and install the optional dependencies, as defined in the `pyproject.toml` file:
|
|
|
|
.. code:: console
|
|
|
|
$ pip install -r doc-requirements.txt
|
|
|
|
From the project's root directory, run the following command:
|
|
|
|
.. code:: console
|
|
|
|
$ sphinx-autobuild --host=0.0.0.0 docs/ docs/_build/html
|
|
|
|
Sphinx will take a minute or so to build the current version of the docs, and it will then be available on local port 8000
|
|
(e.g., http://localhost:8000).
|
|
As you make changes, sphinx will automatically detects them and updates the browser page in real-time.
|
|
When you finish your edit, you can stop the server via ``Ctrl-C``.
|