Skip to content

Commit 846ca4d

Browse files
committed
Be more careful with glob.glob (fixes bpython#491)
If we have glob.escape, use it. Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
1 parent 5880f85 commit 846ca4d

File tree

2 files changed

+20
-8
lines changed

2 files changed

+20
-8
lines changed

bpython/autocomplete.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@
2727

2828
import __main__
2929
import abc
30+
import glob
3031
import keyword
3132
import os
33+
import re
3234
import rlcompleter
35+
import sys
3336
from six.moves import range, builtins
3437
from six import string_types, iteritems
3538

36-
from glob import glob
37-
3839
from bpython import inspection
3940
from bpython import importcompletion
4041
from bpython import line as lineparts
@@ -160,6 +161,17 @@ class FilenameCompletion(BaseCompletionType):
160161
def __init__(self):
161162
super(FilenameCompletion, self).__init__(False)
162163

164+
if sys.version_info[:2] >= (3, 4):
165+
def safe_glob(self, pathname):
166+
return glob.glob(glob.escape(pathname) + '*')
167+
else:
168+
def safe_glob(self, pathname):
169+
try:
170+
return glob.glob(pathname + '*')
171+
except re.error:
172+
# see #491
173+
return tuple()
174+
163175
def matches(self, cursor_offset, line, **kwargs):
164176
cs = lineparts.current_string(cursor_offset, line)
165177
if cs is None:
@@ -168,7 +180,7 @@ def matches(self, cursor_offset, line, **kwargs):
168180
matches = set()
169181
username = text.split(os.path.sep, 1)[0]
170182
user_dir = os.path.expanduser(username)
171-
for filename in glob(os.path.expanduser(text + '*')):
183+
for filename in self.safe_glob(os.path.expanduser(text)):
172184
if os.path.isdir(filename):
173185
filename += os.path.sep
174186
if text.startswith('~'):

bpython/test/test_autocomplete.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,15 @@ def test_locate_fails_when_not_in_string(self):
123123
def test_locate_succeeds_when_in_string(self):
124124
self.assertEqual(self.completer.locate(4, "a'bc'd"), (2, 4, 'bc'))
125125

126-
@mock.patch('bpython.autocomplete.glob', new=lambda text: [])
126+
@mock.patch('glob.glob', new=lambda text: [])
127127
def test_match_returns_none_if_not_in_string(self):
128128
self.assertEqual(self.completer.matches(2, 'abcd'), None)
129129

130-
@mock.patch('bpython.autocomplete.glob', new=lambda text: [])
130+
@mock.patch('glob.glob', new=lambda text: [])
131131
def test_match_returns_empty_list_when_no_files(self):
132132
self.assertEqual(self.completer.matches(2, '"a'), set())
133133

134-
@mock.patch('bpython.autocomplete.glob',
134+
@mock.patch('glob.glob',
135135
new=lambda text: ['abcde', 'aaaaa'])
136136
@mock.patch('os.path.expanduser', new=lambda text: text)
137137
@mock.patch('os.path.isdir', new=lambda text: False)
@@ -140,7 +140,7 @@ def test_match_returns_files_when_files_exist(self):
140140
self.assertEqual(sorted(self.completer.matches(2, '"x')),
141141
['aaaaa', 'abcde'])
142142

143-
@mock.patch('bpython.autocomplete.glob',
143+
@mock.patch('glob.glob',
144144
new=lambda text: ['abcde', 'aaaaa'])
145145
@mock.patch('os.path.expanduser', new=lambda text: text)
146146
@mock.patch('os.path.isdir', new=lambda text: True)
@@ -149,7 +149,7 @@ def test_match_returns_dirs_when_dirs_exist(self):
149149
self.assertEqual(sorted(self.completer.matches(2, '"x')),
150150
['aaaaa/', 'abcde/'])
151151

152-
@mock.patch('bpython.autocomplete.glob',
152+
@mock.patch('glob.glob',
153153
new=lambda text: ['/expand/ed/abcde', '/expand/ed/aaaaa'])
154154
@mock.patch('os.path.expanduser',
155155
new=lambda text: text.replace('~', '/expand/ed'))

0 commit comments

Comments
 (0)