Skip to content

Commit

Permalink
Automatically install and update module dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
TheLastProject committed Mar 23, 2017
1 parent ff338f9 commit 4a27bca
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- Install dependencies automatically if the module provides a requirements.txt file

## [0.5] - 2017-03-22
### API changes
- Remove Action.notify_message and Action.notify_error, which are synonyms for add_message and add_error
Expand Down
35 changes: 35 additions & 0 deletions pext/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import getopt
import json
import os
import pip
import signal
import sys
import threading
Expand Down Expand Up @@ -426,6 +427,7 @@ def __init__(self, config_retriever: ConfigRetriever) -> None:
"""Initialize the module manager."""
self.config_retriever = config_retriever
self.module_dir = os.path.join(self.config_retriever.get_setting('config_path'), 'modules')
self.module_dependencies_dir = os.path.join(self.config_retriever.get_setting('config_path'), 'module_dependencies')
self.logger = None # type: Optional[Logger]

@staticmethod
Expand Down Expand Up @@ -456,6 +458,15 @@ def _log_error(self, message: str) -> None:
else:
print(message)

def _pip_install(self, module_dir_name: str) -> None:
"""Install module dependencies using pip."""
pip.main(['install',
'--upgrade',
'--target',
os.path.join(self.module_dependencies_dir, module_dir_name),
'-r',
os.path.join(self.module_dir, module_dir_name, 'requirements.txt')])

def bind_logger(self, logger: Logger) -> str:
"""Connect a logger to the module manager.
Expand All @@ -475,6 +486,11 @@ def load_module(self, window: 'Window', module: Dict) -> bool:
module_dir = ModuleManager.add_prefix(module['name']).replace('.', '_')
module_name = ModuleManager.remove_prefix(module['name'])

# Append module dependencies path if not yet appended
module_dependencies_path = os.path.join(self.config_retriever.get_setting('config_path'), 'module_dependencies', module_dir)
if module_dependencies_path not in sys.path:
sys.path.append(module_dependencies_path)

# Prepare viewModel and context
vm = ViewModel()
module_context = QQmlContext(window.context)
Expand All @@ -492,6 +508,10 @@ def load_module(self, window: 'Window', module: Dict) -> bool:
except ImportError as e1:
self._log_error(
"Failed to load module {} from {}: {}".format(module_name, module_dir, e1))

# Remove module dependencies path
sys.path.remove(module_dependencies_path)

return False

Module = getattr(module_import, 'Module')
Expand Down Expand Up @@ -637,6 +657,11 @@ def install_module(self, url: str, verbose=False, interactive=True) -> bool:

return False

if verbose:
self._log('Installing dependencies for {}'.format(module_name))

self._pip_install(dir_name)

if verbose:
self._log('Installed {}'.format(module_name))

Expand All @@ -659,6 +684,11 @@ def uninstall_module(self, module_name: str, verbose=False) -> bool:

return False

try:
rmtree(os.path.join(self.module_dependencies_dir, dir_name))
except FileNotFoundError:
pass

if verbose:
self._log('Uninstalled {}'.format(module_name))

Expand All @@ -682,6 +712,11 @@ def update_module(self, module_name: str, verbose=False) -> bool:

return False

if verbose:
self._log('Updating dependencies for {}'.format(module_name))

self._pip_install(dir_name)

if verbose:
self._log('Updated {}'.format(module_name))

Expand Down

0 comments on commit 4a27bca

Please sign in to comment.