Skip to content

Commit 05a2d40

Browse files
committed
Raise an exception if safe_eval fails instead of returning a sentinel.
1 parent cb0a166 commit 05a2d40

File tree

2 files changed

+19
-17
lines changed

2 files changed

+19
-17
lines changed

bpython/autocomplete.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,9 @@ def matches(cls, cursor_offset, line, locals_, **kwargs):
205205
return None
206206
start, end, orig = r
207207
_, _, dexpr = lineparts.current_dict(cursor_offset, line)
208-
obj = safe_eval(dexpr, locals_)
209-
if obj is SafeEvalFailed:
208+
try:
209+
obj = safe_eval(dexpr, locals_)
210+
except EvaluationError:
210211
return []
211212
if obj and isinstance(obj, type({})) and obj.keys():
212213
return ["{!r}]".format(k) for k in obj.keys() if repr(k).startswith(orig)]
@@ -288,23 +289,20 @@ def matches(cls, cursor_offset, line, **kwargs):
288289
return [match for match in matches if not match.startswith('_')]
289290
return matches
290291

291-
class SafeEvalFailed(Exception):
292-
"""If this object is returned, safe_eval failed"""
293-
# Because every normal Python value is a possible return value of safe_eval
292+
293+
class EvaluationError(Exception):
294+
"""Raised if an exception occurred in safe_eval."""
295+
294296

295297
def safe_eval(expr, namespace):
296298
"""Not all that safe, just catches some errors"""
297-
if expr.isdigit():
298-
# Special case: float literal, using attrs here will result in
299-
# a SyntaxError
300-
return SafeEvalFailed
301299
try:
302-
obj = eval(expr, namespace)
303-
return obj
300+
return eval(expr, namespace)
304301
except (NameError, AttributeError, SyntaxError):
305302
# If debugging safe_eval, raise this!
306303
# raise
307-
return SafeEvalFailed
304+
raise EvaluationError
305+
308306

309307
def attr_matches(text, namespace, autocomplete_mode):
310308
"""Taken from rlcompleter.py and bent to my will.
@@ -318,8 +316,13 @@ def attr_matches(text, namespace, autocomplete_mode):
318316
return []
319317

320318
expr, attr = m.group(1, 3)
321-
obj = safe_eval(expr, namespace)
322-
if obj is SafeEvalFailed:
319+
if expr.isdigit():
320+
# Special case: float literal, using attrs here will result in
321+
# a SyntaxError
322+
return []
323+
try:
324+
obj = safe_eval(expr, namespace)
325+
except EvaluationError:
323326
return []
324327
with inspection.AttrCleaner(obj):
325328
matches = attr_lookup(obj, expr, attr, autocomplete_mode)

bpython/test/test_autocomplete.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@ def skip(f):
1414

1515
class TestSafeEval(unittest.TestCase):
1616
def test_catches_syntax_error(self):
17-
try:
17+
with self.assertRaises(autocomplete.EvaluationError):
1818
autocomplete.safe_eval('1re',{})
19-
except:
20-
self.fail('safe_eval raises an error')
19+
2120

2221
class TestFormatters(unittest.TestCase):
2322

0 commit comments

Comments
 (0)