##// 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 44 from IPython.utils.io import capture_output
45 45 from IPython.utils.ipstruct import Struct
46 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 48 from IPython.utils.timing import clock, clock2
49 49 from IPython.utils.warn import warn, error
50 50
51
51 52 #-----------------------------------------------------------------------------
52 53 # Magic implementation classes
53 54 #-----------------------------------------------------------------------------
@@ -324,7 +325,7 b' python-profiler package from non-free.""")'
324 325 """Run the named file inside IPython as a program.
325 326
326 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 330 Parameters after the filename are passed as command-line arguments to
330 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 346 and sys.argv). This allows for very convenient loading of code for
346 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 356 Options:
349 357
350 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 448 will run the example module.
441 449
450 -G: disable shell-like glob expansion of arguments.
451
442 452 """
443 453
444 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 457 mode='list', list_all=1)
447 458 if "m" in opts:
448 459 modulename = opts["m"][0]
@@ -476,8 +487,11 b' python-profiler package from non-free.""")'
476 487 # were run from a system shell.
477 488 save_argv = sys.argv # save it for later restoring
478 489
479 # simulate shell expansion on arguments, at least tilde expansion
480 args = [ os.path.expanduser(a) for a in arg_lst[1:] ]
490 if 'G' in opts:
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 496 sys.argv = [filename] + args # put in the proper filename
483 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 111 @py3compat.doctest_refactor_print
90 112 def doctest_reset_del():
91 113 """Test that resetting doesn't cause errors in __del__ methods.
@@ -19,6 +19,7 b' import sys'
19 19 import tempfile
20 20 import warnings
21 21 from hashlib import md5
22 import glob
22 23
23 24 import IPython
24 25 from IPython.testing.skipdoctest import skip_doctest
@@ -355,6 +356,28 b' def expand_path(s):'
355 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 381 def target_outdated(target,deps):
359 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 32 from IPython.testing.tools import make_tempfile, AssertPrints
33 33 from IPython.utils import path, io
34 34 from IPython.utils import py3compat
35 from IPython.utils.tempdir import TemporaryDirectory
35 36
36 37 # Platform-dependent imports
37 38 try:
@@ -444,3 +445,48 b' def test_unicode_in_filename():'
444 445 path.get_py_filename(u'fooéè.py', force_win32=False)
445 446 except IOError as ex:
446 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