##// END OF EJS Templates
move IPython.lib.kernel to IPython.utils.kernel...
MinRK -
Show More
@@ -0,0 +1,315 b''
1 """Utilities for connecting to kernels
2
3 Authors:
4
5 * Min Ragan-Kelley
6
7 """
8
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2011 The IPython Development Team
11 #
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
15
16 #-----------------------------------------------------------------------------
17 # Imports
18 #-----------------------------------------------------------------------------
19
20 import glob
21 import json
22 import os
23 import sys
24 from getpass import getpass
25 from subprocess import Popen, PIPE
26
27 # external imports
28 from IPython.external.ssh import tunnel
29
30 # IPython imports
31 from IPython.core.profiledir import ProfileDir
32 from IPython.utils.path import filefind, get_ipython_dir
33 from IPython.utils.py3compat import str_to_bytes
34
35
36 #-----------------------------------------------------------------------------
37 # Functions
38 #-----------------------------------------------------------------------------
39
40 def get_connection_file(app=None):
41 """Return the path to the connection file of an app
42
43 Parameters
44 ----------
45 app : KernelApp instance [optional]
46 If unspecified, the currently running app will be used
47 """
48 if app is None:
49 from IPython.zmq.ipkernel import IPKernelApp
50 if not IPKernelApp.initialized():
51 raise RuntimeError("app not specified, and not in a running Kernel")
52
53 app = IPKernelApp.instance()
54 return filefind(app.connection_file, ['.', app.profile_dir.security_dir])
55
56 def find_connection_file(filename, profile=None):
57 """find a connection file, and return its absolute path.
58
59 The current working directory and the profile's security
60 directory will be searched for the file if it is not given by
61 absolute path.
62
63 If profile is unspecified, then the current running application's
64 profile will be used, or 'default', if not run from IPython.
65
66 If the argument does not match an existing file, it will be interpreted as a
67 fileglob, and the matching file in the profile's security dir with
68 the latest access time will be used.
69
70 Parameters
71 ----------
72 filename : str
73 The connection file or fileglob to search for.
74 profile : str [optional]
75 The name of the profile to use when searching for the connection file,
76 if different from the current IPython session or 'default'.
77
78 Returns
79 -------
80 str : The absolute path of the connection file.
81 """
82 from IPython.core.application import BaseIPythonApplication as IPApp
83 try:
84 # quick check for absolute path, before going through logic
85 return filefind(filename)
86 except IOError:
87 pass
88
89 if profile is None:
90 # profile unspecified, check if running from an IPython app
91 if IPApp.initialized():
92 app = IPApp.instance()
93 profile_dir = app.profile_dir
94 else:
95 # not running in IPython, use default profile
96 profile_dir = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), 'default')
97 else:
98 # find profiledir by profile name:
99 profile_dir = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
100 security_dir = profile_dir.security_dir
101
102 try:
103 # first, try explicit name
104 return filefind(filename, ['.', security_dir])
105 except IOError:
106 pass
107
108 # not found by full name
109
110 if '*' in filename:
111 # given as a glob already
112 pat = filename
113 else:
114 # accept any substring match
115 pat = '*%s*' % filename
116 matches = glob.glob( os.path.join(security_dir, pat) )
117 if not matches:
118 raise IOError("Could not find %r in %r" % (filename, security_dir))
119 elif len(matches) == 1:
120 return matches[0]
121 else:
122 # get most recent match, by access time:
123 return sorted(matches, key=lambda f: os.stat(f).st_atime)[-1]
124
125 def get_connection_info(connection_file=None, unpack=False, profile=None):
126 """Return the connection information for the current Kernel.
127
128 Parameters
129 ----------
130 connection_file : str [optional]
131 The connection file to be used. Can be given by absolute path, or
132 IPython will search in the security directory of a given profile.
133 If run from IPython,
134
135 If unspecified, the connection file for the currently running
136 IPython Kernel will be used, which is only allowed from inside a kernel.
137 unpack : bool [default: False]
138 if True, return the unpacked dict, otherwise just the string contents
139 of the file.
140 profile : str [optional]
141 The name of the profile to use when searching for the connection file,
142 if different from the current IPython session or 'default'.
143
144
145 Returns
146 -------
147 The connection dictionary of the current kernel, as string or dict,
148 depending on `unpack`.
149 """
150 if connection_file is None:
151 # get connection file from current kernel
152 cf = get_connection_file()
153 else:
154 # connection file specified, allow shortnames:
155 cf = find_connection_file(connection_file, profile=profile)
156
157 with open(cf) as f:
158 info = f.read()
159
160 if unpack:
161 info = json.loads(info)
162 # ensure key is bytes:
163 info['key'] = str_to_bytes(info.get('key', ''))
164 return info
165
166 def connect_qtconsole(connection_file=None, argv=None, profile=None):
167 """Connect a qtconsole to the current kernel.
168
169 This is useful for connecting a second qtconsole to a kernel, or to a
170 local notebook.
171
172 Parameters
173 ----------
174 connection_file : str [optional]
175 The connection file to be used. Can be given by absolute path, or
176 IPython will search in the security directory of a given profile.
177 If run from IPython,
178
179 If unspecified, the connection file for the currently running
180 IPython Kernel will be used, which is only allowed from inside a kernel.
181 argv : list [optional]
182 Any extra args to be passed to the console.
183 profile : str [optional]
184 The name of the profile to use when searching for the connection file,
185 if different from the current IPython session or 'default'.
186
187
188 Returns
189 -------
190 subprocess.Popen instance running the qtconsole frontend
191 """
192 argv = [] if argv is None else argv
193
194 if connection_file is None:
195 # get connection file from current kernel
196 cf = get_connection_file()
197 else:
198 cf = find_connection_file(connection_file, profile=profile)
199
200 cmd = ';'.join([
201 "from IPython.frontend.qt.console import qtconsoleapp",
202 "qtconsoleapp.main()"
203 ])
204
205 return Popen([sys.executable, '-c', cmd, '--existing', cf] + argv, stdout=PIPE, stderr=PIPE)
206
207 def tunnel_to_kernel(connection_info, sshserver, sshkey=None):
208 """tunnel connections to a kernel via ssh
209
210 This will open four SSH tunnels from localhost on this machine to the
211 ports associated with the kernel. They can be either direct
212 localhost-localhost tunnels, or if an intermediate server is necessary,
213 the kernel must be listening on a public IP.
214
215 Parameters
216 ----------
217 connection_info : dict or str (path)
218 Either a connection dict, or the path to a JSON connection file
219 sshserver : str
220 The ssh sever to use to tunnel to the kernel. Can be a full
221 `user@server:port` string. ssh config aliases are respected.
222 sshkey : str [optional]
223 Path to file containing ssh key to use for authentication.
224 Only necessary if your ssh config does not already associate
225 a keyfile with the host.
226
227 Returns
228 -------
229
230 (shell, iopub, stdin, hb) : ints
231 The four ports on localhost that have been forwarded to the kernel.
232 """
233 if isinstance(connection_info, basestring):
234 # it's a path, unpack it
235 with open(connection_info) as f:
236 connection_info = json.loads(f.read())
237
238 cf = connection_info
239
240 lports = tunnel.select_random_ports(4)
241 rports = cf['shell_port'], cf['iopub_port'], cf['stdin_port'], cf['hb_port']
242
243 remote_ip = cf['ip']
244
245 if tunnel.try_passwordless_ssh(sshserver, sshkey):
246 password=False
247 else:
248 password = getpass("SSH Password for %s: "%sshserver)
249
250 for lp,rp in zip(lports, rports):
251 tunnel.ssh_tunnel(lp, rp, sshserver, remote_ip, sshkey, password)
252
253 return tuple(lports)
254
255
256 def swallow_argv(argv, aliases=None, flags=None):
257 """strip frontend-specific aliases and flags from an argument list
258
259 For use primarily in frontend apps that want to pass a subset of command-line
260 arguments through to a subprocess, where frontend-specific flags and aliases
261 should be removed from the list.
262
263 Parameters
264 ----------
265
266 argv : list(str)
267 The starting argv, to be filtered
268 aliases : container of aliases (dict, list, set, etc.)
269 The frontend-specific aliases to be removed
270 flags : container of flags (dict, list, set, etc.)
271 The frontend-specific flags to be removed
272
273 Returns
274 -------
275
276 argv : list(str)
277 The argv list, excluding flags and aliases that have been stripped
278 """
279
280 if aliases is None:
281 aliases = set()
282 if flags is None:
283 flags = set()
284
285 stripped = list(argv) # copy
286
287 swallow_next = False
288 was_flag = False
289 for a in argv:
290 if swallow_next:
291 swallow_next = False
292 # last arg was an alias, remove the next one
293 # *unless* the last alias has a no-arg flag version, in which
294 # case, don't swallow the next arg if it's also a flag:
295 if not (was_flag and a.startswith('-')):
296 stripped.remove(a)
297 continue
298 if a.startswith('-'):
299 split = a.lstrip('-').split('=')
300 alias = split[0]
301 if alias in aliases:
302 stripped.remove(a)
303 if len(split) == 1:
304 # alias passed with arg via space
305 swallow_next = True
306 # could have been a flag that matches an alias, e.g. `existing`
307 # in which case, we might not swallow the next arg
308 was_flag = alias in flags
309 elif alias in flags and len(split) == 1:
310 # strip flag, but don't swallow next, as flags don't take args
311 stripped.remove(a)
312
313 # return shortened list
314 return stripped
315
@@ -34,9 +34,9 b' import uuid'
34 34 from IPython.config.application import boolean_flag
35 35 from IPython.config.configurable import Configurable
36 36 from IPython.core.profiledir import ProfileDir
37 from IPython.lib.kernel import tunnel_to_kernel, find_connection_file, swallow_argv
38 37 from IPython.zmq.blockingkernelmanager import BlockingKernelManager
39 38 from IPython.zmq.kernelmanager import KernelManager
39 from IPython.utils.kernel import tunnel_to_kernel, find_connection_file, swallow_argv
40 40 from IPython.utils.path import filefind
41 41 from IPython.utils.py3compat import str_to_bytes
42 42 from IPython.utils.traitlets import (
@@ -61,7 +61,6 b' from IPython.config.application import catch_config_error, boolean_flag'
61 61 from IPython.core.application import BaseIPythonApplication
62 62 from IPython.core.profiledir import ProfileDir
63 63 from IPython.frontend.consoleapp import IPythonConsoleApp
64 from IPython.lib.kernel import swallow_argv
65 64 from IPython.zmq.session import Session, default_secure
66 65 from IPython.zmq.zmqshell import ZMQInteractiveShell
67 66 from IPython.zmq.ipkernel import (
@@ -71,6 +70,7 b' from IPython.zmq.ipkernel import ('
71 70 )
72 71 from IPython.utils.importstring import import_item
73 72 from IPython.utils.localinterfaces import LOCALHOST
73 from IPython.utils.kernel import swallow_argv
74 74 from IPython.utils.traitlets import (
75 75 Dict, Unicode, Integer, List, Enum, Bool,
76 76 DottedObjectName
@@ -59,13 +59,13 b' from IPython.external.qt import QtCore, QtGui'
59 59 from IPython.config.application import boolean_flag, catch_config_error
60 60 from IPython.core.application import BaseIPythonApplication
61 61 from IPython.core.profiledir import ProfileDir
62 from IPython.lib.kernel import tunnel_to_kernel, find_connection_file
63 62 from IPython.frontend.qt.console.frontend_widget import FrontendWidget
64 63 from IPython.frontend.qt.console.ipython_widget import IPythonWidget
65 64 from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
66 65 from IPython.frontend.qt.console import styles
67 66 from IPython.frontend.qt.console.mainwindow import MainWindow
68 67 from IPython.frontend.qt.kernelmanager import QtKernelManager
68 from IPython.utils.kernel import tunnel_to_kernel, find_connection_file
69 69 from IPython.utils.path import filefind
70 70 from IPython.utils.py3compat import str_to_bytes
71 71 from IPython.utils.traitlets import (
@@ -1,315 +1,12 b''
1 """Utilities for connecting to kernels
2
3 Authors:
4
5 * Min Ragan-Kelley
1 """[DEPRECATED] Utilities for connecting to kernels
6 2
3 Moved to IPython.utils.kernel, where it always belonged.
7 4 """
8 5
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2011 The IPython Development Team
11 #
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
15
16 #-----------------------------------------------------------------------------
17 # Imports
18 #-----------------------------------------------------------------------------
19
20 import glob
21 import json
22 import os
23 import sys
24 from getpass import getpass
25 from subprocess import Popen, PIPE
26
27 # external imports
28 from IPython.external.ssh import tunnel
29
30 # IPython imports
31 from IPython.core.profiledir import ProfileDir
32 from IPython.utils.path import filefind, get_ipython_dir
33 from IPython.utils.py3compat import str_to_bytes
34
35
36 #-----------------------------------------------------------------------------
37 # Functions
38 #-----------------------------------------------------------------------------
39
40 def get_connection_file(app=None):
41 """Return the path to the connection file of an app
42
43 Parameters
44 ----------
45 app : KernelApp instance [optional]
46 If unspecified, the currently running app will be used
47 """
48 if app is None:
49 from IPython.zmq.ipkernel import IPKernelApp
50 if not IPKernelApp.initialized():
51 raise RuntimeError("app not specified, and not in a running Kernel")
52
53 app = IPKernelApp.instance()
54 return filefind(app.connection_file, ['.', app.profile_dir.security_dir])
55
56 def find_connection_file(filename, profile=None):
57 """find a connection file, and return its absolute path.
58
59 The current working directory and the profile's security
60 directory will be searched for the file if it is not given by
61 absolute path.
62
63 If profile is unspecified, then the current running application's
64 profile will be used, or 'default', if not run from IPython.
65
66 If the argument does not match an existing file, it will be interpreted as a
67 fileglob, and the matching file in the profile's security dir with
68 the latest access time will be used.
69
70 Parameters
71 ----------
72 filename : str
73 The connection file or fileglob to search for.
74 profile : str [optional]
75 The name of the profile to use when searching for the connection file,
76 if different from the current IPython session or 'default'.
77
78 Returns
79 -------
80 str : The absolute path of the connection file.
81 """
82 from IPython.core.application import BaseIPythonApplication as IPApp
83 try:
84 # quick check for absolute path, before going through logic
85 return filefind(filename)
86 except IOError:
87 pass
88
89 if profile is None:
90 # profile unspecified, check if running from an IPython app
91 if IPApp.initialized():
92 app = IPApp.instance()
93 profile_dir = app.profile_dir
94 else:
95 # not running in IPython, use default profile
96 profile_dir = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), 'default')
97 else:
98 # find profiledir by profile name:
99 profile_dir = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
100 security_dir = profile_dir.security_dir
101
102 try:
103 # first, try explicit name
104 return filefind(filename, ['.', security_dir])
105 except IOError:
106 pass
107
108 # not found by full name
109
110 if '*' in filename:
111 # given as a glob already
112 pat = filename
113 else:
114 # accept any substring match
115 pat = '*%s*' % filename
116 matches = glob.glob( os.path.join(security_dir, pat) )
117 if not matches:
118 raise IOError("Could not find %r in %r" % (filename, security_dir))
119 elif len(matches) == 1:
120 return matches[0]
121 else:
122 # get most recent match, by access time:
123 return sorted(matches, key=lambda f: os.stat(f).st_atime)[-1]
124
125 def get_connection_info(connection_file=None, unpack=False, profile=None):
126 """Return the connection information for the current Kernel.
127
128 Parameters
129 ----------
130 connection_file : str [optional]
131 The connection file to be used. Can be given by absolute path, or
132 IPython will search in the security directory of a given profile.
133 If run from IPython,
134
135 If unspecified, the connection file for the currently running
136 IPython Kernel will be used, which is only allowed from inside a kernel.
137 unpack : bool [default: False]
138 if True, return the unpacked dict, otherwise just the string contents
139 of the file.
140 profile : str [optional]
141 The name of the profile to use when searching for the connection file,
142 if different from the current IPython session or 'default'.
143
144
145 Returns
146 -------
147 The connection dictionary of the current kernel, as string or dict,
148 depending on `unpack`.
149 """
150 if connection_file is None:
151 # get connection file from current kernel
152 cf = get_connection_file()
153 else:
154 # connection file specified, allow shortnames:
155 cf = find_connection_file(connection_file, profile=profile)
156
157 with open(cf) as f:
158 info = f.read()
159
160 if unpack:
161 info = json.loads(info)
162 # ensure key is bytes:
163 info['key'] = str_to_bytes(info.get('key', ''))
164 return info
165
166 def connect_qtconsole(connection_file=None, argv=None, profile=None):
167 """Connect a qtconsole to the current kernel.
168
169 This is useful for connecting a second qtconsole to a kernel, or to a
170 local notebook.
171
172 Parameters
173 ----------
174 connection_file : str [optional]
175 The connection file to be used. Can be given by absolute path, or
176 IPython will search in the security directory of a given profile.
177 If run from IPython,
178
179 If unspecified, the connection file for the currently running
180 IPython Kernel will be used, which is only allowed from inside a kernel.
181 argv : list [optional]
182 Any extra args to be passed to the console.
183 profile : str [optional]
184 The name of the profile to use when searching for the connection file,
185 if different from the current IPython session or 'default'.
186
187
188 Returns
189 -------
190 subprocess.Popen instance running the qtconsole frontend
191 """
192 argv = [] if argv is None else argv
193
194 if connection_file is None:
195 # get connection file from current kernel
196 cf = get_connection_file()
197 else:
198 cf = find_connection_file(connection_file, profile=profile)
199
200 cmd = ';'.join([
201 "from IPython.frontend.qt.console import qtconsoleapp",
202 "qtconsoleapp.main()"
203 ])
204
205 return Popen([sys.executable, '-c', cmd, '--existing', cf] + argv, stdout=PIPE, stderr=PIPE)
206
207 def tunnel_to_kernel(connection_info, sshserver, sshkey=None):
208 """tunnel connections to a kernel via ssh
209
210 This will open four SSH tunnels from localhost on this machine to the
211 ports associated with the kernel. They can be either direct
212 localhost-localhost tunnels, or if an intermediate server is necessary,
213 the kernel must be listening on a public IP.
214
215 Parameters
216 ----------
217 connection_info : dict or str (path)
218 Either a connection dict, or the path to a JSON connection file
219 sshserver : str
220 The ssh sever to use to tunnel to the kernel. Can be a full
221 `user@server:port` string. ssh config aliases are respected.
222 sshkey : str [optional]
223 Path to file containing ssh key to use for authentication.
224 Only necessary if your ssh config does not already associate
225 a keyfile with the host.
226
227 Returns
228 -------
229
230 (shell, iopub, stdin, hb) : ints
231 The four ports on localhost that have been forwarded to the kernel.
232 """
233 if isinstance(connection_info, basestring):
234 # it's a path, unpack it
235 with open(connection_info) as f:
236 connection_info = json.loads(f.read())
237
238 cf = connection_info
239
240 lports = tunnel.select_random_ports(4)
241 rports = cf['shell_port'], cf['iopub_port'], cf['stdin_port'], cf['hb_port']
242
243 remote_ip = cf['ip']
244
245 if tunnel.try_passwordless_ssh(sshserver, sshkey):
246 password=False
247 else:
248 password = getpass("SSH Password for %s: "%sshserver)
249
250 for lp,rp in zip(lports, rports):
251 tunnel.ssh_tunnel(lp, rp, sshserver, remote_ip, sshkey, password)
252
253 return tuple(lports)
254
6 import warnings
7 warnings.warn("IPython.lib.kernel moved to IPython.utils.kernel in IPython 0.14",
8 DeprecationWarning
9 )
255 10
256 def swallow_argv(argv, aliases=None, flags=None):
257 """strip frontend-specific aliases and flags from an argument list
258
259 For use primarily in frontend apps that want to pass a subset of command-line
260 arguments through to a subprocess, where frontend-specific flags and aliases
261 should be removed from the list.
262
263 Parameters
264 ----------
265
266 argv : list(str)
267 The starting argv, to be filtered
268 aliases : container of aliases (dict, list, set, etc.)
269 The frontend-specific aliases to be removed
270 flags : container of flags (dict, list, set, etc.)
271 The frontend-specific flags to be removed
272
273 Returns
274 -------
275
276 argv : list(str)
277 The argv list, excluding flags and aliases that have been stripped
278 """
279
280 if aliases is None:
281 aliases = set()
282 if flags is None:
283 flags = set()
284
285 stripped = list(argv) # copy
286
287 swallow_next = False
288 was_flag = False
289 for a in argv:
290 if swallow_next:
291 swallow_next = False
292 # last arg was an alias, remove the next one
293 # *unless* the last alias has a no-arg flag version, in which
294 # case, don't swallow the next arg if it's also a flag:
295 if not (was_flag and a.startswith('-')):
296 stripped.remove(a)
297 continue
298 if a.startswith('-'):
299 split = a.lstrip('-').split('=')
300 alias = split[0]
301 if alias in aliases:
302 stripped.remove(a)
303 if len(split) == 1:
304 # alias passed with arg via space
305 swallow_next = True
306 # could have been a flag that matches an alias, e.g. `existing`
307 # in which case, we might not swallow the next arg
308 was_flag = alias in flags
309 elif alias in flags and len(split) == 1:
310 # strip flag, but don't swallow next, as flags don't take args
311 stripped.remove(a)
312
313 # return shortened list
314 return stripped
11 from IPython.utils.kernel import *
315 12
@@ -24,7 +24,7 b' import nose.tools as nt'
24 24
25 25 # Our own imports
26 26 from IPython.testing import decorators as dec
27 from IPython.lib import kernel
27 from IPython.utils import kernel
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Classes and functions
@@ -35,7 +35,7 b' from IPython.core.magics import MacroToEdit, CodeMagics'
35 35 from IPython.core.magic import magics_class, line_magic, Magics
36 36 from IPython.core.payloadpage import install_payload_page
37 37 from IPython.inprocess.socket import SocketABC
38 from IPython.lib.kernel import (
38 from IPython.utils.kernel import (
39 39 get_connection_file, get_connection_info, connect_qtconsole
40 40 )
41 41 from IPython.testing.skipdoctest import skip_doctest
General Comments 0
You need to be logged in to leave comments. Login now