See More

try: import unittest2 as unittest except ImportError: import unittest import re from bpython.line import current_word, current_dict_key, current_dict, \ current_string, current_object, current_object_attribute, \ current_from_import_from, current_from_import_import, current_import, \ current_method_definition_name, current_single_word, \ current_string_literal_attr def cursor(s): """'ab|c' -> (2, 'abc')""" cursor_offset = s.index('|') line = s[:cursor_offset] + s[cursor_offset+1:] return cursor_offset, line def decode(s): """'ad' -> ((3, 'abcd'), (1, 3, 'bdc'))""" if not s.count('|') == 1: raise ValueError('match helper needs | to occur once') if s.count('<') != s.count('>') or not s.count('<') in (0, 1): raise ValueError('match helper needs <, and > to occur just once') matches = list(re.finditer(r'[<>|]', s)) assert len(matches) in [1, 3], [m.group() for m in matches] d = {} for i, m in enumerate(matches): d[m.group(0)] = m.start() - i s = s[:m.start() - i] + s[m.end() - i:] assert len(d) in [1, 3], 'need all the parts just once! %r' % d if '<' in d: return (d['|'], s), (d['<'], d['>'], s[d['<']:d['>']]) else: return (d['|'], s), None def line_with_cursor(cursor_offset, line): return line[:cursor_offset] + '|' + line[cursor_offset:] def encode(cursor_offset, line, result): """encode(3, 'abdcd', (1, 3, 'bdc')) -> ad' Written for prettier assert error messages """ encoded_line = line_with_cursor(cursor_offset, line) if result is None: return encoded_line start, end, value = result assert line[start:end] == value if start < cursor_offset: encoded_line = encoded_line[:start] + '<' + encoded_line[start:] else: encoded_line = encoded_line[:start+1] + '<' + encoded_line[start+1:] if end < cursor_offset: encoded_line = encoded_line[:end+1] + '>' + encoded_line[end+1:] else: encoded_line = encoded_line[:end+2] + '>' + encoded_line[end+2:] return encoded_line class LineTestCase(unittest.TestCase): def assertAccess(self, s): r"""Asserts that self.func matches as described by s, which uses a little language to describe matches: abcdhijklmnopqrstuvwx|yz /|\ /|\ /|\ | | | the function should the current cursor position match this "efg" is between the x and y """ (cursor_offset, line), match = decode(s) result = self.func(cursor_offset, line) self.assertEqual( result, match, "%s(%r) result\n%r (%r) doesn't match expected\n%r (%r)" % ( self.func.__name__, line_with_cursor(cursor_offset, line), encode(cursor_offset, line, result), result, s, match)) class TestHelpers(LineTestCase): def test_I(self): self.assertEqual(cursor('asd|fgh'), (3, 'asdfgh')) def test_decode(self): self.assertEqual(decode('ad'), ((3, 'abdcd'), (1, 4, 'bdc'))) self.assertEqual(decode('a|d'), ((1, 'abdcd'), (1, 4, 'bdc'))) self.assertEqual(decode('ad|'), ((5, 'abdcd'), (1, 4, 'bdc'))) def test_encode(self): self.assertEqual(encode(3, 'abdcd', (1, 4, 'bdc')), 'ad') self.assertEqual(encode(1, 'abdcd', (1, 4, 'bdc')), 'a|d') self.assertEqual(encode(4, 'abdcd', (1, 4, 'bdc')), 'ad') self.assertEqual(encode(5, 'abdcd', (1, 4, 'bdc')), 'ad|') def test_assert_access(self): def dumb_func(cursor_offset, line): return (0, 2, 'ab') self.func = dumb_func self.assertAccess('d') class TestCurrentWord(LineTestCase): def setUp(self): self.func = current_word def test_simple(self): self.assertAccess('|') self.assertAccess('|asdf') self.assertAccess('') self.assertAccess('') self.assertAccess('') self.assertAccess('asdf + ') self.assertAccess(' + asdf') def test_inside(self): self.assertAccess('') self.assertAccess('') def test_dots(self): self.assertAccess('') self.assertAccess('') self.assertAccess('') self.assertAccess('stuff[stuff] + {123: 456} + ') self.assertAccess('stuff[]') self.assertAccess('stuff[asdf[]') def test_open_paren(self): self.assertAccess('') # documenting current behavior - TODO is this intended? class TestCurrentDictKey(LineTestCase): def setUp(self): self.func = current_dict_key def test_simple(self): self.assertAccess('asdf|') self.assertAccess('asdf|') self.assertAccess('asdf[<>|') self.assertAccess('asdf[<>|]') self.assertAccess('object.dict[') self.assertAccess('asdf|') self.assertAccess('asdf[<(>|]') self.assertAccess('asdf[<(1>|]') self.assertAccess('asdf[<(1,>|]') self.assertAccess('asdf[<(1, >|]') self.assertAccess('asdf[<(1, 2)>|]') # TODO self.assertAccess('d[d[<12|>') self.assertAccess("d[<'a>|") class TestCurrentDict(LineTestCase): def setUp(self): self.func = current_dict def test_simple(self): self.assertAccess('asdf|') self.assertAccess('asdf|') self.assertAccess('[|') self.assertAccess('[|]') self.assertAccess('[abc|') self.assertAccess('asdf|') class TestCurrentString(LineTestCase): def setUp(self): self.func = current_string def test_closed(self): self.assertAccess('""') self.assertAccess('""') self.assertAccess('"<|asdf>"') self.assertAccess("''") self.assertAccess("'<|asdf>'") self.assertAccess("''''''") self.assertAccess('""""""') self.assertAccess('asdf.afd("a") + ""') def test_open(self): self.assertAccess('"') self.assertAccess('"') self.assertAccess('"<|asdf>') self.assertAccess("'") self.assertAccess("'<|asdf>") self.assertAccess("'''") self.assertAccess('"""') self.assertAccess('asdf.afd("a") + "') class TestCurrentObject(LineTestCase): def setUp(self): self.func = current_object def test_simple(self): self.assertAccess('.attr1|') self.assertAccess('.|') self.assertAccess('Object|') self.assertAccess('Object|.') self.assertAccess('.|') self.assertAccess('.attr2|') self.assertAccess('.att|r1.attr2') self.assertAccess('stuff[stuff] + {123: 456} + .attr2|') self.assertAccess('stuff[asd|fg]') self.assertAccess('stuff[asdf[asd|fg]') class TestCurrentAttribute(LineTestCase): def setUp(self): self.func = current_object_attribute def test_simple(self): self.assertAccess('Object.') self.assertAccess('Object.attr1.') self.assertAccess('Object..attr2') self.assertAccess('stuff[stuff] + {123: 456} + Object.attr1.') self.assertAccess('stuff[asd|fg]') self.assertAccess('stuff[asdf[asd|fg]') self.assertAccess('Object.attr1.<|attr2>') self.assertAccess('Object..attr2') class TestCurrentFromImportFrom(LineTestCase): def setUp(self): self.func = current_from_import_from def test_simple(self): self.assertAccess('from import path') self.assertAccess('from import path|') self.assertAccess('if True|: from sys import path') self.assertAccess('if True: |from sys import path') self.assertAccess('if True: from import p|ath') self.assertAccess('if True: from sys imp|ort path') self.assertAccess('if True: from sys import |path') self.assertAccess('if True: from sys import path.stu|ff') self.assertAccess('if True: from import sep|') self.assertAccess('from ') class TestCurrentFromImportImport(LineTestCase): def setUp(self): self.func = current_from_import_import def test_simple(self): self.assertAccess('from sys import ') self.assertAccess('from sys import

