Skip to content
This repository was archived by the owner on Apr 27, 2019. It is now read-only.

Commit 8bc385b

Browse files
committed
Unit tests, mapping overridden
1 parent 6b5291a commit 8bc385b

4 files changed

Lines changed: 74 additions & 37 deletions

File tree

base_plugin.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
from packets import Packets
55

66

7-
packet_name_regex = re.compile(r'(on|after)_(?P<packet_name>\w+)')
7+
packet_name_regex = re.compile(r'(?P<when>on|after)_(?P<packet_name>\w+)')
88

99

1010
class MapOverridePacketsMethods(type):
1111
ignored_methods = ('activate', 'deactivate')
1212

1313
def __new__(cls, name, bases, cls_dict):
1414
if name != 'BasePlugin':
15-
cls_dict['override_packets'] = []
15+
cls_dict['override_packets'] = {}
1616
methods = (
1717
key for key, value in cls_dict.iteritems()
1818
if key not in cls.ignored_methods and callable(value)
@@ -22,8 +22,10 @@ def __new__(cls, name, bases, cls_dict):
2222
if packet:
2323
packet_name = packet.group('packet_name').upper()
2424
enum = getattr(Packets, packet_name, None)
25-
if enum and enum.value not in cls_dict['override_packets']:
26-
cls_dict['override_packets'].append(enum.value)
25+
if enum:
26+
cls_dict['override_packets'].setdefault(
27+
enum.value, {}
28+
)[packet.group('when')] = packet_method_name
2729

2830
return super(MapOverridePacketsMethods, cls).__new__(
2931
cls, name, bases, cls_dict
@@ -56,6 +58,15 @@ class BasePlugin(object):
5658
depends = []
5759
active = True
5860

61+
def __init__(self, *args, **kwargs):
62+
super(BasePlugin, self).__init__(*args, **kwargs)
63+
if self.__class__.__name__ != 'BasePlugin':
64+
for packet, when_dict in self.override_packets.iteritems():
65+
for when, packet_name in when_dict.iteritems():
66+
self.override_packets[packet][when] = getattr(
67+
self, packet_name
68+
)
69+
5970
def activate(self):
6071
"""
6172
Called when the plugins are activated, do any setup work here.
@@ -403,11 +414,14 @@ def after_fly_ship(self, data):
403414
def after_central_structure_update(self, data):
404415
return True
405416

406-
def __repr__(self):
407-
return '<Plugin instance: {} (version {})>'.format(
417+
def __unicode__(self):
418+
return u'<Plugin instance: {} (version {})>'.format(
408419
self.name, self.version
409420
)
410421

422+
def __str__(self):
423+
return self.__unicode__()
424+
411425

412426
class CommandNameError(Exception):
413427
"""

plugin_manager.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def __init__(self, factory, base_class=BasePlugin):
5252
5353
:param base_class: The base class to use while searching for plugins.
5454
"""
55+
self.packets = {}
5556
self.plugins = {}
5657
self.plugin_classes = {}
5758
self.plugins_waiting_to_load = {}
@@ -216,6 +217,7 @@ def activate_plugins(self, plugins, dependencies):
216217
for p in plugin_deps:
217218
self.plugin_classes[plugin.name].plugins[p.name] = p
218219
self.plugins[plugin.name].activate()
220+
self.map_plugin_packets(plugin)
219221
except FatalPluginError as e:
220222
self.logger.critical(
221223
'A plugin reported a fatal error. Error: %s', str(e)
@@ -231,8 +233,9 @@ def deactivate_plugins(self):
231233
'A plugin reported a fatal error. Error: %s', str(e)
232234
)
233235
raise
236+
self.de_map_plugin_packets(plugin)
234237

235-
def do(self, protocol, command, data):
238+
def do(self, protocol, when, data):
236239
"""
237240
Runs a command across all currently loaded plugins.
238241
@@ -247,27 +250,45 @@ def do(self, protocol, command, data):
247250
return True
248251

249252
return_values = []
250-
plugins = (
251-
plugin for plugin in self.plugins.itervalues()
252-
if plugin.active and data.id in plugin.override_packets
253-
)
254-
for plugin in plugins:
253+
packets = self.packets.get(data.id, {}).get(when, {}).itervalues()
254+
for plugin, packet_method in packets:
255255
try:
256256
plugin.protocol = protocol
257-
res = getattr(plugin, command, lambda _: True)(data)
257+
res = packet_method(data)
258258
if res is None:
259259
res = True
260260
return_values.append(res)
261261
except:
262262
self.logger.exception(
263263
'Error in plugin %s with function %s.',
264-
str(plugin), command
264+
str(plugin), packet_method.__name__
265265
)
266266
return all(return_values)
267267

268268
def die(self):
269269
self.deactivate_plugins()
270270

271+
def map_plugin_packets(self, plugin):
272+
"""
273+
Maps plugin overridden packets ready to use in do method.
274+
"""
275+
for packet_id, when_dict in plugin.override_packets.iteritems():
276+
for when, packet_method in when_dict.iteritems():
277+
self.packets.setdefault(
278+
packet_id, {}
279+
).setdefault(
280+
when, {}
281+
)[plugin.name] = (plugin, packet_method)
282+
283+
def de_map_plugin_packets(self, plugin):
284+
"""
285+
Removes plugin overridden packets method from packets dictionary.
286+
"""
287+
for packet_id, when_dict in self.packets.iteritems():
288+
for when, plugins in when_dict.iteritems():
289+
if plugin.name in plugins:
290+
plugins.pop(plugin.name)
291+
271292

272293
def route(func):
273294
"""
@@ -276,18 +297,15 @@ def route(func):
276297
logger = logging.getLogger('starrypy.plugin_manager.route')
277298

278299
def wrapped_function(self, data):
279-
name = func.__name__
280-
on = 'on_%s' % name
281-
after = 'after_%s' % name
282-
res = self.plugin_manager.do(self, on, data)
300+
res = self.plugin_manager.do(self, 'on', data)
283301
if res:
284302
res = func(self, data)
285303
d = deferLater(
286304
reactor,
287305
.01,
288306
self.plugin_manager.do,
289307
self,
290-
after,
308+
'after',
291309
data
292310
)
293311
d.addErrback(print_this_defered_failure)

tests/test_base_plugin.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,28 @@ class TestPlugin2(BasePlugin):
2121
def on_burn_container(self, data):
2222
pass
2323

24+
def after_burn_container(self, data):
25+
pass
26+
2427
test_plugin2 = TestPlugin2()
2528
test_plugin = TestPlugin()
26-
self.assertListEqual(test_plugin.override_packets, [5, 14])
27-
self.assertListEqual(test_plugin2.override_packets, [44])
29+
self.assertDictEqual(
30+
test_plugin.override_packets,
31+
{
32+
5: {
33+
'on': test_plugin.on_chat_received
34+
},
35+
14: {
36+
'on': test_plugin.on_chat_sent
37+
}
38+
}
39+
)
40+
self.assertDictEqual(
41+
test_plugin2.override_packets,
42+
{
43+
44: {
44+
'on': test_plugin2.on_burn_container,
45+
'after': test_plugin2.after_burn_container
46+
}
47+
}
48+
)

tests/test_plugin_manager.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,19 +101,3 @@ def test_installed_plugins(self, mock_config, mock_path, mock_sys):
101101
result = pm.installed_plugins()
102102

103103
self.assertListEqual(result, ['plugin'])
104-
105-
@patch('plugin_manager.__import__')
106-
@patch('plugin_manager.inspect.getmembers')
107-
@patch('plugin_manager.sys')
108-
@patch('plugin_manager.path')
109-
@patch('plugin_manager.ConfigurationManager')
110-
def test_import_plugin(
111-
self,
112-
mock_config,
113-
mock_path,
114-
mock_sys,
115-
mock_getmembers,
116-
mock_import
117-
):
118-
mock_factory = Mock()
119-
mock_import.return_value = ''

0 commit comments

Comments
 (0)