##// END OF EJS Templates
Split swallow_argv into standalone function in lib.kernel...
MinRK -
Show More
@@ -0,0 +1,63 b''
1 """Tests for kernel utility functions
2
3 Authors
4 -------
5 * MinRK
6 """
7 #-----------------------------------------------------------------------------
8 # Copyright (c) 2011, the IPython Development Team.
9 #
10 # Distributed under the terms of the Modified BSD License.
11 #
12 # The full license is in the file COPYING.txt, distributed with this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
19 # Stdlib imports
20 from unittest import TestCase
21
22 # Third-party imports
23 import nose.tools as nt
24
25 # Our own imports
26 from IPython.testing import decorators as dec
27 from IPython.lib import kernel
28
29 #-----------------------------------------------------------------------------
30 # Classes and functions
31 #-----------------------------------------------------------------------------
32
33 @dec.parametric
34 def test_swallow_argv():
35 tests = [
36 # expected , argv , aliases, flags
37 (['-a', '5'], ['-a', '5'], None, None),
38 (['5'], ['-a', '5'], None, ['a']),
39 ([], ['-a', '5'], ['a'], None),
40 ([], ['-a', '5'], ['a'], ['a']),
41 ([], ['--foo'], None, ['foo']),
42 (['--foo'], ['--foo'], ['foobar'], []),
43 ([], ['--foo', '5'], ['foo'], []),
44 ([], ['--foo=5'], ['foo'], []),
45 (['--foo=5'], ['--foo=5'], [], ['foo']),
46 (['5'], ['--foo', '5'], [], ['foo']),
47 (['bar'], ['--foo', '5', 'bar'], ['foo'], ['foo']),
48 (['bar'], ['--foo=5', 'bar'], ['foo'], ['foo']),
49 (['5','bar'], ['--foo', '5', 'bar'], None, ['foo']),
50 (['bar'], ['--foo', '5', 'bar'], ['foo'], None),
51 (['bar'], ['--foo=5', 'bar'], ['foo'], None),
52 ]
53 for expected, argv, aliases, flags in tests:
54 stripped = kernel.swallow_argv(argv, aliases=aliases, flags=flags)
55 message = '\n'.join(['',
56 "argv: %r" % argv,
57 "aliases: %r" % aliases,
58 "flags : %r" % flags,
59 "expected : %r" % expected,
60 "returned : %r" % stripped,
61 ])
62 yield nt.assert_equal(expected, stripped, message)
63
@@ -33,7 +33,7 b' import uuid'
33 from IPython.config.application import boolean_flag
33 from IPython.config.application import boolean_flag
34 from IPython.config.configurable import Configurable
34 from IPython.config.configurable import Configurable
35 from IPython.core.profiledir import ProfileDir
35 from IPython.core.profiledir import ProfileDir
36 from IPython.lib.kernel import tunnel_to_kernel, find_connection_file
36 from IPython.lib.kernel import tunnel_to_kernel, find_connection_file, swallow_argv
37 from IPython.zmq.blockingkernelmanager import BlockingKernelManager
37 from IPython.zmq.blockingkernelmanager import BlockingKernelManager
38 from IPython.utils.path import filefind
38 from IPython.utils.path import filefind
39 from IPython.utils.py3compat import str_to_bytes
39 from IPython.utils.py3compat import str_to_bytes
@@ -136,6 +136,9 b' class IPythonConsoleApp(Configurable):'
136 kernel_manager_class = BlockingKernelManager
136 kernel_manager_class = BlockingKernelManager
137
137
138 kernel_argv = List(Unicode)
138 kernel_argv = List(Unicode)
139 # frontend flags&aliases to be stripped when building kernel_argv
140 frontend_flags = Any(app_flags)
141 frontend_aliases = Any(app_aliases)
139
142
140 pure = CBool(False, config=True,
143 pure = CBool(False, config=True,
141 help="Use a pure Python kernel instead of an IPython kernel.")
144 help="Use a pure Python kernel instead of an IPython kernel.")
@@ -182,45 +185,13 b' class IPythonConsoleApp(Configurable):'
182 )
185 )
183
186
184
187
185 def parse_command_line(self, argv=None):
188 def build_kernel_argv(self, argv=None):
186 #super(PythonBaseConsoleApp, self).parse_command_line(argv)
189 """build argv to be passed to kernel subprocess"""
187 # make this stuff after this a function, in case the super stuff goes
188 # away. Also, Min notes that this functionality should be moved to a
189 # generic library of kernel stuff
190 self.swallow_args(app_aliases,app_flags,argv=argv)
191
192 def swallow_args(self, aliases,flags, argv=None):
193 if argv is None:
190 if argv is None:
194 argv = sys.argv[1:]
191 argv = sys.argv[1:]
195 self.kernel_argv = list(argv) # copy
192 self.kernel_argv = swallow_argv(argv, self.frontend_aliases, self.frontend_flags)
196 # kernel should inherit default config file from frontend
193 # kernel should inherit default config file from frontend
197 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
194 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
198 # Scrub frontend-specific flags
199 swallow_next = False
200 was_flag = False
201 for a in argv:
202 if swallow_next:
203 swallow_next = False
204 # last arg was an alias, remove the next one
205 # *unless* the last alias has a no-arg flag version, in which
206 # case, don't swallow the next arg if it's also a flag:
207 if not (was_flag and a.startswith('-')):
208 self.kernel_argv.remove(a)
209 continue
210 if a.startswith('-'):
211 split = a.lstrip('-').split('=')
212 alias = split[0]
213 if alias in aliases:
214 self.kernel_argv.remove(a)
215 if len(split) == 1:
216 # alias passed with arg via space
217 swallow_next = True
218 # could have been a flag that matches an alias, e.g. `existing`
219 # in which case, we might not swallow the next arg
220 was_flag = alias in flags
221 elif alias in flags:
222 # strip flag, but don't swallow next, as flags don't take args
223 self.kernel_argv.remove(a)
224
195
225 def init_connection_file(self):
196 def init_connection_file(self):
226 """find the connection file, and load the info if found.
197 """find the connection file, and load the info if found.
@@ -55,6 +55,7 b' from .notebookmanager import NotebookManager'
55 from IPython.config.application import catch_config_error
55 from IPython.config.application import catch_config_error
56 from IPython.core.application import BaseIPythonApplication
56 from IPython.core.application import BaseIPythonApplication
57 from IPython.core.profiledir import ProfileDir
57 from IPython.core.profiledir import ProfileDir
58 from IPython.lib.kernel import swallow_argv
58 from IPython.zmq.session import Session, default_secure
59 from IPython.zmq.session import Session, default_secure
59 from IPython.zmq.zmqshell import ZMQInteractiveShell
60 from IPython.zmq.zmqshell import ZMQInteractiveShell
60 from IPython.zmq.ipkernel import (
61 from IPython.zmq.ipkernel import (
@@ -283,27 +284,10 b' class NotebookApp(BaseIPythonApplication):'
283 if argv is None:
284 if argv is None:
284 argv = sys.argv[1:]
285 argv = sys.argv[1:]
285
286
286 self.kernel_argv = list(argv) # copy
287 # Scrub frontend-specific flags
288 self.kernel_argv = swallow_argv(argv, notebook_aliases, notebook_flags)
287 # Kernel should inherit default config file from frontend
289 # Kernel should inherit default config file from frontend
288 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
290 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
289 # Scrub frontend-specific flags
290 for a in argv:
291 if a.startswith('-') and a.lstrip('-') in notebook_flags:
292 self.kernel_argv.remove(a)
293 swallow_next = False
294 for a in argv:
295 if swallow_next:
296 self.kernel_argv.remove(a)
297 swallow_next = False
298 continue
299 if a.startswith('-'):
300 split = a.lstrip('-').split('=')
301 alias = split[0]
302 if alias in notebook_aliases:
303 self.kernel_argv.remove(a)
304 if len(split) == 1:
305 # alias passed with arg via space
306 swallow_next = True
307
291
308 def init_configurables(self):
292 def init_configurables(self):
309 # Don't let Qt or ZMQ swallow KeyboardInterupts.
293 # Don't let Qt or ZMQ swallow KeyboardInterupts.
@@ -144,6 +144,8 b' class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):'
144 classes = [IPKernelApp, IPythonWidget, ZMQInteractiveShell, ProfileDir, Session]
144 classes = [IPKernelApp, IPythonWidget, ZMQInteractiveShell, ProfileDir, Session]
145 flags = Dict(flags)
145 flags = Dict(flags)
146 aliases = Dict(aliases)
146 aliases = Dict(aliases)
147 frontend_flags = Any(qt_flags)
148 frontend_aliases = Any(qt_aliases)
147 kernel_manager_class = QtKernelManager
149 kernel_manager_class = QtKernelManager
148
150
149 stylesheet = Unicode('', config=True,
151 stylesheet = Unicode('', config=True,
@@ -169,7 +171,7 b' class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):'
169
171
170 def parse_command_line(self, argv=None):
172 def parse_command_line(self, argv=None):
171 super(IPythonQtConsoleApp, self).parse_command_line(argv)
173 super(IPythonQtConsoleApp, self).parse_command_line(argv)
172 self.swallow_args(qt_aliases,qt_flags,argv=argv)
174 self.build_kernel_argv(argv)
173
175
174
176
175 def new_frontend_master(self):
177 def new_frontend_master(self):
@@ -101,11 +101,14 b' class ZMQTerminalIPythonApp(TerminalIPythonApp, IPythonConsoleApp):'
101 classes = List([IPKernelApp, ZMQTerminalInteractiveShell, Session])
101 classes = List([IPKernelApp, ZMQTerminalInteractiveShell, Session])
102 flags = Dict(flags)
102 flags = Dict(flags)
103 aliases = Dict(aliases)
103 aliases = Dict(aliases)
104 frontend_aliases = Any(frontend_aliases)
105 frontend_flags = Any(frontend_flags)
106
104 subcommands = Dict()
107 subcommands = Dict()
105
108
106 def parse_command_line(self, argv=None):
109 def parse_command_line(self, argv=None):
107 super(ZMQTerminalIPythonApp, self).parse_command_line(argv)
110 super(ZMQTerminalIPythonApp, self).parse_command_line(argv)
108 self.swallow_args(frontend_aliases,frontend_flags,argv=argv)
111 self.build_kernel_argv(argv)
109
112
110 def init_shell(self):
113 def init_shell(self):
111 IPythonConsoleApp.initialize(self)
114 IPythonConsoleApp.initialize(self)
@@ -253,3 +253,63 b' def tunnel_to_kernel(connection_info, sshserver, sshkey=None):'
253 return tuple(lports)
253 return tuple(lports)
254
254
255
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
General Comments 0
You need to be logged in to leave comments. Login now