123 lines
4.8 KiB
Python
123 lines
4.8 KiB
Python
# Copyright (c) 2017 Adler Neves <adlerosn@gmail.com>
|
|
#
|
|
# MIT License
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
# a copy of this software and associated documentation files (the
|
|
# "Software"), to deal in the Software without restriction, including
|
|
# without limitation the rights to use, copy, modify, merge, publish,
|
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
# permit persons to whom the Software is furnished to do so, subject to
|
|
# the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be
|
|
# included in all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
from server_secrets.hookModules import hookModules
|
|
|
|
class HookOption:
|
|
def __init__(self, module, handler):
|
|
self.module = module
|
|
self.handler = handler
|
|
|
|
hookOptions = dict()
|
|
for module in hookModules:
|
|
if hasattr(module, 'getHooks'):
|
|
hooks = module.getHooks()
|
|
if isinstance(hooks, dict):
|
|
for event, callbacks in hooks.items():
|
|
if isinstance(event, str) and isinstance(callbacks, list):
|
|
if event not in hookOptions:
|
|
hookOptions[event] = list()
|
|
hookOptions[event]+=map(lambda c: HookOption(module,c), callbacks)
|
|
|
|
del hookModules
|
|
|
|
def fire(event, data=None):
|
|
'''
|
|
event: str = the event fired
|
|
data: object? = auxiliary data for the desired event
|
|
---
|
|
Event types:
|
|
|
|
filter -> data should be a collection
|
|
the use case is either removing data from user sight, sorting or transforming it somehow
|
|
it usually is the last stage before data goes to the user
|
|
example: one stage of "filter:sentencelist" can replace all curse words by asterisks
|
|
|
|
action -> data can be anything
|
|
the usecase is when you finish doing something and wants to notify something happened
|
|
example: "action:xyz_tool:preprocessing:result"
|
|
example: "action:sentencelist:result"
|
|
|
|
query -> data can be anything
|
|
the use case is when data related to the one provided needs to be taken out of other plugins
|
|
example: "query:sentencelist" (where data is the corpus, and the return is a list of dicts, where one entry contains the callback to the plugins that provides such feature)
|
|
|
|
provider -> data will remain unused
|
|
the use case is when one plugin can have its features extended by
|
|
example: "provider:xyz_tool" (an "jkl_dataset" can provide assets for the "xyz_tool" plugin)
|
|
|
|
---
|
|
|
|
Quick review:
|
|
|
|
provider -> none Input, list Output
|
|
query -> any Input, list Output
|
|
filter -> iter Input, iter Output
|
|
action -> any Input, none Output
|
|
|
|
---
|
|
|
|
This part of the platform gives you no guarantee that some recursion loop won't
|
|
happen when more than one plugin acts; because of that, avoid breaking the
|
|
sequence:
|
|
provider -> query -> filter -> action
|
|
No problem in skipping some stage; but can be some problem in firing the previous
|
|
stages on a further stage. Also, avoid firing events on the same stage of a
|
|
fired event.
|
|
'''
|
|
if not isinstance(event,str):
|
|
raise TypeError("Event should be a string")
|
|
elif ':' not in event:
|
|
raise NameError('All events should have a prefix. Ex: "query:provider:sentencelist"')
|
|
elif event.startswith('filter:'):
|
|
if not hasattr(data,'__iter__'):
|
|
raise AttributeError('data provided should be iterable')
|
|
for hookOption in hookOptions.get(event,list()):
|
|
data = hookOption.handler(data)
|
|
return data
|
|
elif event.startswith('action:'):
|
|
for hookOption in hookOptions.get(event,list()):
|
|
hookOption.handler(data)
|
|
return
|
|
elif event.startswith('query:'):
|
|
result = list()
|
|
for hookOption in hookOptions.get(event,list()):
|
|
result.append(hookOption.handler(data))
|
|
return result
|
|
elif event.startswith('provider:'):
|
|
result = list()
|
|
for hookOption in hookOptions.get(event,list()):
|
|
result.append(hookOption.handler())
|
|
return result
|
|
else:
|
|
raise NotImplementedError('Event wasn\'t implented: '+str(event))
|
|
|
|
from urllib.parse import quote as urlGet
|
|
|
|
def buildNextGetPart(url):
|
|
return '?next='+urlGet(url, safe='')
|
|
|
|
def nextGetArg(redirect, url):
|
|
redirect['Location']+=buildNextGetPart(url)
|
|
return redirect
|