') self.assertAccess('from sys import |path') self.assertAccess('from sys| import path') self.assertAccess('from s|ys import path') self.assertAccess('from |sys import path') self.assertAccess('from xml.dom import ') # because syntax error self.assertAccess('from xml.dom import Node.as|d') class TestCurrentImport(LineTestCase): def setUp(self): self.func = current_import def test_simple(self): self.assertAccess('import ') self.assertAccess('import

') self.assertAccess('import |path') self.assertAccess('import path, ') self.assertAccess('import path another|') self.assertAccess('if True: import ') self.assertAccess('if True: import ') self.assertAccess('if True: import ') self.assertAccess('if True: import as something') class TestMethodDefinitionName(LineTestCase): def setUp(self): self.func = current_method_definition_name def test_simple(self): self.assertAccess('def ') self.assertAccess(' def bar(x, y)|:') self.assertAccess(' def (x, y)') class TestSingleWord(LineTestCase): def setUp(self): self.func = current_single_word def test_simple(self): self.assertAccess('foo.bar|') self.assertAccess('.foo|') self.assertAccess(' ') class TestCurrentStringLiteral(LineTestCase): def setUp(self): self.func = current_string_literal_attr def test_simple(self): self.assertAccess('"hey".') self.assertAccess('"hey"|') self.assertAccess('"hey"|.a') self.assertAccess('"hey".') self.assertAccess('"hey".asdf d|') self.assertAccess('"hey".<|>') if __name__ == '__main__': unittest.main()