##// END OF EJS Templates
front ends can have both Manager and Client
MinRK -
Show More
@@ -1,120 +1,150
1 """ Defines a convenient mix-in class for implementing Qt frontends.
1 """ Defines a convenient mix-in class for implementing Qt frontends.
2 """
2 """
3
3
4 class BaseFrontendMixin(object):
4 class BaseFrontendMixin(object):
5 """ A mix-in class for implementing Qt frontends.
5 """ A mix-in class for implementing Qt frontends.
6
6
7 To handle messages of a particular type, frontends need only define an
7 To handle messages of a particular type, frontends need only define an
8 appropriate handler method. For example, to handle 'stream' messaged, define
8 appropriate handler method. For example, to handle 'stream' messaged, define
9 a '_handle_stream(msg)' method.
9 a '_handle_stream(msg)' method.
10 """
10 """
11
11
12 #---------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
13 # 'BaseFrontendMixin' concrete interface
13 # 'BaseFrontendMixin' concrete interface
14 #---------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
15 _kernel_client = None
15 _kernel_client = None
16 _kernel_manager = None
16
17
17 def _get_kernel_client(self):
18 @property
18 """Returns the current kernel client.
19 def kernel_client(self):
19 """
20 """Returns the current kernel client."""
20 return self._kernel_client
21 return self._kernel_client
21
22
22 def _set_kernel_client(self, kernel_client):
23 @kernel_client.setter
24 def kernel_client(self, kernel_client):
23 """Disconnect from the current kernel client (if any) and set a new
25 """Disconnect from the current kernel client (if any) and set a new
24 kernel client.
26 kernel client.
25 """
27 """
26 # Disconnect the old kernel client, if necessary.
28 # Disconnect the old kernel client, if necessary.
27 old_client = self._kernel_client
29 old_client = self._kernel_client
28 if old_client is not None:
30 if old_client is not None:
29 old_client.started_channels.disconnect(self._started_channels)
31 old_client.started_channels.disconnect(self._started_channels)
30 old_client.stopped_channels.disconnect(self._stopped_channels)
32 old_client.stopped_channels.disconnect(self._stopped_channels)
31
33
32 # Disconnect the old kernel client's channels.
34 # Disconnect the old kernel client's channels.
33 old_client.iopub_channel.message_received.disconnect(self._dispatch)
35 old_client.iopub_channel.message_received.disconnect(self._dispatch)
34 old_client.shell_channel.message_received.disconnect(self._dispatch)
36 old_client.shell_channel.message_received.disconnect(self._dispatch)
35 old_client.stdin_channel.message_received.disconnect(self._dispatch)
37 old_client.stdin_channel.message_received.disconnect(self._dispatch)
36 old_client.hb_channel.kernel_died.disconnect(
38 old_client.hb_channel.kernel_died.disconnect(
37 self._handle_kernel_died)
39 self._handle_kernel_died)
38
40
39 # Handle the case where the old kernel client is still listening.
41 # Handle the case where the old kernel client is still listening.
40 if old_client.channels_running:
42 if old_client.channels_running:
41 self._stopped_channels()
43 self._stopped_channels()
42
44
43 # Set the new kernel client.
45 # Set the new kernel client.
44 self._kernel_client = kernel_client
46 self._kernel_client = kernel_client
45 if kernel_client is None:
47 if kernel_client is None:
46 return
48 return
47
49
48 # Connect the new kernel client.
50 # Connect the new kernel client.
49 kernel_client.started_channels.connect(self._started_channels)
51 kernel_client.started_channels.connect(self._started_channels)
50 kernel_client.stopped_channels.connect(self._stopped_channels)
52 kernel_client.stopped_channels.connect(self._stopped_channels)
51
53
52 # Connect the new kernel client's channels.
54 # Connect the new kernel client's channels.
53 kernel_client.iopub_channel.message_received.connect(self._dispatch)
55 kernel_client.iopub_channel.message_received.connect(self._dispatch)
54 kernel_client.shell_channel.message_received.connect(self._dispatch)
56 kernel_client.shell_channel.message_received.connect(self._dispatch)
55 kernel_client.stdin_channel.message_received.connect(self._dispatch)
57 kernel_client.stdin_channel.message_received.connect(self._dispatch)
58 # hb_channel
56 kernel_client.hb_channel.kernel_died.connect(self._handle_kernel_died)
59 kernel_client.hb_channel.kernel_died.connect(self._handle_kernel_died)
57
60
58 # Handle the case where the kernel client started channels before
61 # Handle the case where the kernel client started channels before
59 # we connected.
62 # we connected.
60 if kernel_client.channels_running:
63 if kernel_client.channels_running:
61 self._started_channels()
64 self._started_channels()
62
65
63 kernel_client = property(_get_kernel_client, _set_kernel_client)
66 @property
67 def kernel_manager(self):
68 """The kernel manager, if any"""
69 return self._kernel_manager
70
71 @kernel_manager.setter
72 def kernel_manager(self, kernel_manager):
73 old_man = self._kernel_manager
74 if old_man is not None:
75 old_man.kernel_restarted.disconnect(self._handle_kernel_restarted)
76
77 self._kernel_manager = kernel_manager
78 if kernel_manager is None:
79 return
80
81 kernel_manager.kernel_restarted.connect(self._handle_kernel_restarted)
64
82
65 #---------------------------------------------------------------------------
83 #---------------------------------------------------------------------------
66 # 'BaseFrontendMixin' abstract interface
84 # 'BaseFrontendMixin' abstract interface
67 #---------------------------------------------------------------------------
85 #---------------------------------------------------------------------------
68
86
69 def _handle_kernel_died(self, since_last_heartbeat):
87 def _handle_kernel_died(self, since_last_heartbeat):
70 """ This is called when the ``kernel_died`` signal is emitted.
88 """ This is called when the ``kernel_died`` signal is emitted.
71
89
72 This method is called when the kernel heartbeat has not been
90 This method is called when the kernel heartbeat has not been
73 active for a certain amount of time. The typical action will be to
91 active for a certain amount of time.
74 give the user the option of restarting the kernel.
92 This is a strictly passive notification -
93 the kernel is likely being restarted by its KernelManager.
75
94
76 Parameters
95 Parameters
77 ----------
96 ----------
78 since_last_heartbeat : float
97 since_last_heartbeat : float
79 The time since the heartbeat was last received.
98 The time since the heartbeat was last received.
80 """
99 """
81
100
101 def _handle_kernel_restarted(self):
102 """ This is called when the ``kernel_restarted`` signal is emitted.
103
104 This method is called when the kernel has been restarted by the
105 autorestart mechanism.
106
107 Parameters
108 ----------
109 since_last_heartbeat : float
110 The time since the heartbeat was last received.
111 """
82 def _started_kernel(self):
112 def _started_kernel(self):
83 """Called when the KernelManager starts (or restarts) the kernel subprocess.
113 """Called when the KernelManager starts (or restarts) the kernel subprocess.
84 Channels may or may not be running at this point.
114 Channels may or may not be running at this point.
85 """
115 """
86
116
87 def _started_channels(self):
117 def _started_channels(self):
88 """ Called when the KernelManager channels have started listening or
118 """ Called when the KernelManager channels have started listening or
89 when the frontend is assigned an already listening KernelManager.
119 when the frontend is assigned an already listening KernelManager.
90 """
120 """
91
121
92 def _stopped_channels(self):
122 def _stopped_channels(self):
93 """ Called when the KernelManager channels have stopped listening or
123 """ Called when the KernelManager channels have stopped listening or
94 when a listening KernelManager is removed from the frontend.
124 when a listening KernelManager is removed from the frontend.
95 """
125 """
96
126
97 #---------------------------------------------------------------------------
127 #---------------------------------------------------------------------------
98 # 'BaseFrontendMixin' protected interface
128 # 'BaseFrontendMixin' protected interface
99 #---------------------------------------------------------------------------
129 #---------------------------------------------------------------------------
100
130
101 def _dispatch(self, msg):
131 def _dispatch(self, msg):
102 """ Calls the frontend handler associated with the message type of the
132 """ Calls the frontend handler associated with the message type of the
103 given message.
133 given message.
104 """
134 """
105 msg_type = msg['header']['msg_type']
135 msg_type = msg['header']['msg_type']
106 handler = getattr(self, '_handle_' + msg_type, None)
136 handler = getattr(self, '_handle_' + msg_type, None)
107 if handler:
137 if handler:
108 handler(msg)
138 handler(msg)
109
139
110 def _is_from_this_session(self, msg):
140 def _is_from_this_session(self, msg):
111 """ Returns whether a reply from the kernel originated from a request
141 """ Returns whether a reply from the kernel originated from a request
112 from this frontend.
142 from this frontend.
113 """
143 """
114 session = self._kernel_client.session.session
144 session = self._kernel_client.session.session
115 parent = msg['parent_header']
145 parent = msg['parent_header']
116 if not parent:
146 if not parent:
117 # if the message has no parent, assume it is meant for all frontends
147 # if the message has no parent, assume it is meant for all frontends
118 return True
148 return True
119 else:
149 else:
120 return parent.get('session') == session
150 return parent.get('session') == session
General Comments 0
You need to be logged in to leave comments. Login now