##// END OF EJS Templates
Merge pull request #2165 from tkf/run-glob...
Bradley M. Froehle -
r8544:e54a60bc merge
parent child Browse files
Show More
@@ -0,0 +1,2 b''
1 import sys
2 print sys.argv[1:]
@@ -44,10 +44,11 b' from IPython.utils import py3compat'
44 from IPython.utils.io import capture_output
44 from IPython.utils.io import capture_output
45 from IPython.utils.ipstruct import Struct
45 from IPython.utils.ipstruct import Struct
46 from IPython.utils.module_paths import find_mod
46 from IPython.utils.module_paths import find_mod
47 from IPython.utils.path import get_py_filename, unquote_filename
47 from IPython.utils.path import get_py_filename, unquote_filename, shellglob
48 from IPython.utils.timing import clock, clock2
48 from IPython.utils.timing import clock, clock2
49 from IPython.utils.warn import warn, error
49 from IPython.utils.warn import warn, error
50
50
51
51 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
52 # Magic implementation classes
53 # Magic implementation classes
53 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
@@ -324,7 +325,7 b' python-profiler package from non-free.""")'
324 """Run the named file inside IPython as a program.
325 """Run the named file inside IPython as a program.
325
326
326 Usage:\\
327 Usage:\\
327 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options]] file [args]
328 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options] -G] file [args]
328
329
329 Parameters after the filename are passed as command-line arguments to
330 Parameters after the filename are passed as command-line arguments to
330 the program (put in sys.argv). Then, control returns to IPython's
331 the program (put in sys.argv). Then, control returns to IPython's
@@ -345,6 +346,13 b' python-profiler package from non-free.""")'
345 and sys.argv). This allows for very convenient loading of code for
346 and sys.argv). This allows for very convenient loading of code for
346 interactive work, while giving each program a 'clean sheet' to run in.
347 interactive work, while giving each program a 'clean sheet' to run in.
347
348
349 Arguments are expanded using shell-like glob match. Patterns
350 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
351 tilde '~' will be expanded into user's home directory. Unlike
352 real shells, quotation does not suppress expansions. Use
353 *two* back slashes (e.g., '\\\\*') to suppress expansions.
354 To completely disable these expansions, you can use -G flag.
355
348 Options:
356 Options:
349
357
350 -n: __name__ is NOT set to '__main__', but to the running file's name
358 -n: __name__ is NOT set to '__main__', but to the running file's name
@@ -439,10 +447,13 b' python-profiler package from non-free.""")'
439
447
440 will run the example module.
448 will run the example module.
441
449
450 -G: disable shell-like glob expansion of arguments.
451
442 """
452 """
443
453
444 # get arguments and set sys.argv for program to be run.
454 # get arguments and set sys.argv for program to be run.
445 opts, arg_lst = self.parse_options(parameter_s, 'nidtN:b:pD:l:rs:T:em:',
455 opts, arg_lst = self.parse_options(parameter_s,
456 'nidtN:b:pD:l:rs:T:em:G',
446 mode='list', list_all=1)
457 mode='list', list_all=1)
447 if "m" in opts:
458 if "m" in opts:
448 modulename = opts["m"][0]
459 modulename = opts["m"][0]
@@ -476,8 +487,11 b' python-profiler package from non-free.""")'
476 # were run from a system shell.
487 # were run from a system shell.
477 save_argv = sys.argv # save it for later restoring
488 save_argv = sys.argv # save it for later restoring
478
489
479 # simulate shell expansion on arguments, at least tilde expansion
490 if 'G' in opts:
480 args = [ os.path.expanduser(a) for a in arg_lst[1:] ]
491 args = arg_lst[1:]
492 else:
493 # tilde and glob expansion
494 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
481
495
482 sys.argv = [filename] + args # put in the proper filename
496 sys.argv = [filename] + args # put in the proper filename
483 # protect sys.argv from potential unicode strings on Python 2:
497 # protect sys.argv from potential unicode strings on Python 2:
@@ -86,6 +86,28 b' def doctest_run_builtins():'
86 ....:
86 ....:
87 """
87 """
88
88
89
90 def doctest_run_option_parser():
91 r"""Test option parser in %run.
92
93 In [1]: %run print_argv.py
94 []
95
96 In [2]: %run print_argv.py print*.py
97 ['print_argv.py']
98
99 In [3]: %run print_argv.py print\\*.py
100 ['print*.py']
101
102 In [4]: %run print_argv.py 'print*.py'
103 ['print_argv.py']
104
105 In [5]: %run -G print_argv.py print*.py
106 ['print*.py']
107
108 """
109
110
89 @py3compat.doctest_refactor_print
111 @py3compat.doctest_refactor_print
90 def doctest_reset_del():
112 def doctest_reset_del():
91 """Test that resetting doesn't cause errors in __del__ methods.
113 """Test that resetting doesn't cause errors in __del__ methods.
@@ -19,6 +19,7 b' import sys'
19 import tempfile
19 import tempfile
20 import warnings
20 import warnings
21 from hashlib import md5
21 from hashlib import md5
22 import glob
22
23
23 import IPython
24 import IPython
24 from IPython.testing.skipdoctest import skip_doctest
25 from IPython.testing.skipdoctest import skip_doctest
@@ -355,6 +356,28 b' def expand_path(s):'
355 return s
356 return s
356
357
357
358
359 def unescape_glob(string):
360 """Unescape glob pattern in `string`."""
361 def unescape(s):
362 for pattern in '*[]!?':
363 s = s.replace(r'\{0}'.format(pattern), pattern)
364 return s
365 return '\\'.join(map(unescape, string.split('\\\\')))
366
367
368 def shellglob(args):
369 """
370 Do glob expansion for each element in `args` and return a flattened list.
371
372 Unmatched glob pattern will remain as-is in the returned list.
373
374 """
375 expanded = []
376 for a in args:
377 expanded.extend(glob.glob(a) or [unescape_glob(a)])
378 return expanded
379
380
358 def target_outdated(target,deps):
381 def target_outdated(target,deps):
359 """Determine whether a target is out of date.
382 """Determine whether a target is out of date.
360
383
@@ -32,6 +32,7 b' from IPython.testing.decorators import skip_if_not_win32, skip_win32'
32 from IPython.testing.tools import make_tempfile, AssertPrints
32 from IPython.testing.tools import make_tempfile, AssertPrints
33 from IPython.utils import path, io
33 from IPython.utils import path, io
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.tempdir import TemporaryDirectory
35
36
36 # Platform-dependent imports
37 # Platform-dependent imports
37 try:
38 try:
@@ -444,3 +445,48 b' def test_unicode_in_filename():'
444 path.get_py_filename(u'fooéè.py', force_win32=False)
445 path.get_py_filename(u'fooéè.py', force_win32=False)
445 except IOError as ex:
446 except IOError as ex:
446 str(ex)
447 str(ex)
448
449
450 def test_shellglob():
451 """Test glob expansion for %run magic."""
452 filenames_start_with_a = map('a{0}'.format, range(3))
453 filenames_end_with_b = map('{0}b'.format, range(3))
454 filenames = filenames_start_with_a + filenames_end_with_b
455
456 with TemporaryDirectory() as td:
457 save = os.getcwdu()
458 try:
459 os.chdir(td)
460
461 # Create empty files
462 for fname in filenames:
463 open(os.path.join(td, fname), 'w').close()
464
465 def assert_match(patterns, matches):
466 # glob returns unordered list. that's why sorted is required.
467 nt.assert_equals(sorted(path.shellglob(patterns)),
468 sorted(matches))
469
470 assert_match(['*'], filenames)
471 assert_match(['a*'], filenames_start_with_a)
472 assert_match(['*c'], ['*c'])
473 assert_match(['*', 'a*', '*b', '*c'],
474 filenames
475 + filenames_start_with_a
476 + filenames_end_with_b
477 + ['*c'])
478
479 assert_match([r'\*'], ['*'])
480 assert_match([r'a\*', 'a*'], ['a*'] + filenames_start_with_a)
481 assert_match(['a[012]'], filenames_start_with_a)
482 assert_match([r'a\[012]'], ['a[012]'])
483 finally:
484 os.chdir(save)
485
486
487 def test_unescape_glob():
488 nt.assert_equals(path.unescape_glob(r'\*\[\!\]\?'), '*[!]?')
489 nt.assert_equals(path.unescape_glob(r'\\*'), r'\*')
490 nt.assert_equals(path.unescape_glob(r'\\\*'), r'\*')
491 nt.assert_equals(path.unescape_glob(r'\\a'), r'\a')
492 nt.assert_equals(path.unescape_glob(r'\a'), r'\a')
General Comments 0
You need to be logged in to leave comments. Login now