From b1c2e3022498c8c3d60f2fd384725f5ea5ee2817 2012-05-26 03:20:01 From: Fernando Perez Date: 2012-05-26 03:20:01 Subject: [PATCH] Fix bugs in completer.py with incompletely-implemented property. From a docstring that ended mid-sentence, it's pretty clear that we'd forgotten to finish the implementation of the completion splitter with real properties. I have no clue how the tests were passing, as there was also a nasty bit of state mangling being done by one of the tests; finished the implementation and fixed the tests. --- diff --git a/IPython/core/completer.py b/IPython/core/completer.py index 333eadd..d451fcd 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -178,11 +178,14 @@ def compress_user(path, tilde_expand, tilde_val): else: return path + class Bunch(object): pass + DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?' GREEDY_DELIMS = ' \r\n' + class CompletionSplitter(object): """An object to split an input line in a manner similar to readline. @@ -194,7 +197,7 @@ class CompletionSplitter(object): What characters are used as splitting delimiters can be controlled by setting the `delims` attribute (this is a property that internally - automatically builds the necessary """ + automatically builds the necessary regular expression)""" # Private interface @@ -212,19 +215,21 @@ class CompletionSplitter(object): def __init__(self, delims=None): delims = CompletionSplitter._delims if delims is None else delims - self.set_delims(delims) + self.delims = delims - def set_delims(self, delims): + @property + def delims(self): + """Return the string of delimiter characters.""" + return self._delims + + @delims.setter + def delims(self, delims): """Set the delimiters for line splitting.""" expr = '[' + ''.join('\\'+ c for c in delims) + ']' self._delim_re = re.compile(expr) self._delims = delims self._delim_expr = expr - def get_delims(self): - """Return the string of delimiter characters.""" - return self._delims - def split_line(self, line, cursor_pos=None): """Split a line of text with a cursor at the given position. """ @@ -377,7 +382,7 @@ class Completer(Configurable): def get__all__entries(obj): """returns the strings in the __all__ attribute""" try: - words = getattr(obj,'__all__') + words = getattr(obj, '__all__') except: return [] @@ -390,12 +395,12 @@ class IPCompleter(Completer): def _greedy_changed(self, name, old, new): """update the splitter and readline delims when greedy is changed""" if new: - self.splitter.set_delims(GREEDY_DELIMS) + self.splitter.delims = GREEDY_DELIMS else: - self.splitter.set_delims(DELIMS) + self.splitter.delims = DELIMS if self.readline: - self.readline.set_completer_delims(self.splitter.get_delims()) + self.readline.set_completer_delims(self.splitter.delims) merge_completions = CBool(True, config=True, help="""Whether to merge completion results into a single list @@ -821,7 +826,7 @@ class IPCompleter(Completer): self.line_buffer = line_buffer self.text_until_cursor = self.line_buffer[:cursor_pos] - #io.rprint('\nCOMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg + #io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg # Start with a clean slate of completions self.matches[:] = [] diff --git a/IPython/core/tests/test_completer.py b/IPython/core/tests/test_completer.py index 821eedd..15285cc 100644 --- a/IPython/core/tests/test_completer.py +++ b/IPython/core/tests/test_completer.py @@ -119,8 +119,8 @@ class CompletionSplitterTestCase(unittest.TestCase): self.sp = completer.CompletionSplitter() def test_delim_setting(self): - self.sp.set_delims(' ') - nt.assert_equal(self.sp.get_delims(), ' ') + self.sp.delims = ' ' + nt.assert_equal(self.sp.delims, ' ') nt.assert_equal(self.sp._delim_expr, '[\ ]') def test_spaces(self): @@ -202,13 +202,18 @@ def test_local_file_completions(): def test_greedy_completions(): ip = get_ipython() - ip.Completer.greedy = False - ip.ex('a=range(5)') - _,c = ip.complete('.',line='a[0].') - nt.assert_false('a[0].real' in c, "Shouldn't have completed on a[0]: %s"%c) - ip.Completer.greedy = True - _,c = ip.complete('.',line='a[0].') - nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c) + greedy_original = ip.Completer.greedy + try: + ip.Completer.greedy = False + ip.ex('a=range(5)') + _,c = ip.complete('.',line='a[0].') + nt.assert_false('a[0].real' in c, + "Shouldn't have completed on a[0]: %s"%c) + ip.Completer.greedy = True + _,c = ip.complete('.',line='a[0].') + nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c) + finally: + ip.Completer.greedy = greedy_original def test_omit__names(): @@ -280,7 +285,8 @@ def test_func_kw_completions(): ip = get_ipython() c = ip.Completer ip.ex('def myfunc(a=1,b=2): return a+b') - s, matches = c.complete(None,'myfunc(1,b') - nt.assert_true('b=' in matches) - s, matches = c.complete(None,'myfunc(1,b)',10)#cursor is right after b - nt.assert_true('b=' in matches) + s, matches = c.complete(None, 'myfunc(1,b') + nt.assert_in('b=', matches) + # Simulate completing with cursor right after b (pos==10): + s, matches = c.complete(None,'myfunc(1,b)', 10) + nt.assert_in('b=', matches)