From ab668430425c5284cdd061ce080fbdaea41dacb0 Mon Sep 17 00:00:00 2001 From: Greg Heinrich Date: Thu, 21 Jul 2016 14:32:21 +0200 Subject: [PATCH] Add support for plug-ins --- digits/extensions/data/__init__.py | 37 +++++++++++------ digits/extensions/data/imageGradients/data.py | 8 ++++ digits/extensions/data/interface.py | 8 ++++ digits/extensions/view/__init__.py | 40 ++++++++++++------- digits/extensions/view/imageGradients/view.py | 8 ++++ digits/extensions/view/interface.py | 8 ++++ docs/BuildDigits.md | 7 ++++ setup.py | 9 +++++ 8 files changed, 97 insertions(+), 28 deletions(-) create mode 100644 setup.py diff --git a/digits/extensions/data/__init__.py b/digits/extensions/data/__init__.py index 9e53b9413..772b2773c 100644 --- a/digits/extensions/data/__init__.py +++ b/digits/extensions/data/__init__.py @@ -1,15 +1,22 @@ # Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. from __future__ import absolute_import +import copy +from pkg_resources import iter_entry_points + from . import imageGradients from . import objectDetection -data_extensions = [ - # Set show=True if extension should be shown by default - # on DIGITS home page. These defaults can be changed by - # editing DIGITS config option 'data_extension_list' - {'class': imageGradients.DataIngestion, 'show': False}, - {'class': objectDetection.DataIngestion, 'show': True}, + +# Entry point group (this is the key we use to register and +# find installed plug-ins) +GROUP = "digits.plugins.data" + + +# built-in extensions +builtin_data_extensions = [ + imageGradients.DataIngestion, + objectDetection.DataIngestion, ] @@ -17,17 +24,21 @@ def get_extensions(show_all=False): """ return set of data data extensions """ - return [extension['class'] - for extension in data_extensions - if show_all or extension['show']] + extensions = copy.copy(builtin_data_extensions) + # find installed extension plug-ins + for entry_point in iter_entry_points(group=GROUP, name=None): + extensions.append(entry_point.load()) + + return [extension + for extension in extensions + if show_all or extension.get_default_visibility()] def get_extension(extension_id): """ return extension associated with specified extension_id """ - for extension in data_extensions: - extension_class = extension['class'] - if extension_class.get_id() == extension_id: - return extension_class + for extension in get_extensions(show_all=True): + if extension.get_id() == extension_id: + return extension return None diff --git a/digits/extensions/data/imageGradients/data.py b/digits/extensions/data/imageGradients/data.py index 4c3b772ac..1fa9593c0 100644 --- a/digits/extensions/data/imageGradients/data.py +++ b/digits/extensions/data/imageGradients/data.py @@ -45,6 +45,14 @@ def encode_entry(self, entry): def get_category(): return "Images" + @staticmethod + def get_default_visibility(): + """ + Return whether to show extension in GUI (can be overridden through + DIGITS configuration options) + """ + return False + @staticmethod @override def get_id(): diff --git a/digits/extensions/data/interface.py b/digits/extensions/data/interface.py index 1fe346dda..32a5fd346 100644 --- a/digits/extensions/data/interface.py +++ b/digits/extensions/data/interface.py @@ -36,6 +36,14 @@ def get_dataset_form(): """ raise NotImplementedError + @staticmethod + def get_default_visibility(): + """ + Return whether to show extension in GUI (can be overridden through + DIGITS configuration options) + """ + return True + @staticmethod def get_dataset_template(form): """ diff --git a/digits/extensions/view/__init__.py b/digits/extensions/view/__init__.py index ad1537b99..4d9b55cbb 100644 --- a/digits/extensions/view/__init__.py +++ b/digits/extensions/view/__init__.py @@ -1,18 +1,24 @@ # Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. from __future__ import absolute_import +import copy +from pkg_resources import iter_entry_points + from . import boundingBox from . import imageGradients from . import rawData -view_extensions = [ - # Set show=True if extension should be shown by default - # in the 'Select Visualization Method' dialog. These defaults - # can be changed by editing DIGITS config option - # 'view_extension_list' - {'class': boundingBox.Visualization, 'show': True}, - {'class': imageGradients.Visualization, 'show': False}, - {'class': rawData.Visualization, 'show': True}, + +# Entry point group (this is the key we use to register and +# find installed plug-ins) +GROUP = "digits.plugins.view" + + +# built-in extensions +builtin_view_extensions = [ + boundingBox.Visualization, + imageGradients.Visualization, + rawData.Visualization, ] @@ -27,17 +33,21 @@ def get_extensions(show_all=False): """ return set of data data extensions """ - return [extension['class'] - for extension in view_extensions - if show_all or extension['show']] + extensions = copy.copy(builtin_view_extensions) + # find installed extension plug-ins + for entry_point in iter_entry_points(group=GROUP, name=None): + extensions.append(entry_point.load()) + + return [extension + for extension in extensions + if show_all or extension.get_default_visibility()] def get_extension(extension_id): """ return extension associated with specified extension_id """ - for extension in view_extensions: - extension_class = extension['class'] - if extension_class.get_id() == extension_id: - return extension_class + for extension in get_extensions(show_all=True): + if extension.get_id() == extension_id: + return extension return None diff --git a/digits/extensions/view/imageGradients/view.py b/digits/extensions/view/imageGradients/view.py index 32de6aab7..81286da4b 100644 --- a/digits/extensions/view/imageGradients/view.py +++ b/digits/extensions/view/imageGradients/view.py @@ -69,6 +69,14 @@ def get_config_template(form): context = {'form': form} return (template, context) + @staticmethod + def get_default_visibility(): + """ + Return whether to show extension in GUI (can be overridden through + DIGITS configuration options) + """ + return False + @staticmethod def get_id(): return digits.extensions.data.imageGradients.data.DataIngestion.get_id() diff --git a/digits/extensions/view/interface.py b/digits/extensions/view/interface.py index 8d16e1e57..843c74ebe 100644 --- a/digits/extensions/view/interface.py +++ b/digits/extensions/view/interface.py @@ -32,6 +32,14 @@ def get_config_template(form): """ raise NotImplementedError + @staticmethod + def get_default_visibility(): + """ + Return whether to show extension in GUI (can be overridden through + DIGITS configuration options) + """ + return True + def get_header_template(self): """ This returns the content to be rendered at the top of the result diff --git a/docs/BuildDigits.md b/docs/BuildDigits.md index e115a3997..422488fc0 100644 --- a/docs/BuildDigits.md +++ b/docs/BuildDigits.md @@ -40,6 +40,13 @@ Several PyPI packages need to be installed: sudo pip install -r $DIGITS_HOME/requirements.txt ``` +# [Optional] Enable support for plug-ins + +DIGITS needs to be installed to enable loading data and visualization plug-ins: +``` +sudo pip install $DIGITS_HOME +``` + # Starting the server You can run DIGITS in two modes: diff --git a/setup.py b/setup.py new file mode 100644 index 000000000..3ed13e632 --- /dev/null +++ b/setup.py @@ -0,0 +1,9 @@ +from setuptools import setup, find_packages + +import digits + +setup( + name = "digits", + packages = find_packages(), + version = digits.__version__ +)