class Transformer(object): def __init__(self, styles): self.styles = styles self.line_style_processor = LineStyleProcessor() def style(self, line): if not self.styles: return line region_map = self.line_style_processor.get_region_map( line, self.styles) regions = region_map.keys() regions.sort() pos = 0 styled_line = [] for region in regions: style = region_map[region] start, end = region[0], region[1] if pos < start: self._append_to(styled_line, line, pos, start) self._append_to(styled_line, line, start, end, style) else: self._append_to(styled_line, line, start, end, style) pos = end if pos <= len(line) - 1: self._append_to(styled_line, line, pos, len(line)) return ''.join(styled_line) def _append_to(self, styled_line, line, start, end, style=None): if style: styled_line.append(style.transforms) styled_line.append(line[start:end]) styled_line.append(DEFAULT_STYLE)
class Transformer(object): def __init__(self, styles): self.styles = styles self.line_style_processor = LineStyleProcessor() def style(self, line): if not self.styles: return line region_map = self.line_style_processor.get_region_map(line, self.styles) regions = region_map.keys() regions.sort() pos = 0 styled_line = [] for region in regions: style = region_map[region] start, end = region[0], region[1] if pos < start: self._append_to(styled_line, line, pos, start) self._append_to(styled_line, line, start, end, style) else: self._append_to(styled_line, line, start, end, style) pos = end if pos <= len(line) - 1: self._append_to(styled_line, line, pos, len(line)) return ''.join(styled_line) def _append_to(self, styled_line, line, start, end, style=None): if style: styled_line.append(style.transforms) styled_line.append(line[start : end]) styled_line.append(DEFAULT_STYLE)
class LineStyleProcessorTests(unittest.TestCase): def setUp(self): self.lineStyleProcessor = LineStyleProcessor() self.find_regions = self.lineStyleProcessor.find_regions def test_get_region_map(self): # 0123456789012345678901234567890123456789 line = "This is a long string forty chars long.." red = ['red'] s1 = RegexStyle(regex("This"), red) s2 = RegexStyle(regex("is"), red) s3 = RegexStyle(regex("s"), red) styles = [s1, s2, s3] region_map = self.lineStyleProcessor.get_region_map( line, styles) regions = region_map.keys() regions.sort() self.assert_results([(0,4), (5,7), (15,16), (32,33)], regions) self.assertEqual(region_map[(0,4)], s1) self.assertEqual(region_map[(5,7)], s2) self.assertEqual(region_map[(15,16)], s3) self.assertEqual(region_map[(32,33)], s3) def test_get_region_map_reverse_order(self): # 0123456789012345678901234567890123456789 line = "This is a long string forty chars long.." red = ['red'] s1 = RegexStyle(regex("s"), red) s2 = RegexStyle(regex("is"), red) s3 = RegexStyle(regex("This"), red) styles = [s1, s2, s3] region_map = self.lineStyleProcessor.get_region_map(line, styles) regions = region_map.keys() regions.sort() self.assert_results([(3,4), (6,7), (15,16), (32,33)], regions) self.assertEqual(region_map[(3,4)], s1) self.assertEqual(region_map[(6,7)], s1) self.assertEqual(region_map[(15,16)], s1) self.assertEqual(region_map[(32,33)], s1) def test_get_region_map_index_style_when_start_is_equal_to_line_length(self): line = "blip" region = (len(line), len(line) + 1) s1 = IndexStyle([region], ['red']) region_map = self.lineStyleProcessor.get_region_map(line, [s1]) regions = region_map.keys() self.assert_results([], regions) def test_get_region_map_index_style_when_end_is_greater_than_line_length(self): # 01234567890123456 line = "a short string..." region = (7,20) self.assertTrue(region[1] > len(line)) s1 = IndexStyle([region], ['red']) styles = [s1] region_map = self.lineStyleProcessor.get_region_map(line, styles) regions = region_map.keys() self.assert_results([(7,17)], regions) self.assertEqual(region_map[(7,17)], s1) def test_get_region_map_index_style_when_end_is_none(self): line = "end is None, and therefore defaults to line length" region = (0, None) s1 = IndexStyle([region], ['red']) styles = [s1] region_map = self.lineStyleProcessor.get_region_map(line, styles) regions = region_map.keys() expected_end = len(line) self.assert_results([(0, expected_end)], regions) self.assertEqual(region_map[(0, expected_end)], s1) def test_get_region_map_index_style(self): line = "a test string that needs to be longer than 65 characters.........." s1 = IndexStyle([ (1,5), (4,10), (15,20), (35,40), (45,50)], ['red']) s2 = IndexStyle([ (1,3), (4,6), (7,14), (41,44), (55,60)], ['red']) s3 = IndexStyle([ (60,65)], ['red']) styles = [s1, s2, s3] region_map = self.lineStyleProcessor.get_region_map(line, styles) regions = region_map.keys() regions.sort() self.assert_results([(1,5), (7,14), (15,20), (35,40), (41,44), (45,50), (55,60), (60,65)], regions) # (60,65)? self.assertEqual(region_map[(1,5)], s1) self.assertEqual(region_map[(7,14)], s2) self.assertEqual(region_map[(15,20)], s1) self.assertEqual(region_map[(35,40)], s1) self.assertEqual(region_map[(41,44)], s2) self.assertEqual(region_map[(45,50)], s1) self.assertEqual(region_map[(55,60)], s2) self.assertEqual(region_map[(60,65)], s3) def assert_results(self, expected_results, results): self.assertEquals(len(expected_results), len(results)) for i, result in enumerate(results): self.assertEqual(expected_results[i], result) def test_repeated_invocation_returns_new_list(self): results1 = self.find_regions('string', 'in') results2 = self.find_regions('string', 'in') self.assertIsNot(results1, results2) self.assert_results([(3,5)], results1) self.assert_results([(3,5)], results2) def test_missing_searchstr_return_empty_results(self): results = self.find_regions('some string', '') self.assert_results([], results) results = self.find_regions('some string', None) self.assert_results([], results) results = self.find_regions('', '') self.assert_results([], results) def test_no_match(self): results = self.find_regions('', 'a') self.assert_results([], results) results = self.find_regions('', 'foo') self.assert_results([], results) results = self.find_regions('some string', 'foo') self.assert_results([], results) def test_smart_simple_cases(self): results = self.find_regions('this is...', 'this') self.assert_results([(0,4)], results) results = self.find_regions('my string', 'string') self.assert_results([(3,9)], results) def test_single_char_match(self): results = self.find_regions('a', 'a') self.assert_results([(0,1)], results) results = self.find_regions('aaaaa', 'a') self.assert_results([(0,1), (1,2), (2,3), (3,4), (4,5)], results) results = self.find_regions('axaxa', 'a') self.assert_results([(0,1), (2,3), (4,5)], results) results = self.find_regions('foo', 'f') self.assert_results([(0,1)], results) results = self.find_regions('foo', 'o') self.assert_results([(1,2), (2,3)], results) def test_consecutive_matches(self): results = self.find_regions('isisis', 'is') self.assert_results([(0,2), (2,4), (4,6)], results) results = self.find_regions('isisisis', 'is') self.assert_results([(0,2), (2,4), (4,6), (6,8)], results) results = self.find_regions('x isis', 'is') self.assert_results([(2,4), (4,6)], results) # 0 1 2 # 012345678901234567890 results = self.find_regions('this is his list isis', 'is') self.assert_results([(2,4), (5,7), (9,11), (13,15), (17,19), (19,21)], results) def test_find_regions_with_simple_regex(self): results = self.find_regions('x-11-11', regex('\d+')) self.assert_results([(2,4), (5,7)], results) results = self.find_regions('01-3456-11-11', regex('\d+')) self.assert_results([(0,2), (3,7), (8,10), (11,13)], results) results = self.find_regions('0123456789 nums', regex('\d+')) self.assert_results([(0,10)], results) results = self.find_regions('0123456789', regex('\d+')) self.assert_results([(0,10)], results) results = self.find_regions('some string', regex('\w+')) self.assert_results([(0,4), (5,11)], results) results = self.find_regions('some long string', regex('long')) self.assert_results([(5,9)], results) results = self.find_regions('foo boo', regex('o+')) self.assert_results([(1,3), (5,7)], results) results = self.find_regions('foo boo', regex('o')) self.assert_results([(1,2), (2,3), (5,6), (6,7)], results) results = self.find_regions(" '192.168.99.1'", regex('\d+\.\d+\.\d+\.\d+')) self.assert_results([(2,14)], results) def assert_results(self, expected_results, results): self.assertEquals(len(expected_results), len(results)) for i, result in enumerate(results): self.assertEqual(expected_results[i], result)
class LineStyleProcessorTests(unittest.TestCase): def setUp(self): self.lineStyleProcessor = LineStyleProcessor() self.find_regions = self.lineStyleProcessor.find_regions def test_get_region_map(self): # 0123456789012345678901234567890123456789 line = "This is a long string forty chars long.." red = ['red'] s1 = RegexStyle(regex("This"), red) s2 = RegexStyle(regex("is"), red) s3 = RegexStyle(regex("s"), red) styles = [s1, s2, s3] region_map = self.lineStyleProcessor.get_region_map(line, styles) regions = region_map.keys() regions.sort() self.assert_results([(0, 4), (5, 7), (15, 16), (32, 33)], regions) self.assertEqual(region_map[(0, 4)], s1) self.assertEqual(region_map[(5, 7)], s2) self.assertEqual(region_map[(15, 16)], s3) self.assertEqual(region_map[(32, 33)], s3) def test_get_region_map_reverse_order(self): # 0123456789012345678901234567890123456789 line = "This is a long string forty chars long.." red = ['red'] s1 = RegexStyle(regex("s"), red) s2 = RegexStyle(regex("is"), red) s3 = RegexStyle(regex("This"), red) styles = [s1, s2, s3] region_map = self.lineStyleProcessor.get_region_map(line, styles) regions = region_map.keys() regions.sort() self.assert_results([(3, 4), (6, 7), (15, 16), (32, 33)], regions) self.assertEqual(region_map[(3, 4)], s1) self.assertEqual(region_map[(6, 7)], s1) self.assertEqual(region_map[(15, 16)], s1) self.assertEqual(region_map[(32, 33)], s1) def test_get_region_map_index_style_when_start_is_equal_to_line_length( self): line = "blip" region = (len(line), len(line) + 1) s1 = IndexStyle([region], ['red']) region_map = self.lineStyleProcessor.get_region_map(line, [s1]) regions = region_map.keys() self.assert_results([], regions) def test_get_region_map_index_style_when_end_is_greater_than_line_length( self): # 01234567890123456 line = "a short string..." region = (7, 20) self.assertTrue(region[1] > len(line)) s1 = IndexStyle([region], ['red']) styles = [s1] region_map = self.lineStyleProcessor.get_region_map(line, styles) regions = region_map.keys() self.assert_results([(7, 17)], regions) self.assertEqual(region_map[(7, 17)], s1) def test_get_region_map_index_style_when_end_is_none(self): line = "end is None, and therefore defaults to line length" region = (0, None) s1 = IndexStyle([region], ['red']) styles = [s1] region_map = self.lineStyleProcessor.get_region_map(line, styles) regions = region_map.keys() expected_end = len(line) self.assert_results([(0, expected_end)], regions) self.assertEqual(region_map[(0, expected_end)], s1) def test_get_region_map_index_style(self): line = "a test string that needs to be longer than 65 characters.........." s1 = IndexStyle([(1, 5), (4, 10), (15, 20), (35, 40), (45, 50)], ['red']) s2 = IndexStyle([(1, 3), (4, 6), (7, 14), (41, 44), (55, 60)], ['red']) s3 = IndexStyle([(60, 65)], ['red']) styles = [s1, s2, s3] region_map = self.lineStyleProcessor.get_region_map(line, styles) regions = region_map.keys() regions.sort() self.assert_results([(1, 5), (7, 14), (15, 20), (35, 40), (41, 44), (45, 50), (55, 60), (60, 65)], regions) # (60,65)? self.assertEqual(region_map[(1, 5)], s1) self.assertEqual(region_map[(7, 14)], s2) self.assertEqual(region_map[(15, 20)], s1) self.assertEqual(region_map[(35, 40)], s1) self.assertEqual(region_map[(41, 44)], s2) self.assertEqual(region_map[(45, 50)], s1) self.assertEqual(region_map[(55, 60)], s2) self.assertEqual(region_map[(60, 65)], s3) def assert_results(self, expected_results, results): self.assertEquals(len(expected_results), len(results)) for i, result in enumerate(results): self.assertEqual(expected_results[i], result) def test_repeated_invocation_returns_new_list(self): results1 = self.find_regions('string', 'in') results2 = self.find_regions('string', 'in') self.assertIsNot(results1, results2) self.assert_results([(3, 5)], results1) self.assert_results([(3, 5)], results2) def test_missing_searchstr_return_empty_results(self): results = self.find_regions('some string', '') self.assert_results([], results) results = self.find_regions('some string', None) self.assert_results([], results) results = self.find_regions('', '') self.assert_results([], results) def test_no_match(self): results = self.find_regions('', 'a') self.assert_results([], results) results = self.find_regions('', 'foo') self.assert_results([], results) results = self.find_regions('some string', 'foo') self.assert_results([], results) def test_smart_simple_cases(self): results = self.find_regions('this is...', 'this') self.assert_results([(0, 4)], results) results = self.find_regions('my string', 'string') self.assert_results([(3, 9)], results) def test_single_char_match(self): results = self.find_regions('a', 'a') self.assert_results([(0, 1)], results) results = self.find_regions('aaaaa', 'a') self.assert_results([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)], results) results = self.find_regions('axaxa', 'a') self.assert_results([(0, 1), (2, 3), (4, 5)], results) results = self.find_regions('foo', 'f') self.assert_results([(0, 1)], results) results = self.find_regions('foo', 'o') self.assert_results([(1, 2), (2, 3)], results) def test_consecutive_matches(self): results = self.find_regions('isisis', 'is') self.assert_results([(0, 2), (2, 4), (4, 6)], results) results = self.find_regions('isisisis', 'is') self.assert_results([(0, 2), (2, 4), (4, 6), (6, 8)], results) results = self.find_regions('x isis', 'is') self.assert_results([(2, 4), (4, 6)], results) # 0 1 2 # 012345678901234567890 results = self.find_regions('this is his list isis', 'is') self.assert_results([(2, 4), (5, 7), (9, 11), (13, 15), (17, 19), (19, 21)], results) def test_find_regions_with_simple_regex(self): results = self.find_regions('x-11-11', regex('\d+')) self.assert_results([(2, 4), (5, 7)], results) results = self.find_regions('01-3456-11-11', regex('\d+')) self.assert_results([(0, 2), (3, 7), (8, 10), (11, 13)], results) results = self.find_regions('0123456789 nums', regex('\d+')) self.assert_results([(0, 10)], results) results = self.find_regions('0123456789', regex('\d+')) self.assert_results([(0, 10)], results) results = self.find_regions('some string', regex('\w+')) self.assert_results([(0, 4), (5, 11)], results) results = self.find_regions('some long string', regex('long')) self.assert_results([(5, 9)], results) results = self.find_regions('foo boo', regex('o+')) self.assert_results([(1, 3), (5, 7)], results) results = self.find_regions('foo boo', regex('o')) self.assert_results([(1, 2), (2, 3), (5, 6), (6, 7)], results) results = self.find_regions(" '192.168.99.1'", regex('\d+\.\d+\.\d+\.\d+')) self.assert_results([(2, 14)], results) def assert_results(self, expected_results, results): self.assertEquals(len(expected_results), len(results)) for i, result in enumerate(results): self.assertEqual(expected_results[i], result)