platypush/docs/source/_ext/add_dependencies.py
Fabio Manganiello c3337ccc6c
[#311] Docs deps autogen sphinx plugin.
Added an `add_dependencies` plugin to the Sphinx build process that
parses the manifest files of the scanned backends and plugins and
automatically generates the documentation for the required dependencies
and triggered events.

This means that those dependencies are no longer required to be listed
in the docstring of the class itself.

Also in this commit:

- Black/LINT for some integrations that hadn't been touched in a long
  time.

- Deleted some leftovers from previous refactors (deprecated
  `backend.mqtt`, `backend.zwave.mqtt`, `backend.http.request.rss`).

- Deleted deprecated `inotify` backend - replaced by `file.monitor` (see
  #289).
2023-09-24 17:00:08 +02:00

100 lines
2.5 KiB
Python

import os
import re
import yaml
from sphinx.application import Sphinx
def add_events(source: list[str], manifest: dict, idx: int) -> int:
events = manifest.get('events', [])
if not events:
return idx
source.insert(
idx,
'Triggered events\n----------------\n\n'
+ '\n'.join(f'\t- :class:`{event}`' for event in events)
+ '\n\n',
)
return idx + 1
def add_install_deps(source: list[str], manifest: dict, idx: int) -> int:
install_deps = manifest.get('install', {})
install_cmds = {
'pip': 'pip install',
'Alpine': 'apk add',
'Arch Linux': 'pacman -S',
'Debian': 'apt install',
'Fedora': 'yum install',
}
parsed_deps = {
'pip': install_deps.get('pip', []),
'Alpine': install_deps.get('apk', []),
'Arch Linux': install_deps.get('pacman', []),
'Debian': install_deps.get('apt', []),
'Fedora': install_deps.get('dnf', install_deps.get('yum', [])),
}
if not any(parsed_deps.values()):
return idx
source.insert(idx, 'Dependencies\n^^^^^^^^^^^^\n\n')
idx += 1
for env, deps in parsed_deps.items():
if deps:
install_cmd = install_cmds[env]
source.insert(
idx,
f'**{env}**\n\n'
+ '.. code-block:: bash\n\n\t'
+ f'{install_cmd} '
+ ' '.join(deps)
+ '\n\n',
)
idx += 1
return idx
def parse_dependencies(_: Sphinx, doc: str, source: list[str]):
if not (source and re.match(r'^platypush/(backend|plugins)/.*', doc)):
return
src = [src.split('\n') for src in source][0]
if len(src) < 3:
return
base_path = os.path.abspath(
os.path.join(os.path.dirname(os.path.relpath(__file__)), '..', '..', '..')
)
manifest_file = os.path.join(
base_path,
*doc.split(os.sep)[:-1],
*doc.split(os.sep)[-1].split('.'),
'manifest.yaml',
)
if not os.path.isfile(manifest_file):
return
with open(manifest_file) as f:
manifest: dict = yaml.safe_load(f).get('manifest', {})
idx = add_install_deps(src, manifest, idx=3)
add_events(src, manifest, idx=idx)
source[0] = '\n'.join(src)
def setup(app: Sphinx):
app.connect('source-read', parse_dependencies)
return {
'version': '0.1',
'parallel_read_safe': True,
'parallel_write_safe': True,
}