comparison src/tools/trigger.py @ 2499:af4a38ebf52a

core (trigger): new returnPoint method: Normally trigger return value is a boolean used to check if normal workflow must be continued or stopped. This method add a way to also specify a return value to the method, in addition to the "continue or not" boolean.
author Goffi <goffi@goffi.org>
date Wed, 28 Feb 2018 18:28:39 +0100
parents 0046283a285d
children
comparison
equal deleted inserted replaced
2498:d6de69da3dd4 2499:af4a38ebf52a
27 class TriggerException(Exception): 27 class TriggerException(Exception):
28 pass 28 pass
29 29
30 30
31 class SkipOtherTriggers(Exception): 31 class SkipOtherTriggers(Exception):
32 """ Exception to raise if normal behaviour must be followed instead of 32 """ Exception to raise if normal behaviour must be followed instead of following triggers list """
33 following triggers list """
34 pass 33 pass
35 34
36 35
37 class TriggerManager(object): 36 class TriggerManager(object):
38 """This class manage triggers: code which interact to change the behaviour 37 """This class manage triggers: code which interact to change the behaviour of SàT"""
39 of SàT"""
40 38
41 try: # FIXME: to be removed when a better solution is found 39 try: # FIXME: to be removed when a better solution is found
42 MIN_PRIORITY = float('-inf') 40 MIN_PRIORITY = float('-inf')
43 MAX_PRIORITY = float('+inf') 41 MAX_PRIORITY = float('+inf')
44 except: # XXX: Pyjamas will bug if you specify ValueError here 42 except: # XXX: Pyjamas will bug if you specify ValueError here
49 def __init__(self): 47 def __init__(self):
50 self.__triggers = {} 48 self.__triggers = {}
51 49
52 def add(self, point_name, callback, priority=0): 50 def add(self, point_name, callback, priority=0):
53 """Add a trigger to a point 51 """Add a trigger to a point
52
54 @param point_name: name of the point when the trigger should be run 53 @param point_name: name of the point when the trigger should be run
55 @param callback: method to call at the trigger point 54 @param callback: method to call at the trigger point
56 @param priority: callback will be called in priority order, biggest 55 @param priority: callback will be called in priority order, biggest
57 first 56 first
58 """ 57 """
67 self.__triggers[point_name].sort(key=lambda trigger_tuple: 66 self.__triggers[point_name].sort(key=lambda trigger_tuple:
68 trigger_tuple[0], reverse=True) 67 trigger_tuple[0], reverse=True)
69 68
70 def remove(self, point_name, callback): 69 def remove(self, point_name, callback):
71 """Remove a trigger from a point 70 """Remove a trigger from a point
71
72 @param point_name: name of the point when the trigger should be run 72 @param point_name: name of the point when the trigger should be run
73 @param callback: method to remove, must exists in the trigger point""" 73 @param callback: method to remove, must exists in the trigger point
74 """
74 for trigger_tuple in self.__triggers[point_name]: 75 for trigger_tuple in self.__triggers[point_name]:
75 if trigger_tuple[1] == callback: 76 if trigger_tuple[1] == callback:
76 self.__triggers[point_name].remove(trigger_tuple) 77 self.__triggers[point_name].remove(trigger_tuple)
77 return 78 return
78 raise TriggerException("Trying to remove an unexisting trigger") 79 raise TriggerException("Trying to remove an unexisting trigger")
79 80
80 def point(self, point_name, *args, **kwargs): 81 def point(self, point_name, *args, **kwargs):
81 """This put a trigger point 82 """This put a trigger point
82 All the trigger for that point will be run 83
84 All the triggers for that point will be run
83 @param point_name: name of the trigger point 85 @param point_name: name of the trigger point
84 @return: True if the action must be continued, False else""" 86 @return: True if the action must be continued, False else
87 """
85 if point_name not in self.__triggers: 88 if point_name not in self.__triggers:
86 return True 89 return True
87 90
88 for priority, trigger in self.__triggers[point_name]: 91 for priority, trigger in self.__triggers[point_name]:
89 try: 92 try:
90 if not trigger(*args, **kwargs): 93 if not trigger(*args, **kwargs):
91 return False 94 return False
92 except SkipOtherTriggers: 95 except SkipOtherTriggers:
93 break 96 break
94 return True 97 return True
98
99 def returnPoint(self, point_name, *args, **kwargs):
100 """Like point but trigger must return (continue, return_value)
101
102 All triggers for that point must return a tuple with 2 values:
103 - continue, same as for point, if False action must be finished
104 - return_value: value to return ONLY IF CONTINUE IS FALSE
105 @param point_name: name of the trigger point
106 @return: True if the action must be continued, False else
107 """
108
109 if point_name not in self.__triggers:
110 return True
111
112 for priority, trigger in self.__triggers[point_name]:
113 try:
114 cont, ret_value = trigger(*args, **kwargs)
115 if not cont:
116 return False, ret_value
117 except SkipOtherTriggers:
118 break
119 return True, None