##// END OF EJS Templates
add missing KernelManager to ConsoleApp class list
MinRK -
Show More
@@ -1,361 +1,362
1 """ A minimal application base mixin for all ZMQ based IPython frontends.
1 """ A minimal application base mixin for all ZMQ based IPython frontends.
2
2
3 This is not a complete console app, as subprocess will not be able to receive
3 This is not a complete console app, as subprocess will not be able to receive
4 input, there is no real readline support, among other limitations. This is a
4 input, there is no real readline support, among other limitations. This is a
5 refactoring of what used to be the IPython/frontend/qt/console/qtconsoleapp.py
5 refactoring of what used to be the IPython/frontend/qt/console/qtconsoleapp.py
6
6
7 Authors:
7 Authors:
8
8
9 * Evan Patterson
9 * Evan Patterson
10 * Min RK
10 * Min RK
11 * Erik Tollerud
11 * Erik Tollerud
12 * Fernando Perez
12 * Fernando Perez
13 * Bussonnier Matthias
13 * Bussonnier Matthias
14 * Thomas Kluyver
14 * Thomas Kluyver
15 * Paul Ivanov
15 * Paul Ivanov
16
16
17 """
17 """
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 # stdlib imports
23 # stdlib imports
24 import atexit
24 import atexit
25 import json
25 import json
26 import os
26 import os
27 import shutil
27 import shutil
28 import signal
28 import signal
29 import sys
29 import sys
30 import uuid
30 import uuid
31
31
32
32
33 # Local imports
33 # Local imports
34 from IPython.config.application import boolean_flag
34 from IPython.config.application import boolean_flag
35 from IPython.config.configurable import Configurable
35 from IPython.config.configurable import Configurable
36 from IPython.core.profiledir import ProfileDir
36 from IPython.core.profiledir import ProfileDir
37 from IPython.lib.kernel import tunnel_to_kernel, find_connection_file, swallow_argv
37 from IPython.lib.kernel import tunnel_to_kernel, find_connection_file, swallow_argv
38 from IPython.zmq.blockingkernelmanager import BlockingKernelManager
38 from IPython.zmq.blockingkernelmanager import BlockingKernelManager
39 from IPython.zmq.kernelmanager import KernelManager
39 from IPython.utils.path import filefind
40 from IPython.utils.path import filefind
40 from IPython.utils.py3compat import str_to_bytes
41 from IPython.utils.py3compat import str_to_bytes
41 from IPython.utils.traitlets import (
42 from IPython.utils.traitlets import (
42 Dict, List, Unicode, CUnicode, Int, CBool, Any, CaselessStrEnum
43 Dict, List, Unicode, CUnicode, Int, CBool, Any, CaselessStrEnum
43 )
44 )
44 from IPython.zmq.ipkernel import (
45 from IPython.zmq.ipkernel import (
45 flags as ipkernel_flags,
46 flags as ipkernel_flags,
46 aliases as ipkernel_aliases,
47 aliases as ipkernel_aliases,
47 IPKernelApp
48 IPKernelApp
48 )
49 )
49 from IPython.zmq.session import Session, default_secure
50 from IPython.zmq.session import Session, default_secure
50 from IPython.zmq.zmqshell import ZMQInteractiveShell
51 from IPython.zmq.zmqshell import ZMQInteractiveShell
51
52
52 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
53 # Network Constants
54 # Network Constants
54 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
55
56
56 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
57 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
57
58
58 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
59 # Globals
60 # Globals
60 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
61
62
62
63
63 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
64 # Aliases and Flags
65 # Aliases and Flags
65 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
66
67
67 flags = dict(ipkernel_flags)
68 flags = dict(ipkernel_flags)
68
69
69 # the flags that are specific to the frontend
70 # the flags that are specific to the frontend
70 # these must be scrubbed before being passed to the kernel,
71 # these must be scrubbed before being passed to the kernel,
71 # or it will raise an error on unrecognized flags
72 # or it will raise an error on unrecognized flags
72 app_flags = {
73 app_flags = {
73 'existing' : ({'IPythonConsoleApp' : {'existing' : 'kernel*.json'}},
74 'existing' : ({'IPythonConsoleApp' : {'existing' : 'kernel*.json'}},
74 "Connect to an existing kernel. If no argument specified, guess most recent"),
75 "Connect to an existing kernel. If no argument specified, guess most recent"),
75 }
76 }
76 app_flags.update(boolean_flag(
77 app_flags.update(boolean_flag(
77 'confirm-exit', 'IPythonConsoleApp.confirm_exit',
78 'confirm-exit', 'IPythonConsoleApp.confirm_exit',
78 """Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',
79 """Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',
79 to force a direct exit without any confirmation.
80 to force a direct exit without any confirmation.
80 """,
81 """,
81 """Don't prompt the user when exiting. This will terminate the kernel
82 """Don't prompt the user when exiting. This will terminate the kernel
82 if it is owned by the frontend, and leave it alive if it is external.
83 if it is owned by the frontend, and leave it alive if it is external.
83 """
84 """
84 ))
85 ))
85 flags.update(app_flags)
86 flags.update(app_flags)
86
87
87 aliases = dict(ipkernel_aliases)
88 aliases = dict(ipkernel_aliases)
88
89
89 # also scrub aliases from the frontend
90 # also scrub aliases from the frontend
90 app_aliases = dict(
91 app_aliases = dict(
91 ip = 'KernelManager.ip',
92 ip = 'KernelManager.ip',
92 transport = 'KernelManager.transport',
93 transport = 'KernelManager.transport',
93 hb = 'IPythonConsoleApp.hb_port',
94 hb = 'IPythonConsoleApp.hb_port',
94 shell = 'IPythonConsoleApp.shell_port',
95 shell = 'IPythonConsoleApp.shell_port',
95 iopub = 'IPythonConsoleApp.iopub_port',
96 iopub = 'IPythonConsoleApp.iopub_port',
96 stdin = 'IPythonConsoleApp.stdin_port',
97 stdin = 'IPythonConsoleApp.stdin_port',
97 existing = 'IPythonConsoleApp.existing',
98 existing = 'IPythonConsoleApp.existing',
98 f = 'IPythonConsoleApp.connection_file',
99 f = 'IPythonConsoleApp.connection_file',
99
100
100
101
101 ssh = 'IPythonConsoleApp.sshserver',
102 ssh = 'IPythonConsoleApp.sshserver',
102 )
103 )
103 aliases.update(app_aliases)
104 aliases.update(app_aliases)
104
105
105 #-----------------------------------------------------------------------------
106 #-----------------------------------------------------------------------------
106 # Classes
107 # Classes
107 #-----------------------------------------------------------------------------
108 #-----------------------------------------------------------------------------
108
109
109 #-----------------------------------------------------------------------------
110 #-----------------------------------------------------------------------------
110 # IPythonConsole
111 # IPythonConsole
111 #-----------------------------------------------------------------------------
112 #-----------------------------------------------------------------------------
112
113
113 classes = [IPKernelApp, ZMQInteractiveShell, ProfileDir, Session]
114 classes = [IPKernelApp, ZMQInteractiveShell, KernelManager, ProfileDir, Session]
114
115
115 try:
116 try:
116 from IPython.zmq.pylab.backend_inline import InlineBackend
117 from IPython.zmq.pylab.backend_inline import InlineBackend
117 except ImportError:
118 except ImportError:
118 pass
119 pass
119 else:
120 else:
120 classes.append(InlineBackend)
121 classes.append(InlineBackend)
121
122
122 class IPythonConsoleApp(Configurable):
123 class IPythonConsoleApp(Configurable):
123 name = 'ipython-console-mixin'
124 name = 'ipython-console-mixin'
124 default_config_file_name='ipython_config.py'
125 default_config_file_name='ipython_config.py'
125
126
126 description = """
127 description = """
127 The IPython Mixin Console.
128 The IPython Mixin Console.
128
129
129 This class contains the common portions of console client (QtConsole,
130 This class contains the common portions of console client (QtConsole,
130 ZMQ-based terminal console, etc). It is not a full console, in that
131 ZMQ-based terminal console, etc). It is not a full console, in that
131 launched terminal subprocesses will not be able to accept input.
132 launched terminal subprocesses will not be able to accept input.
132
133
133 The Console using this mixing supports various extra features beyond
134 The Console using this mixing supports various extra features beyond
134 the single-process Terminal IPython shell, such as connecting to
135 the single-process Terminal IPython shell, such as connecting to
135 existing kernel, via:
136 existing kernel, via:
136
137
137 ipython <appname> --existing
138 ipython <appname> --existing
138
139
139 as well as tunnel via SSH
140 as well as tunnel via SSH
140
141
141 """
142 """
142
143
143 classes = classes
144 classes = classes
144 flags = Dict(flags)
145 flags = Dict(flags)
145 aliases = Dict(aliases)
146 aliases = Dict(aliases)
146 kernel_manager_class = BlockingKernelManager
147 kernel_manager_class = BlockingKernelManager
147
148
148 kernel_argv = List(Unicode)
149 kernel_argv = List(Unicode)
149 # frontend flags&aliases to be stripped when building kernel_argv
150 # frontend flags&aliases to be stripped when building kernel_argv
150 frontend_flags = Any(app_flags)
151 frontend_flags = Any(app_flags)
151 frontend_aliases = Any(app_aliases)
152 frontend_aliases = Any(app_aliases)
152
153
153 # create requested profiles by default, if they don't exist:
154 # create requested profiles by default, if they don't exist:
154 auto_create = CBool(True)
155 auto_create = CBool(True)
155 # connection info:
156 # connection info:
156
157
157 sshserver = Unicode('', config=True,
158 sshserver = Unicode('', config=True,
158 help="""The SSH server to use to connect to the kernel.""")
159 help="""The SSH server to use to connect to the kernel.""")
159 sshkey = Unicode('', config=True,
160 sshkey = Unicode('', config=True,
160 help="""Path to the ssh key to use for logging in to the ssh server.""")
161 help="""Path to the ssh key to use for logging in to the ssh server.""")
161
162
162 hb_port = Int(0, config=True,
163 hb_port = Int(0, config=True,
163 help="set the heartbeat port [default: random]")
164 help="set the heartbeat port [default: random]")
164 shell_port = Int(0, config=True,
165 shell_port = Int(0, config=True,
165 help="set the shell (ROUTER) port [default: random]")
166 help="set the shell (ROUTER) port [default: random]")
166 iopub_port = Int(0, config=True,
167 iopub_port = Int(0, config=True,
167 help="set the iopub (PUB) port [default: random]")
168 help="set the iopub (PUB) port [default: random]")
168 stdin_port = Int(0, config=True,
169 stdin_port = Int(0, config=True,
169 help="set the stdin (DEALER) port [default: random]")
170 help="set the stdin (DEALER) port [default: random]")
170 connection_file = Unicode('', config=True,
171 connection_file = Unicode('', config=True,
171 help="""JSON file in which to store connection info [default: kernel-<pid>.json]
172 help="""JSON file in which to store connection info [default: kernel-<pid>.json]
172
173
173 This file will contain the IP, ports, and authentication key needed to connect
174 This file will contain the IP, ports, and authentication key needed to connect
174 clients to this kernel. By default, this file will be created in the security-dir
175 clients to this kernel. By default, this file will be created in the security-dir
175 of the current profile, but can be specified by absolute path.
176 of the current profile, but can be specified by absolute path.
176 """)
177 """)
177 def _connection_file_default(self):
178 def _connection_file_default(self):
178 return 'kernel-%i.json' % os.getpid()
179 return 'kernel-%i.json' % os.getpid()
179
180
180 existing = CUnicode('', config=True,
181 existing = CUnicode('', config=True,
181 help="""Connect to an already running kernel""")
182 help="""Connect to an already running kernel""")
182
183
183 confirm_exit = CBool(True, config=True,
184 confirm_exit = CBool(True, config=True,
184 help="""
185 help="""
185 Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',
186 Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',
186 to force a direct exit without any confirmation.""",
187 to force a direct exit without any confirmation.""",
187 )
188 )
188
189
189
190
190 def build_kernel_argv(self, argv=None):
191 def build_kernel_argv(self, argv=None):
191 """build argv to be passed to kernel subprocess"""
192 """build argv to be passed to kernel subprocess"""
192 if argv is None:
193 if argv is None:
193 argv = sys.argv[1:]
194 argv = sys.argv[1:]
194 self.kernel_argv = swallow_argv(argv, self.frontend_aliases, self.frontend_flags)
195 self.kernel_argv = swallow_argv(argv, self.frontend_aliases, self.frontend_flags)
195 # kernel should inherit default config file from frontend
196 # kernel should inherit default config file from frontend
196 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
197 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
197
198
198 def init_connection_file(self):
199 def init_connection_file(self):
199 """find the connection file, and load the info if found.
200 """find the connection file, and load the info if found.
200
201
201 The current working directory and the current profile's security
202 The current working directory and the current profile's security
202 directory will be searched for the file if it is not given by
203 directory will be searched for the file if it is not given by
203 absolute path.
204 absolute path.
204
205
205 When attempting to connect to an existing kernel and the `--existing`
206 When attempting to connect to an existing kernel and the `--existing`
206 argument does not match an existing file, it will be interpreted as a
207 argument does not match an existing file, it will be interpreted as a
207 fileglob, and the matching file in the current profile's security dir
208 fileglob, and the matching file in the current profile's security dir
208 with the latest access time will be used.
209 with the latest access time will be used.
209
210
210 After this method is called, self.connection_file contains the *full path*
211 After this method is called, self.connection_file contains the *full path*
211 to the connection file, never just its name.
212 to the connection file, never just its name.
212 """
213 """
213 if self.existing:
214 if self.existing:
214 try:
215 try:
215 cf = find_connection_file(self.existing)
216 cf = find_connection_file(self.existing)
216 except Exception:
217 except Exception:
217 self.log.critical("Could not find existing kernel connection file %s", self.existing)
218 self.log.critical("Could not find existing kernel connection file %s", self.existing)
218 self.exit(1)
219 self.exit(1)
219 self.log.info("Connecting to existing kernel: %s" % cf)
220 self.log.info("Connecting to existing kernel: %s" % cf)
220 self.connection_file = cf
221 self.connection_file = cf
221 else:
222 else:
222 # not existing, check if we are going to write the file
223 # not existing, check if we are going to write the file
223 # and ensure that self.connection_file is a full path, not just the shortname
224 # and ensure that self.connection_file is a full path, not just the shortname
224 try:
225 try:
225 cf = find_connection_file(self.connection_file)
226 cf = find_connection_file(self.connection_file)
226 except Exception:
227 except Exception:
227 # file might not exist
228 # file might not exist
228 if self.connection_file == os.path.basename(self.connection_file):
229 if self.connection_file == os.path.basename(self.connection_file):
229 # just shortname, put it in security dir
230 # just shortname, put it in security dir
230 cf = os.path.join(self.profile_dir.security_dir, self.connection_file)
231 cf = os.path.join(self.profile_dir.security_dir, self.connection_file)
231 else:
232 else:
232 cf = self.connection_file
233 cf = self.connection_file
233 self.connection_file = cf
234 self.connection_file = cf
234
235
235 # should load_connection_file only be used for existing?
236 # should load_connection_file only be used for existing?
236 # as it is now, this allows reusing ports if an existing
237 # as it is now, this allows reusing ports if an existing
237 # file is requested
238 # file is requested
238 try:
239 try:
239 self.load_connection_file()
240 self.load_connection_file()
240 except Exception:
241 except Exception:
241 self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
242 self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
242 self.exit(1)
243 self.exit(1)
243
244
244 def load_connection_file(self):
245 def load_connection_file(self):
245 """load ip/port/hmac config from JSON connection file"""
246 """load ip/port/hmac config from JSON connection file"""
246 # this is identical to KernelApp.load_connection_file
247 # this is identical to KernelApp.load_connection_file
247 # perhaps it can be centralized somewhere?
248 # perhaps it can be centralized somewhere?
248 try:
249 try:
249 fname = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
250 fname = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
250 except IOError:
251 except IOError:
251 self.log.debug("Connection File not found: %s", self.connection_file)
252 self.log.debug("Connection File not found: %s", self.connection_file)
252 return
253 return
253 self.log.debug(u"Loading connection file %s", fname)
254 self.log.debug(u"Loading connection file %s", fname)
254 with open(fname) as f:
255 with open(fname) as f:
255 cfg = json.load(f)
256 cfg = json.load(f)
256
257
257 self.config.KernelManager.transport = cfg.get('transport', 'tcp')
258 self.config.KernelManager.transport = cfg.get('transport', 'tcp')
258 self.config.KernelManager.ip = cfg.get('ip', LOCALHOST)
259 self.config.KernelManager.ip = cfg.get('ip', LOCALHOST)
259
260
260 for channel in ('hb', 'shell', 'iopub', 'stdin'):
261 for channel in ('hb', 'shell', 'iopub', 'stdin'):
261 name = channel + '_port'
262 name = channel + '_port'
262 if getattr(self, name) == 0 and name in cfg:
263 if getattr(self, name) == 0 and name in cfg:
263 # not overridden by config or cl_args
264 # not overridden by config or cl_args
264 setattr(self, name, cfg[name])
265 setattr(self, name, cfg[name])
265 if 'key' in cfg:
266 if 'key' in cfg:
266 self.config.Session.key = str_to_bytes(cfg['key'])
267 self.config.Session.key = str_to_bytes(cfg['key'])
267
268
268 def init_ssh(self):
269 def init_ssh(self):
269 """set up ssh tunnels, if needed."""
270 """set up ssh tunnels, if needed."""
270 if not self.existing or (not self.sshserver and not self.sshkey):
271 if not self.existing or (not self.sshserver and not self.sshkey):
271 return
272 return
272
273
273 self.load_connection_file()
274 self.load_connection_file()
274
275
275 transport = self.config.KernelManager.transport
276 transport = self.config.KernelManager.transport
276 ip = self.config.KernelManager.ip
277 ip = self.config.KernelManager.ip
277
278
278 if transport != 'tcp':
279 if transport != 'tcp':
279 self.log.error("Can only use ssh tunnels with TCP sockets, not %s", transport)
280 self.log.error("Can only use ssh tunnels with TCP sockets, not %s", transport)
280 sys.exit(-1)
281 sys.exit(-1)
281
282
282 if self.sshkey and not self.sshserver:
283 if self.sshkey and not self.sshserver:
283 # specifying just the key implies that we are connecting directly
284 # specifying just the key implies that we are connecting directly
284 self.sshserver = ip
285 self.sshserver = ip
285 ip = LOCALHOST
286 ip = LOCALHOST
286
287
287 # build connection dict for tunnels:
288 # build connection dict for tunnels:
288 info = dict(ip=ip,
289 info = dict(ip=ip,
289 shell_port=self.shell_port,
290 shell_port=self.shell_port,
290 iopub_port=self.iopub_port,
291 iopub_port=self.iopub_port,
291 stdin_port=self.stdin_port,
292 stdin_port=self.stdin_port,
292 hb_port=self.hb_port
293 hb_port=self.hb_port
293 )
294 )
294
295
295 self.log.info("Forwarding connections to %s via %s"%(ip, self.sshserver))
296 self.log.info("Forwarding connections to %s via %s"%(ip, self.sshserver))
296
297
297 # tunnels return a new set of ports, which will be on localhost:
298 # tunnels return a new set of ports, which will be on localhost:
298 self.config.KernelManager.ip = LOCALHOST
299 self.config.KernelManager.ip = LOCALHOST
299 try:
300 try:
300 newports = tunnel_to_kernel(info, self.sshserver, self.sshkey)
301 newports = tunnel_to_kernel(info, self.sshserver, self.sshkey)
301 except:
302 except:
302 # even catch KeyboardInterrupt
303 # even catch KeyboardInterrupt
303 self.log.error("Could not setup tunnels", exc_info=True)
304 self.log.error("Could not setup tunnels", exc_info=True)
304 self.exit(1)
305 self.exit(1)
305
306
306 self.shell_port, self.iopub_port, self.stdin_port, self.hb_port = newports
307 self.shell_port, self.iopub_port, self.stdin_port, self.hb_port = newports
307
308
308 cf = self.connection_file
309 cf = self.connection_file
309 base,ext = os.path.splitext(cf)
310 base,ext = os.path.splitext(cf)
310 base = os.path.basename(base)
311 base = os.path.basename(base)
311 self.connection_file = os.path.basename(base)+'-ssh'+ext
312 self.connection_file = os.path.basename(base)+'-ssh'+ext
312 self.log.critical("To connect another client via this tunnel, use:")
313 self.log.critical("To connect another client via this tunnel, use:")
313 self.log.critical("--existing %s" % self.connection_file)
314 self.log.critical("--existing %s" % self.connection_file)
314
315
315 def _new_connection_file(self):
316 def _new_connection_file(self):
316 cf = ''
317 cf = ''
317 while not cf:
318 while not cf:
318 # we don't need a 128b id to distinguish kernels, use more readable
319 # we don't need a 128b id to distinguish kernels, use more readable
319 # 48b node segment (12 hex chars). Users running more than 32k simultaneous
320 # 48b node segment (12 hex chars). Users running more than 32k simultaneous
320 # kernels can subclass.
321 # kernels can subclass.
321 ident = str(uuid.uuid4()).split('-')[-1]
322 ident = str(uuid.uuid4()).split('-')[-1]
322 cf = os.path.join(self.profile_dir.security_dir, 'kernel-%s.json' % ident)
323 cf = os.path.join(self.profile_dir.security_dir, 'kernel-%s.json' % ident)
323 # only keep if it's actually new. Protect against unlikely collision
324 # only keep if it's actually new. Protect against unlikely collision
324 # in 48b random search space
325 # in 48b random search space
325 cf = cf if not os.path.exists(cf) else ''
326 cf = cf if not os.path.exists(cf) else ''
326 return cf
327 return cf
327
328
328 def init_kernel_manager(self):
329 def init_kernel_manager(self):
329 # Don't let Qt or ZMQ swallow KeyboardInterupts.
330 # Don't let Qt or ZMQ swallow KeyboardInterupts.
330 signal.signal(signal.SIGINT, signal.SIG_DFL)
331 signal.signal(signal.SIGINT, signal.SIG_DFL)
331
332
332 # Create a KernelManager and start a kernel.
333 # Create a KernelManager and start a kernel.
333 self.kernel_manager = self.kernel_manager_class(
334 self.kernel_manager = self.kernel_manager_class(
334 shell_port=self.shell_port,
335 shell_port=self.shell_port,
335 iopub_port=self.iopub_port,
336 iopub_port=self.iopub_port,
336 stdin_port=self.stdin_port,
337 stdin_port=self.stdin_port,
337 hb_port=self.hb_port,
338 hb_port=self.hb_port,
338 connection_file=self.connection_file,
339 connection_file=self.connection_file,
339 config=self.config,
340 config=self.config,
340 )
341 )
341 # start the kernel
342 # start the kernel
342 if not self.existing:
343 if not self.existing:
343 self.kernel_manager.start_kernel(extra_arguments=self.kernel_argv)
344 self.kernel_manager.start_kernel(extra_arguments=self.kernel_argv)
344 atexit.register(self.kernel_manager.cleanup_ipc_files)
345 atexit.register(self.kernel_manager.cleanup_ipc_files)
345 elif self.sshserver:
346 elif self.sshserver:
346 # ssh, write new connection file
347 # ssh, write new connection file
347 self.kernel_manager.write_connection_file()
348 self.kernel_manager.write_connection_file()
348 atexit.register(self.kernel_manager.cleanup_connection_file)
349 atexit.register(self.kernel_manager.cleanup_connection_file)
349 self.kernel_manager.start_channels()
350 self.kernel_manager.start_channels()
350
351
351
352
352 def initialize(self, argv=None):
353 def initialize(self, argv=None):
353 """
354 """
354 Classes which mix this class in should call:
355 Classes which mix this class in should call:
355 IPythonConsoleApp.initialize(self,argv)
356 IPythonConsoleApp.initialize(self,argv)
356 """
357 """
357 self.init_connection_file()
358 self.init_connection_file()
358 default_secure(self.config)
359 default_secure(self.config)
359 self.init_ssh()
360 self.init_ssh()
360 self.init_kernel_manager()
361 self.init_kernel_manager()
361
362
General Comments 0
You need to be logged in to leave comments. Login now