Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/IPython/core/events.py: 50%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

46 statements  

1"""Infrastructure for registering and firing callbacks on application events. 

2 

3Unlike :mod:`IPython.core.hooks`, which lets end users set single functions to 

4be called at specific times, or a collection of alternative methods to try, 

5callbacks are designed to be used by extension authors. A number of callbacks 

6can be registered for the same event without needing to be aware of one another. 

7 

8The functions defined in this module are no-ops indicating the names of available 

9events and the arguments which will be passed to them. 

10 

11.. note:: 

12 

13 This API is experimental in IPython 2.0, and may be revised in future versions. 

14""" 

15 

16from __future__ import annotations 

17 

18from typing import TYPE_CHECKING, Any, Callable, Iterable 

19 

20if TYPE_CHECKING: 

21 from IPython.core.interactiveshell import InteractiveShell 

22 

23 

24class EventManager: 

25 """Manage a collection of events and a sequence of callbacks for each. 

26  

27 This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell` 

28 instances as an ``events`` attribute. 

29  

30 .. note:: 

31 

32 This API is experimental in IPython 2.0, and may be revised in future versions. 

33 """ 

34 

35 def __init__( 

36 self, 

37 shell: InteractiveShell, 

38 available_events: Iterable[str], 

39 print_on_error: bool = True, 

40 ) -> None: 

41 """Initialise the :class:`CallbackManager`. 

42 

43 Parameters 

44 ---------- 

45 shell 

46 The :class:`~IPython.core.interactiveshell.InteractiveShell` instance 

47 available_events 

48 An iterable of names for callback events. 

49 print_on_error: 

50 A boolean flag to set whether the EventManager will print a warning which a event errors. 

51 """ 

52 self.shell = shell 

53 self.callbacks: dict[str, list[Callable[..., Any]]] = { 

54 n: [] for n in available_events 

55 } 

56 self.print_on_error = print_on_error 

57 

58 def register(self, event: str, function: Callable[..., Any]) -> None: 

59 """Register a new event callback. 

60 

61 Parameters 

62 ---------- 

63 event : str 

64 The event for which to register this callback. 

65 function : callable 

66 A function to be called on the given event. It should take the same 

67 parameters as the appropriate callback prototype. 

68 

69 Raises 

70 ------ 

71 TypeError 

72 If ``function`` is not callable. 

73 KeyError 

74 If ``event`` is not one of the known events. 

75 """ 

76 if not callable(function): 

77 raise TypeError('Need a callable, got %r' % function) 

78 if function not in self.callbacks[event]: 

79 self.callbacks[event].append(function) 

80 

81 def unregister(self, event: str, function: Callable[..., Any]) -> None: 

82 """Remove a callback from the given event.""" 

83 if function in self.callbacks[event]: 

84 return self.callbacks[event].remove(function) 

85 

86 raise ValueError('Function {!r} is not registered as a {} callback'.format(function, event)) 

87 

88 def trigger(self, event: str, *args: Any, **kwargs: Any) -> None: 

89 """Call callbacks for ``event``. 

90 

91 Any additional arguments are passed to all callbacks registered for this 

92 event. Exceptions raised by callbacks are caught, and a message printed. 

93 """ 

94 for func in self.callbacks[event][:]: 

95 try: 

96 func(*args, **kwargs) 

97 except (Exception, KeyboardInterrupt): 

98 if self.print_on_error: 

99 print( 

100 "Error in callback {} (for {}), with arguments args {},kwargs {}:".format( 

101 func, event, args, kwargs 

102 ) 

103 ) 

104 self.shell.showtraceback() 

105 

106# event_name -> prototype mapping 

107available_events: dict[str, Callable[..., Any]] = {} 

108 

109def _define_event(callback_function: Callable[..., Any]) -> Callable[..., Any]: 

110 available_events[callback_function.__name__] = callback_function 

111 return callback_function 

112 

113# ------------------------------------------------------------------------------ 

114# Callback prototypes 

115# 

116# No-op functions which describe the names of available events and the 

117# signatures of callbacks for those events. 

118# ------------------------------------------------------------------------------ 

119 

120@_define_event 

121def pre_execute() -> None: 

122 """Fires before code is executed in response to user/frontend action. 

123 

124 This includes comm and widget messages and silent execution, as well as user 

125 code cells. 

126 """ 

127 pass 

128 

129@_define_event 

130def pre_run_cell(info: Any) -> None: 

131 """Fires before user-entered code runs. 

132 

133 Parameters 

134 ---------- 

135 info : :class:`~IPython.core.interactiveshell.ExecutionInfo` 

136 An object containing information used for the code execution. 

137 """ 

138 pass 

139 

140@_define_event 

141def post_execute() -> None: 

142 """Fires after code is executed in response to user/frontend action. 

143 

144 This includes comm and widget messages and silent execution, as well as user 

145 code cells. 

146 """ 

147 pass 

148 

149@_define_event 

150def post_run_cell(result: Any) -> None: 

151 """Fires after user-entered code runs. 

152 

153 Parameters 

154 ---------- 

155 result : :class:`~IPython.core.interactiveshell.ExecutionResult` 

156 The object which will be returned as the execution result. 

157 """ 

158 pass 

159 

160@_define_event 

161def shell_initialized(ip: InteractiveShell) -> None: 

162 """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`. 

163 

164 This is before extensions and startup scripts are loaded, so it can only be 

165 set by subclassing. 

166 

167 Parameters 

168 ---------- 

169 ip : :class:`~IPython.core.interactiveshell.InteractiveShell` 

170 The newly initialised shell. 

171 """ 

172 pass