Skip to content

Commit 5386923

Browse files
committed
Merge pull request #1 from sdelements/feature/graceful_failure
Make plugins fail gracefully
2 parents b71f65a + ab2bc42 commit 5386923

File tree

1 file changed

+41
-21
lines changed

1 file changed

+41
-21
lines changed

yantra/manager.py

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,19 @@ class PluginContainer(object):
2424

2525
def __init__(self, plugin_type):
2626
self._plugins = []
27+
self._errors = {}
2728
self.plugin_type = plugin_type
2829

30+
@property
31+
def errors(self):
32+
# clear errors from the last time we called get_plugins
33+
self._errors = {}
34+
35+
# attempt to load the plugins and populate errors
36+
self.get_plugins()
37+
38+
return self._errors
39+
2940
def register_plugin(self, plugin_cls):
3041
"""Register instance of the plugin class"""
3142
self._plugins.append(plugin_cls())
@@ -47,8 +58,8 @@ def _get_modules(self):
4758
modname, ext = os.path.splitext(filename)
4859

4960
if ext == ".py":
50-
filename, path, desc = imp.find_module(modname, [directory_path])
51-
plugin_modules.append((modname, filename, path, desc,))
61+
fp, path, desc = imp.find_module(modname, [directory_path])
62+
plugin_modules.append((modname, fp, path, desc,))
5263

5364
return plugin_modules
5465

@@ -63,24 +74,29 @@ def get_plugins(self):
6374
self._plugins = []
6475

6576
for plugin_module in modules:
66-
modname, filename, path, desc = plugin_module
77+
modname, fp, path, desc = plugin_module
6778

68-
if filename:
79+
try:
6980
# load the module and look for classes
70-
module = imp.load_module(modname, filename, path, desc)
71-
classes_in_module = inspect.getmembers(module, inspect.isclass)
81+
module = imp.load_module(modname, fp, path, desc)
82+
except Exception as e:
83+
error_msg = e.__class__.__name__ + ': ' + e.message
84+
self._errors[fp.name] = error_msg
85+
continue
86+
87+
classes_in_module = inspect.getmembers(module, inspect.isclass)
7288

73-
for cls in classes_in_module:
74-
cls = cls[1]
89+
for cls in classes_in_module:
90+
cls = cls[1]
7591

76-
# ignore if it's the base plugin class
77-
if cls.__name__ == self.plugin_type.base_class.__name__:
78-
continue
92+
# ignore if it's the base plugin class
93+
if cls.__name__ == self.plugin_type.base_class.__name__:
94+
continue
7995

80-
# make sure that the class is a subclass of the plugin's
81-
# base class
82-
if self.plugin_type.base_class in cls.__bases__:
83-
self.register_plugin(cls)
96+
# make sure that the class is a subclass of the plugin's
97+
# base class
98+
if self.plugin_type.base_class in cls.__bases__:
99+
self.register_plugin(cls)
84100

85101
return self._plugins
86102

@@ -97,6 +113,15 @@ def __init__(self, plugin_types=None):
97113
for plugin_type in plugin_types:
98114
self.register_plugin_type(plugin_type)
99115

116+
def _get_container(self, plugin_type):
117+
try:
118+
return self._containers[plugin_type.name]
119+
except KeyError:
120+
raise AssertionError("No plugins found for type: {0}: ".format(plugin_type))
121+
122+
def get_errors(self, plugin_type):
123+
return self._get_container(plugin_type).errors
124+
100125
def register_plugin_type(self, plugin_type):
101126
assert isinstance(plugin_type, PluginType)
102127

@@ -106,12 +131,7 @@ def register_plugin_type(self, plugin_type):
106131
self._containers[plugin_type.name] = PluginContainer(plugin_type)
107132

108133
def get_plugins(self, plugin_type):
109-
try:
110-
container = self._containers[plugin_type.name]
111-
except KeyError:
112-
raise AssertionError("No plugins found for type: {0}: ".format(plugin_type))
113-
114-
return container.get_plugins()
134+
return self._get_container(plugin_type).get_plugins()
115135

116136
def has_plugins(self, plugin_type):
117137
return bool(self.get_plugins(plugin_type))

0 commit comments

Comments
 (0)