diff --git a/docs/source/_ext/add_dependencies.py b/docs/source/_ext/add_dependencies.py index 471b5c632f..2a7b4891a4 100644 --- a/docs/source/_ext/add_dependencies.py +++ b/docs/source/_ext/add_dependencies.py @@ -12,10 +12,9 @@ base_path = os.path.abspath( sys.path.insert(0, base_path) -from platypush.common.reflection import Integration # noqa -from platypush.utils import get_plugin_name_by_class, import_file # noqa -from platypush.utils.mock import auto_mocks # noqa -from platypush.utils.mock.modules import mock_imports # noqa +from platypush.common.reflection import Integration # noqa: E402 +from platypush.utils import get_plugin_name_by_class # noqa: E402 +from platypush.utils.mock import auto_mocks # noqa: E402 class IntegrationEnricher: diff --git a/platypush/plugins/application/__init__.py b/platypush/plugins/application/__init__.py index 85a30559eb..94a7469160 100644 --- a/platypush/plugins/application/__init__.py +++ b/platypush/plugins/application/__init__.py @@ -1,7 +1,15 @@ +import inspect +import pathlib +import subprocess from typing import Optional + from platypush.commands import CommandStream, RestartCommand, StopCommand +from platypush.common.db import override_definitions from platypush.config import Config from platypush.plugins import Plugin, action +from platypush.utils import get_backend_class_by_name, get_plugin_class_by_name +from platypush.utils.manifest import Manifest +from platypush.utils.mock import auto_mocks class ApplicationPlugin(Plugin): @@ -29,3 +37,34 @@ class ApplicationPlugin(Plugin): Restart the application. """ CommandStream(self._ctrl_sock).write(RestartCommand()) + + @action + def install(self, extension: str): + """ + Install the dependencies of an extension. + + :param extension: Extension name. For plugins, it will be the plugin + name (e.g. ``light.hue`` or ``music.mpd``); for backend, the name will + be prefixed by ``backend.`` (e.g. ``backend.http`` or ``backend.tcp``). + """ + getter = get_plugin_class_by_name + if extension.startswith('backend.'): + extension = extension[len('backend.') :] + getter = get_backend_class_by_name + + with auto_mocks(), override_definitions(): + ext = getter(extension) + + assert ext, f'Could not find extension {extension}' + manifest_file = str(pathlib.Path(inspect.getfile(ext)).parent / 'manifest.yaml') + install_cmds = list( + Manifest.from_file(manifest_file).install.to_install_commands() + ) + + if not install_cmds: + self.logger.info('No extra requirements found for extension %s', extension) + return + + for cmd in install_cmds: + self.logger.info('> %s', cmd) + subprocess.check_call(cmd, shell=True)