##// END OF EJS Templates
Merge pull request #4895 from takluyver/i3459...
Brian E. Granger -
r15550:e0059071 merge
parent child Browse files
Show More
@@ -260,7 +260,11 b' def magic_run_completer(self, event):'
260 """Complete files that end in .py or .ipy or .ipynb for the %run command.
260 """Complete files that end in .py or .ipy or .ipynb for the %run command.
261 """
261 """
262 comps = arg_split(event.line, strict=False)
262 comps = arg_split(event.line, strict=False)
263 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
263 # relpath should be the current token that we need to complete.
264 if (len(comps) > 1) and (not event.line.endswith(' ')):
265 relpath = comps[-1].strip("'\"")
266 else:
267 relpath = ''
264
268
265 #print("\nev=", event) # dbg
269 #print("\nev=", event) # dbg
266 #print("rp=", relpath) # dbg
270 #print("rp=", relpath) # dbg
@@ -270,20 +274,23 b' def magic_run_completer(self, event):'
270 isdir = os.path.isdir
274 isdir = os.path.isdir
271 relpath, tilde_expand, tilde_val = expand_user(relpath)
275 relpath, tilde_expand, tilde_val = expand_user(relpath)
272
276
273 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
274
275 # Find if the user has already typed the first filename, after which we
277 # Find if the user has already typed the first filename, after which we
276 # should complete on all files, since after the first one other files may
278 # should complete on all files, since after the first one other files may
277 # be arguments to the input script.
279 # be arguments to the input script.
278
280
279 if any(magic_run_re.match(c) for c in comps):
281 if any(magic_run_re.match(c) for c in comps):
280 pys = [f.replace('\\','/') for f in lglob('*')]
282 matches = [f.replace('\\','/') + ('/' if isdir(f) else '')
283 for f in lglob(relpath+'*')]
281 else:
284 else:
285 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
282 pys = [f.replace('\\','/')
286 pys = [f.replace('\\','/')
283 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
287 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
284 lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
288 lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
289
290 matches = dirs + pys
291
285 #print('run comp:', dirs+pys) # dbg
292 #print('run comp:', dirs+pys) # dbg
286 return [compress_user(p, tilde_expand, tilde_val) for p in dirs+pys]
293 return [compress_user(p, tilde_expand, tilde_val) for p in matches]
287
294
288
295
289 def cd_completer(self, event):
296 def cd_completer(self, event):
@@ -15,6 +15,8 b' import tempfile'
15 import unittest
15 import unittest
16 from os.path import join
16 from os.path import join
17
17
18 import nose.tools as nt
19
18 from IPython.core.completerlib import magic_run_completer, module_completion
20 from IPython.core.completerlib import magic_run_completer, module_completion
19 from IPython.utils import py3compat
21 from IPython.utils import py3compat
20 from IPython.utils.tempdir import TemporaryDirectory
22 from IPython.utils.tempdir import TemporaryDirectory
@@ -29,11 +31,17 b' class MockEvent(object):'
29 # Test functions begin
31 # Test functions begin
30 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
31 class Test_magic_run_completer(unittest.TestCase):
33 class Test_magic_run_completer(unittest.TestCase):
34 files = [u"aao.py", u"a.py", u"b.py", u"aao.txt"]
35 dirs = [u"adir/", "bdir/"]
36
32 def setUp(self):
37 def setUp(self):
33 self.BASETESTDIR = tempfile.mkdtemp()
38 self.BASETESTDIR = tempfile.mkdtemp()
34 for fil in [u"aao.py", u"a.py", u"b.py"]:
39 for fil in self.files:
35 with open(join(self.BASETESTDIR, fil), "w") as sfile:
40 with open(join(self.BASETESTDIR, fil), "w") as sfile:
36 sfile.write("pass\n")
41 sfile.write("pass\n")
42 for d in self.dirs:
43 os.mkdir(join(self.BASETESTDIR, d))
44
37 self.oldpath = py3compat.getcwd()
45 self.oldpath = py3compat.getcwd()
38 os.chdir(self.BASETESTDIR)
46 os.chdir(self.BASETESTDIR)
39
47
@@ -47,7 +55,7 b' class Test_magic_run_completer(unittest.TestCase):'
47 event = MockEvent(u"%run a")
55 event = MockEvent(u"%run a")
48 mockself = None
56 mockself = None
49 match = set(magic_run_completer(mockself, event))
57 match = set(magic_run_completer(mockself, event))
50 self.assertEqual(match, set([u"a.py", u"aao.py"]))
58 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
51
59
52 def test_2(self):
60 def test_2(self):
53 """Test magic_run_completer, should match one alterntive
61 """Test magic_run_completer, should match one alterntive
@@ -62,23 +70,23 b' class Test_magic_run_completer(unittest.TestCase):'
62 event = MockEvent(u'%run "a')
70 event = MockEvent(u'%run "a')
63 mockself = None
71 mockself = None
64 match = set(magic_run_completer(mockself, event))
72 match = set(magic_run_completer(mockself, event))
65 self.assertEqual(match, set([u"a.py", u"aao.py"]))
73 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
66
74
67 def test_import_invalid_module(self):
75 def test_completion_more_args(self):
68 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
76 event = MockEvent(u'%run a.py ')
69 invalid_module_names = set(['foo-bar', 'foo:bar', '10foo'])
77 match = set(magic_run_completer(None, event))
70 valid_module_names = set(['foobar'])
78 self.assertEqual(match, set(self.files + self.dirs))
71 with TemporaryDirectory() as tmpdir:
79
72 sys.path.insert( 0, tmpdir )
80 def test_completion_in_dir(self):
73 for name in invalid_module_names | valid_module_names:
81 # Github issue #3459
74 filename = os.path.join(tmpdir, name + '.py')
82 event = MockEvent(u'%run a.py {}'.format(join(self.BASETESTDIR, 'a')))
75 open(filename, 'w').close()
83 print(repr(event.line))
76
84 match = set(magic_run_completer(None, event))
77 s = set( module_completion('import foo') )
85 # We specifically use replace here rather than normpath, because
78 intersection = s.intersection(invalid_module_names)
86 # at one point there were duplicates 'adir' and 'adir/', and normpath
79 self.assertFalse(intersection, intersection)
87 # would hide the failure for that.
80
88 self.assertEqual(match, {join(self.BASETESTDIR, f).replace('\\','/')
81 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
89 for f in (u'a.py', u'aao.py', u'aao.txt', u'adir/')})
82
90
83 class Test_magic_run_completer_nonascii(unittest.TestCase):
91 class Test_magic_run_completer_nonascii(unittest.TestCase):
84 @onlyif_unicode_paths
92 @onlyif_unicode_paths
@@ -119,3 +127,21 b' class Test_magic_run_completer_nonascii(unittest.TestCase):'
119 mockself = None
127 mockself = None
120 match = set(magic_run_completer(mockself, event))
128 match = set(magic_run_completer(mockself, event))
121 self.assertEqual(match, set([u"a.py", u"aaø.py"]))
129 self.assertEqual(match, set([u"a.py", u"aaø.py"]))
130
131 # module_completer:
132
133 def test_import_invalid_module():
134 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
135 invalid_module_names = set(['foo-bar', 'foo:bar', '10foo'])
136 valid_module_names = set(['foobar'])
137 with TemporaryDirectory() as tmpdir:
138 sys.path.insert( 0, tmpdir )
139 for name in invalid_module_names | valid_module_names:
140 filename = os.path.join(tmpdir, name + '.py')
141 open(filename, 'w').close()
142
143 s = set( module_completion('import foo') )
144 intersection = s.intersection(invalid_module_names)
145 nt.assert_equal(intersection, set())
146
147 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
General Comments 0
You need to be logged in to leave comments. Login now