Skip to content

Commit 99f24a0

Browse files
author
Pietro Albini
committed
Refactored the hooks chain
This new implementation freezes the chain when the bot is frozen, and supports multiple chains, without the need to reimplement the logic everytime you add a new chain.
1 parent dd84bdc commit 99f24a0

File tree

3 files changed

+46
-31
lines changed

3 files changed

+46
-31
lines changed

botogram/bot.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def __init__(self, api_connection):
5454
self._shared_memory = shared.SharedMemory()
5555

5656
# Register bot's shared memory initializers
57-
inits = self._main_component._get_memory_preparers()
57+
inits = self._main_component._get_chains()["memory_preparers"][0]
5858
maincompid = self._main_component._component_id
5959
self._shared_memory.register_preparers_list(maincompid, inits)
6060

@@ -162,12 +162,13 @@ def use(self, *components, only_init=False):
162162
self._components.append(component)
163163

164164
# Register initializers for the shared memory
165+
chains = component._get_chains()
165166
compid = component._component_id
166-
preparers = component._get_memory_preparers()
167+
preparers = chains["memory_preparers"][0]
167168
self._shared_memory.register_preparers_list(compid, preparers)
168169

169170
# Register tasks
170-
self._scheduler.register_tasks_list(component._get_timers())
171+
self._scheduler.register_tasks_list(chains["tasks"][0])
171172

172173
def process(self, update):
173174
"""Process an update object"""
@@ -184,12 +185,14 @@ def run(self, workers=2):
184185

185186
def freeze(self):
186187
"""Return a frozen instance of the bot"""
188+
chains = components.merge_chains(self._main_component,
189+
*self._components)
190+
187191
return frozenbot.FrozenBot(self.api, self.about, self.owner,
188192
self.hide_commands, self.before_help,
189193
self.after_help, self.process_backlog,
190194
self.lang, self.itself, self._commands_re,
191-
self._components+[self._main_component],
192-
self._scheduler,
195+
chains, self._scheduler,
193196
self._main_component._component_id,
194197
self._bot_id, self._shared_memory)
195198

botogram/components.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,23 +144,49 @@ def _add_no_commands_hook(self, func):
144144
hook = hooks.NoCommandsHook(func, self)
145145
self.__no_commands.append(hook)
146146

147-
def _get_hooks_chain(self):
147+
def _get_chains(self):
148148
"""Get the full hooks chain for this component"""
149-
return [
149+
messages = [
150150
self.__before_processors[:],
151151
[self.__commands[name] for name in sorted(self.__commands.keys())],
152152
self.__no_commands[:],
153153
self.__processors[:],
154154
]
155+
return {
156+
"messages": messages,
157+
"memory_preparers": [self.__memory_preparers],
158+
"tasks": [self.__timers],
159+
}
155160

156161
def _get_commands(self):
157162
"""Get all the commands this component implements"""
158163
return self.__commands
159164

160-
def _get_memory_preparers(self):
161-
"""Get a list of all the shared memory initializers"""
162-
return self.__memory_preparers
163165

164-
def _get_timers(self):
165-
"""Get a list of all the timers"""
166-
return self.__timers
166+
def merge_chains(main, *components):
167+
"""Merge multiple chains returned by the components"""
168+
merged = {}
169+
components = [main]+list(reversed(components))
170+
171+
# First of all, merge all the subchains of the different components
172+
# together -- This is a separate step so the order is preserved
173+
for component in components:
174+
macrochains = component._get_chains()
175+
for kind, chains in macrochains.items():
176+
if kind not in merged:
177+
merged[kind] = []
178+
179+
for i, chain in enumerate(chains):
180+
try:
181+
merged[kind][i] += chain
182+
except IndexError:
183+
merged[kind].append(chain[:])
184+
185+
# Then merge all the subchains together
186+
result = {}
187+
for kind, chains in merged.items():
188+
result[kind] = []
189+
for chain in chains:
190+
result[kind] += chain
191+
192+
return result

botogram/frozenbot.py

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class FrozenBot:
2222

2323
def __init__(self, api, about, owner, hide_commands, before_help,
2424
after_help, process_backlog, lang, itself, commands_re,
25-
components, scheduler, main_component_id, bot_id,
25+
chains, scheduler, main_component_id, bot_id,
2626
shared_memory):
2727
# This attribute should be added with the default setattr, because is
2828
# needed by the custom setattr
@@ -38,25 +38,11 @@ def __init__(self, api, about, owner, hide_commands, before_help,
3838
self.process_backlog = process_backlog
3939
self.lang = lang
4040
self._commands_re = commands_re
41-
self._components = components
4241
self._main_component_id = main_component_id
4342
self._bot_id = bot_id
4443
self._shared_memory = shared_memory
4544
self._scheduler = scheduler
46-
47-
# Rebuild the hooks chain and commands list
48-
self._commands = components[-1]._get_commands()
49-
self._chain = []
50-
chains = components[-1]._get_hooks_chain()
51-
for component in reversed(components[:-1]):
52-
self._commands.update(component._get_commands())
53-
54-
comp_chain = component._get_hooks_chain()
55-
for i in range(len(chains)):
56-
chains[i] += comp_chain[i]
57-
58-
for chain in chains:
59-
self._chain += chain
45+
self._chains = chains
6046

6147
# Setup the logger
6248
self.logger = logbook.Logger('botogram bot')
@@ -75,7 +61,7 @@ def __reduce__(self):
7561
args = (
7662
self.api, self.about, self.owner, self.hide_commands,
7763
self.before_help, self.after_help, self.process_backlog,
78-
self.lang, self.itself, self._commands_re, self._components,
64+
self.lang, self.itself, self._commands_re, self._chains,
7965
self._scheduler, self._main_component_id, self._bot_id,
8066
self._shared_memory,
8167
)
@@ -186,7 +172,7 @@ def process(self, update):
186172

187173
update.set_api(self.api) # Be sure to use the correct API object
188174

189-
for hook in self._chain:
175+
for hook in self._chains["messages"]:
190176
# Get the correct name of the hook
191177
name = hook.name
192178
self.logger.debug("Processing update #%s with the %s hook..." %

0 commit comments

Comments
 (0)