diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 87697387..72250b26 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -26,6 +26,6 @@ sphinx: # Optional but recommended, declare the Python requirements required # to build your documentation # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html -#python: -# install: -# - requirements: Nymph/Scarab/documentation/cpp/requirements.txt +python: + install: + - requirements: doc/requirements.txt diff --git a/doc/conf.py b/doc/conf.py index 5c4c92ab..a518c54d 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -58,6 +58,7 @@ #'sphinxcontrib.apidoc', 'sphinx.ext.napoleon', #'sphinxarg.ext', + 'sphinx.ext.intersphinx', ] todo_include_todos = True @@ -77,27 +78,39 @@ master_doc = 'index' # General information about the project. -project = 'Dripline-Python' -copyright = '2020, The Dripline-Python Authors' +project = 'dripline-python' +copyright = '2024, The dripline-python Authors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # -# The short X.Y version. -#version = #'0.0.1' -#import pkg_resources +this_version = 'v?.?.?' try: - import dripline, subprocess - version = dripline.__version__#pkg_resources.require("dripline")[0].version -# The full version, including alpha/beta/rc tags. - release = subprocess.check_output(['git', 'describe', '--long']).decode('utf-8').strip() -except Exception as e: - print("failure importing dripline") - #print("error message is:\n{}".format(e.message)) - version = "unknown" - release = "unknown" -print('version/release are: {}/{}'.format(version,release)) + #this_version = check_output(['git', 'describe', '--abbrev=0', '--tags']).decode('utf-8').strip() + this_version = subprocess.check_output(['git', 'describe', '--tags']).decode('utf-8').strip() +except: + pass +version = this_version +release = this_version + + +# Intersphinx details +intersphinx_mapping = { + "scarab": ("https://scarab.readthedocs.io/en/stable/", None), + "dripline": ("https://dripline.readthedocs.io/en/latest/", None), + "dripline-cpp": ("https://dripline-cpp.readthedocs.io/en/latest/", None), + "controls-guide": ("https://controls-guide.readthedocs.io/en/latest/", None), + "dl-home": ("https://driplineorggithubio.readthedocs.io/en/latest/", None), +} + +# We recommend adding the following config value. +# Sphinx defaults to automatically resolve *unresolved* labels using all your Intersphinx mappings. +# This behavior has unintended side-effects, namely that documentations local references can +# suddenly resolve to an external location. +# See also: +# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#confval-intersphinx_disabled_reftypes +intersphinx_disabled_reftypes = ["*"] # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -142,18 +155,16 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'alabaster' +html_theme = 'furo' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = { - 'fixed_sidebar': True, - 'sidebar_collapse': True, - 'github_user': 'driplineorg', - 'github_repo': 'dripline-python', - 'badge_branch': 'dl3/develop', - 'github_button': True, + 'source_repository': 'https://github.com/driplineorg/dripline-python', + 'source_branch': 'main', + 'source_directory': 'doc/', + 'navigation_with_keys': True, } # Add any paths that contain custom themes here, relative to this directory. diff --git a/doc/dl_serve.rst b/doc/dl_serve.rst index 6094e783..9f4de045 100644 --- a/doc/dl_serve.rst +++ b/doc/dl_serve.rst @@ -13,7 +13,7 @@ Use ``> dl-serve [options] [keyword arguments]`` -The user provides a configuration file. +The user typically provides a configuration file with the ``-c`` (``--config``) option. Options ------- @@ -22,72 +22,149 @@ Options -h,--help Print this help message and exit -c,--config TEXT:FILE Config file filename - --verbosity UINT Global logger verosity + --config-encoding TEXT Config file encoding + -v,--verbose Increase verbosity + -q,--quiet Decrease verbosity -V,--version Print the version message and exit + -u,--username TEXT Specify the username for the rabbitmq broker + --password TEXT Specify a password for the rabbitmq broker -- NOTE: this will be plain text on the command line and may end up in your command history! + --password-file TEXT Specify a file (e.g. a secrets file) to be read in as the rabbitmq broker password + --auth-file TEXT Set the authentication file path -b,--broker TEXT Set the dripline broker address -p,--port UINT Set the port for communication with the dripline broker - --auth-file TEXT Set the authentication file path --requests-exchange TEXT Set the name of the requests exchange --alerts-exchange TEXT Set the name of the alerts exchange --max-payload UINT Set the maximum payload size (in bytes) - --loop-timeout-msdripline.loop-timeout-ms UINT - --message-wait-msdripline.message-wait-ms UINT --heartbeat-routing-key TEXT Set the first token of heartbeat routing keys: [token].[origin] + --max-connection-attempts UINT + Maximum number of times to attempt to connect to the broker + --loop-timeout-msloop_timeout_ms UINT + --message-wait-msmessage_wait_ms UINT --heartbeat-interval-s UINT Set the interval between heartbeats in s -Authentication -============== +Configuration +============= + +For information applicable to all dripline application configurations, see :doc:`dripline-cpp:configuration`. + +The full configuration for a service, with default values, is: + +.. code-block:: yaml + + dripline_mesh : + alerts_exchange : alerts + broker : localhost + broker_port : 5672 + heartbeat_routing_key : heartbeat + max_connection_attempts : 10 + max_payload_size : 10000 + requests_exchange : requests + + enable_scheduling : true + heartbeat_interval_s : 60 + loop_timeout_ms : 1000 + message_wait_ms : 1000 + + name : dlpy_service + module: Service + module_path: + + endpoints: + - name: + module: + module_path: + + - name: + module: + module_path: + + <...> + +Any paramters for which you want to use the default values can be left out of the configuration file and do not +need to be specified in other ways (e.g. with a command-line option). The parameters in angle brackets (``<>``) +do not have default values because they'll be specific to the service and will need to be provided by the user. + +When starting the service, ``module`` and ``module_path`` are used to create the service object, while +the remaining configuration information is provided as keyword arguments to the service's ``__init__()`` function. -Communication with the RabbitMQ broker requires the broker address and port, and user/password authentication. +.. note:: + As a matter of convention, dripline-python classes all accept extra keyword arguments to their ``__init__`` functions, usting the ``**kwargs`` argument packing. + These are passed along when the class calls the ``__init__`` of its base class(es), allowing the complete set of keyword arguments to be provided. + +.. note:: + Whenever possible, dripline-python classes provide default values to keyword arguments so that derrived classes are able to be created given the above convention. + All required arguments of the class and its base classes must be passed to the ``__init__`` of any class (for example, ``Endpoint``, which is a base of all available classes, requires the ``name`` keyword argument, meaning that every instance node must have a name argument). + +For a complete example of configuring a service, please see the :doc:`controls-guide:guides/first-mesh`. + +Module and Module Path +---------------------- + +The class used by the application is specified as the ``module`` in the configuration. The default is ``dripline.core.Service``, +and the class used should be ``Service`` or a class derived from it. +Any service class in the ``dripline`` namespace can be used, including those in ``dripline.core`` and ``dripline.implementations`` within the +dripline-python repo, and ``dripline.extensions`` for any :doc:`Dripline extension modules`. -.. TODO update the link to use "latest" symbolic link, or main/develop, when that is available +For modules outside of the ``dripline`` namespace, the module path can be provided with the ``module_path`` key. +If present, this file is searched first and so it will take precedent if the ``module`` has the same name +as a class which is part of dripline-python or any extension. -See `Authentication in the dripline-cpp docs `_ for information on how to specify the broker and authentication information. +Endpoints +--------- + +Endpoints are provided as a list of endpoint configurations under the ``endpoints`` key. As with the service, +the ``module`` and ``module_path`` parameters are used to create each endpoint object, and the remaining parameters +in each block is provided to the respective endpoint's ``__init__()`` function. Configuration File -================== +------------------ -The configuration is used to define what components are part of the service. -These elements all exist within the top-level ``runtime-config`` node within the configuration file, which is described here. -If not already familiar, you're encouraged to review the `dripline-cpp core library documentation `_ for descriptions of roles of the base classes and their relationships. +For most uses of ``dl-serve``, most of the configuration information (other than the defaults) will be provided in a configuration file. -.. TODO again, update this link to a more generic branch, when available. +.. tip:: + To maximize the ability to reuse configuration files in different meshes, we suggest that mesh configuration details be provided in a :ref:`:ref: .dripline_mesh.yaml `` file, + and the service configuration file be specific to the particular service. -The ``runtime-config`` node is built up out of nodes which each describe a class instance. -The details for defining instance nodes is below -The top level of the runtime configuration must be exactly one instance which is either a ``Service`` or a class derrived from it. -It follows the description below for any instance node, but has an extra reserved keyword (``endpoints``), which contains an array of instance nodes which will be added as children of the ``Service`` instance, these can be instance of any ``Endpoint``-derrived class. +Here is an example service configuration file: -For a more complete example of writing a configuration file and using it, see the `first mesh tutorial in the driplineorg controls guide`_ +.. code-block:: yaml -Instance node description -------------------------- -Each instance node defines an object which will be created and configured as part of the service. -There are a number of reserved keywords, which are removed from the node before creation. -The rest of the node is unpacked into the named arguments of the ``__init__`` method of the class when it is created. -The reserved keywords are + name: my_store + module: Service + endpoints: + - name: peaches + module: KeyValueStore + calibration: '2*{}' + initial_value: 0.75 + log_interval: 10 + get_on_set: True + log_on_set: True + - name: chips + module: KeyValueStore + calibration: 'times3({})' + initial_value: 1.75 + - name: waffles + module: KeyValueStore + calibration: '1.*{}' + initial_value: 4.00 -.. glossary:: +Parameter Keywords +------------------ - module - Specifies the name of the class to create an instance of. - The application will search for a class with this name in the following namespaces in order and create the first one it finds: +For the most part, any YAML- or JSON-valid key name can be used for a configuration parameter key, and it has to match the +keyword argument key in the relevant class's ``__init__()`` function. - #. the source file provided in the ``module_path``, if provided - #. the extensions namespace or any namespaces within the extensions namespace (this is not recursive beyond that level) - #. the dripline.implementations namespace - #. the dripline.core namespace +There are several reserved keywords: - module_path - Path to an extra source file containing class implementation for the module. - If present, this file is searched first and so it will take precidents if the ``module`` has the same name as a class which is part of dripline-python +* ``name`` -- every endpoint (and service, since a service is an endpoint) has a name parameter that must be unique across the mesh. +* ``module`` -- the class name that will be built +* ``module_path`` -- an optional parameter to specify the path to the Python module containing the class, if it's not within the ``dripline`` namespace. -.. note:: - As a matter of convention, dripline-python classes all accept extra keyword arguments to their ``__init__`` functions, usting the ``**kwargs`` argument packing. - These are passed along when the class calls the ``__init__`` of its base class(es), allowing the complete set of keyword arguments to be provided. +Authentication +============== -.. note:: - Whenever possible, dripline-python classes provide default values to keyword arguments so that derrived classes are able to be created given the above convention. - All required arguments of the class and its base classes must be passed to the ``__init__`` of any class (for example, ``Endpoint``, which is a base of all available classes, requires the ``name`` keyword argument, meaning that every instance node must have a name argument). +Communication with the RabbitMQ broker requires user/password authentication. + +See :doc:`dripline-cpp:authentication` for information on how to specify the authentication information. diff --git a/doc/extending.rst b/doc/extending.rst index b99f5725..844bd0ec 100644 --- a/doc/extending.rst +++ b/doc/extending.rst @@ -5,17 +5,19 @@ Extending Dripline Dripline-python can be conveniently extended using the namespace plugin method. The controls-guide repository includes an example set of files that can be copied into a new repository to create an extension to the ``dripline`` namespace. Please see the -`controls-guide documentation `_ +:doc:`controls-guide documentation `_ to follow a walkthrough that will implement a new dripline extension. Adding a Service Class ====================== +A new service class can be derived from ``Service`` or any of the service classes from ``dripline.implementations``. + Adding an Endpoint Class ======================== There are some situations in which you will need to create your own endpoint class to add functionality that's not -available in the the ``core`` or ``implementations`` sub-packages. A new endpoing class can be derived from +available in the the ``core`` or ``implementations`` sub-packages. A new endpoint class can be derived from ``Endpoint``, ``Entity``, or any of the endpoint classes from ``dripline.implementations``. Adding ``CMD`` Handlers diff --git a/doc/getting_started.rst b/doc/getting_started.rst index 045d84e7..c5106dc1 100644 --- a/doc/getting_started.rst +++ b/doc/getting_started.rst @@ -34,16 +34,16 @@ which is inside the build directory), you will need to know the location of the for the dripline-python build below (usually ``[prefix]/lib/cmake/Dripline``). As an alternative, you could make a system-wide install at ``/usr/local``. -Dripline-cpp currently requires (all versions are minima): C++17 (via gcc or clang), CMake v3.5, -Boost 1.46, rapidjson 1.0, yaml-cpp, and rabbitmq-c. -Everything should be available from standard package managers. +Dripline-cpp currently requires (all versions are minima): C++17 (via gcc or clang), CMake v3.12, +Boost 1.46, rapidjson 1.0, yaml-cpp, rabbitmq-c, and quill. +Everything should be available from standard package managers, except Quill, which is not in apt (for Ubuntu/Debian). The Python wrapping of C++ code is done with `Pybind11 `_. Version 2.6.0 or higher is required. It can be installed from most package managers or by following their instructions. You will need `CMake `_ to build the C++ wrappers. -Version 3.5 or higher is required. +Version 3.12 or higher is required. It can be installed from most package managers or by following their instructions. Note that this is not included as a dependency in the Python installation process. See ``pyproject.toml`` for more details. diff --git a/doc/index.rst b/doc/index.rst index fdaea221..7d94d53f 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -4,7 +4,7 @@ Welcome to Dripline-python's documentation! =========================================== -Dripline-python builds on `dripline-cpp `_ to provide useful +Dripline-python builds on :doc:`dripline-cpp ` to provide useful implementations for assembly of a dripline mesh. The package is split into three components (each a namespace): ``core``, for extending ``dripline-cpp`` with a pythonic interface and adding the most basic and generic features; ``implementations``, for ready to use classes that enable generic support for various @@ -12,6 +12,9 @@ devices, resources, and behaviors; and ``extensions``, for enabling plugins via There is also a commandline tool, ``dl-serve``, which enables ``YAML``-based configurations to define the components in a running service. +Table of contents +================= + .. toctree:: :maxdepth: 2 @@ -21,6 +24,14 @@ the components in a running service. API Documentation contribute +.. toctree:: + :caption: Links: + + Dripline Docs + Guides and Walkthroughs + Protocol + C++ Implementation + Python Implementation Indices and tables ================== diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 00000000..bf08b344 --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1,2 @@ +# Webpage theme +furo