##// END OF EJS Templates
Attempt to remove backcall....
Matthias Bussonnier -
Show More
@@ -1,166 +1,155 b''
1 1 """Infrastructure for registering and firing callbacks on application events.
2 2
3 3 Unlike :mod:`IPython.core.hooks`, which lets end users set single functions to
4 4 be called at specific times, or a collection of alternative methods to try,
5 5 callbacks are designed to be used by extension authors. A number of callbacks
6 6 can be registered for the same event without needing to be aware of one another.
7 7
8 8 The functions defined in this module are no-ops indicating the names of available
9 9 events and the arguments which will be passed to them.
10 10
11 11 .. note::
12 12
13 13 This API is experimental in IPython 2.0, and may be revised in future versions.
14 14 """
15 15
16 from backcall import callback_prototype
17
18 16
19 17 class EventManager(object):
20 18 """Manage a collection of events and a sequence of callbacks for each.
21 19
22 20 This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
23 21 instances as an ``events`` attribute.
24 22
25 23 .. note::
26 24
27 25 This API is experimental in IPython 2.0, and may be revised in future versions.
28 26 """
29 27
30 28 def __init__(self, shell, available_events, print_on_error=True):
31 29 """Initialise the :class:`CallbackManager`.
32 30
33 31 Parameters
34 32 ----------
35 33 shell
36 34 The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
37 35 available_events
38 36 An iterable of names for callback events.
39 37 print_on_error:
40 38 A boolean flag to set whether the EventManager will print a warning which a event errors.
41 39 """
42 40 self.shell = shell
43 41 self.callbacks = {n:[] for n in available_events}
44 42 self.print_on_error = print_on_error
45 43
46 44 def register(self, event, function):
47 45 """Register a new event callback.
48 46
49 47 Parameters
50 48 ----------
51 49 event : str
52 50 The event for which to register this callback.
53 51 function : callable
54 52 A function to be called on the given event. It should take the same
55 53 parameters as the appropriate callback prototype.
56 54
57 55 Raises
58 56 ------
59 57 TypeError
60 58 If ``function`` is not callable.
61 59 KeyError
62 60 If ``event`` is not one of the known events.
63 61 """
64 62 if not callable(function):
65 63 raise TypeError('Need a callable, got %r' % function)
66 callback_proto = available_events.get(event)
67 64 if function not in self.callbacks[event]:
68 self.callbacks[event].append(callback_proto.adapt(function))
65 self.callbacks[event].append(function)
69 66
70 67 def unregister(self, event, function):
71 68 """Remove a callback from the given event."""
72 69 if function in self.callbacks[event]:
73 70 return self.callbacks[event].remove(function)
74 71
75 # Remove callback in case ``function`` was adapted by `backcall`.
76 for callback in self.callbacks[event]:
77 try:
78 if callback.__wrapped__ is function:
79 return self.callbacks[event].remove(callback)
80 except AttributeError:
81 pass
82
83 72 raise ValueError('Function {!r} is not registered as a {} callback'.format(function, event))
84 73
85 74 def trigger(self, event, *args, **kwargs):
86 75 """Call callbacks for ``event``.
87 76
88 77 Any additional arguments are passed to all callbacks registered for this
89 78 event. Exceptions raised by callbacks are caught, and a message printed.
90 79 """
91 80 for func in self.callbacks[event][:]:
92 81 try:
93 82 func(*args, **kwargs)
94 83 except (Exception, KeyboardInterrupt):
95 84 if self.print_on_error:
96 85 print("Error in callback {} (for {}):".format(func, event))
97 86 self.shell.showtraceback()
98 87
99 88 # event_name -> prototype mapping
100 89 available_events = {}
101 90
102 91 def _define_event(callback_function):
103 92 callback_proto = callback_prototype(callback_function)
104 93 available_events[callback_function.__name__] = callback_proto
105 94 return callback_proto
106 95
107 96 # ------------------------------------------------------------------------------
108 97 # Callback prototypes
109 98 #
110 99 # No-op functions which describe the names of available events and the
111 100 # signatures of callbacks for those events.
112 101 # ------------------------------------------------------------------------------
113 102
114 103 @_define_event
115 104 def pre_execute():
116 105 """Fires before code is executed in response to user/frontend action.
117 106
118 107 This includes comm and widget messages and silent execution, as well as user
119 108 code cells.
120 109 """
121 110 pass
122 111
123 112 @_define_event
124 113 def pre_run_cell(info):
125 114 """Fires before user-entered code runs.
126 115
127 116 Parameters
128 117 ----------
129 118 info : :class:`~IPython.core.interactiveshell.ExecutionInfo`
130 119 An object containing information used for the code execution.
131 120 """
132 121 pass
133 122
134 123 @_define_event
135 124 def post_execute():
136 125 """Fires after code is executed in response to user/frontend action.
137 126
138 127 This includes comm and widget messages and silent execution, as well as user
139 128 code cells.
140 129 """
141 130 pass
142 131
143 132 @_define_event
144 133 def post_run_cell(result):
145 134 """Fires after user-entered code runs.
146 135
147 136 Parameters
148 137 ----------
149 138 result : :class:`~IPython.core.interactiveshell.ExecutionResult`
150 139 The object which will be returned as the execution result.
151 140 """
152 141 pass
153 142
154 143 @_define_event
155 144 def shell_initialized(ip):
156 145 """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
157 146
158 147 This is before extensions and startup scripts are loaded, so it can only be
159 148 set by subclassing.
160 149
161 150 Parameters
162 151 ----------
163 152 ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
164 153 The newly initialised shell.
165 154 """
166 155 pass
@@ -1,118 +1,117 b''
1 1 [metadata]
2 2 name = ipython
3 3 version = attr: IPython.core.release.__version__
4 4 url = https://ipython.org
5 5 description = IPython: Productive Interactive Computing
6 6 long_description_content_type = text/x-rst
7 7 long_description = file: long_description.rst
8 8 license_file = LICENSE
9 9 project_urls =
10 10 Documentation = https://ipython.readthedocs.io/
11 11 Funding = https://numfocus.org/
12 12 Source = https://github.com/ipython/ipython
13 13 Tracker = https://github.com/ipython/ipython/issues
14 14 keywords = Interactive, Interpreter, Shell, Embedding
15 15 platforms = Linux, Mac OSX, Windows
16 16 classifiers =
17 17 Framework :: IPython
18 18 Framework :: Jupyter
19 19 Intended Audience :: Developers
20 20 Intended Audience :: Science/Research
21 21 License :: OSI Approved :: BSD License
22 22 Programming Language :: Python
23 23 Programming Language :: Python :: 3
24 24 Programming Language :: Python :: 3 :: Only
25 25 Topic :: System :: Shells
26 26
27 27 [options]
28 28 packages = find:
29 29 python_requires = >=3.9
30 30 zip_safe = False
31 31 install_requires =
32 32 appnope; sys_platform == "darwin"
33 backcall
34 33 colorama; sys_platform == "win32"
35 34 decorator
36 35 exceptiongroup; python_version<'3.11'
37 36 jedi>=0.16
38 37 matplotlib-inline
39 38 pexpect>4.3; sys_platform != "win32"
40 39 pickleshare
41 40 prompt_toolkit>=3.0.30,<3.1.0,!=3.0.37
42 41 pygments>=2.4.0
43 42 stack_data
44 43 traitlets>=5
45 44 typing_extensions ; python_version<'3.10'
46 45
47 46 [options.extras_require]
48 47 black =
49 48 black
50 49 doc =
51 50 ipykernel
52 51 setuptools>=18.5
53 52 sphinx>=1.3
54 53 sphinx-rtd-theme
55 54 docrepr
56 55 matplotlib
57 56 stack_data
58 57 pytest<7
59 58 typing_extensions
60 59 exceptiongroup
61 60 %(test)s
62 61 kernel =
63 62 ipykernel
64 63 nbconvert =
65 64 nbconvert
66 65 nbformat =
67 66 nbformat
68 67 notebook =
69 68 ipywidgets
70 69 notebook
71 70 parallel =
72 71 ipyparallel
73 72 qtconsole =
74 73 qtconsole
75 74 terminal =
76 75 test =
77 76 pytest<7.1
78 77 pytest-asyncio
79 78 testpath
80 79 test_extra =
81 80 %(test)s
82 81 curio
83 82 matplotlib!=3.2.0
84 83 nbformat
85 84 numpy>=1.22
86 85 pandas
87 86 trio
88 87 all =
89 88 %(black)s
90 89 %(doc)s
91 90 %(kernel)s
92 91 %(nbconvert)s
93 92 %(nbformat)s
94 93 %(notebook)s
95 94 %(parallel)s
96 95 %(qtconsole)s
97 96 %(terminal)s
98 97 %(test_extra)s
99 98 %(test)s
100 99
101 100 [options.packages.find]
102 101 exclude =
103 102 setupext
104 103
105 104 [options.package_data]
106 105 IPython = py.typed
107 106 IPython.core = profile/README*
108 107 IPython.core.tests = *.png, *.jpg, daft_extension/*.py
109 108 IPython.lib.tests = *.wav
110 109 IPython.testing.plugin = *.txt
111 110
112 111 [velin]
113 112 ignore_patterns =
114 113 IPython/core/tests
115 114 IPython/testing
116 115
117 116 [tool.black]
118 117 exclude = 'timing\.py'
General Comments 0
You need to be logged in to leave comments. Login now