diff --git a/senpy/extensions.py b/senpy/extensions.py index 2cc5247..36e2654 100644 --- a/senpy/extensions.py +++ b/senpy/extensions.py @@ -22,11 +22,18 @@ import importlib import logging import traceback import yaml -import pip +import subprocess logger = logging.getLogger(__name__) +def log_subprocess_output(process): + for line in iter(process.stdout.readline, b''): + logger.info('%r', line) + for line in iter(process.stderr.readline, b''): + logger.error('%r', line) + + class Senpy(object): """ Default Senpy extension for Flask """ @@ -333,13 +340,19 @@ class Senpy(object): def _install_deps(cls, info=None): requirements = info.get('requirements', []) if requirements: - pip_args = [] + pip_args = ['pip'] pip_args.append('install') pip_args.append('--use-wheel') for req in requirements: pip_args.append(req) logger.info('Installing requirements: ' + str(requirements)) - pip.main(pip_args) + process = subprocess.Popen(pip_args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + log_subprocess_output(process) + exitcode = process.wait() + if exitcode != 0: + raise Error("Dependencies not properly installed") @classmethod def _load_module(cls, name, root): diff --git a/senpy/models.py b/senpy/models.py index 9ce3f66..2025d31 100644 --- a/senpy/models.py +++ b/senpy/models.py @@ -357,5 +357,8 @@ class Error(SenpyMixin, Exception): def __delattr__(self, key): delattr(self._error, key) + def __str__(self): + return str(self.to_JSON(with_context=False)) + register(Error, 'error') diff --git a/tests/test_extensions.py b/tests/test_extensions.py index ba854e3..0523789 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -61,6 +61,19 @@ class ExtensionsTest(TestCase): assert len(self.senpy.plugins) >= 3 assert self.senpy.plugins["Sleep"].is_activated + def test_installing_nonexistent(self): + """ Fail if the dependencies cannot be met """ + info = { + 'name': 'TestPipFail', + 'module': 'dummy', + 'description': None, + 'requirements': ['IAmMakingThisPackageNameUpToFail'], + 'version': 0 + } + root = os.path.join(self.dir, 'plugins', 'dummy_plugin') + with self.assertRaises(Error): + name, module = self.senpy._load_plugin_from_info(info, root=root) + def test_disabling(self): """ Disabling a plugin """ self.senpy.deactivate_all(sync=True)