def test_config_highlight_encapsulate_type_same(): """Three rules, with matches that encapsulate each other, same color type. The reset of a match would be updated to the color of the encapsulating one. Once the second match updates the reset of the first one to a color, it is no longer considered a reset, and therefore the third match would not update it to its own color. The order in which the rules are applied should not matter. 1: -- 2: ------ 3: ----------""" config = chromaterm.Config() rule1 = chromaterm.Rule('lo wo', color=chromaterm.Color('b#123123')) rule2 = chromaterm.Rule('llo wor', color=chromaterm.Color('b#321321')) rule3 = chromaterm.Rule('hello world', color=chromaterm.Color('b#abcabc')) config.add_rule(rule1) config.add_rule(rule2) config.add_rule(rule3) data = 'hello world' expected = [ rule3.color.color_code, 'he', rule2.color.color_code, 'l', rule1.color.color_code, 'lo wo', rule2.color.color_code, 'r', rule3.color.color_code, 'ld', rule3.color.color_reset ] assert repr(config.highlight(data)) == repr(''.join(expected)) config.remove_rule(rule1) config.remove_rule(rule2) config.add_rule(rule2) config.add_rule(rule1) assert repr(config.highlight(data)) == repr(''.join(expected))
def test_config_highlight_tracking_mixed_full_reset(): """Track multiple color types and ensure a full reset only defaults the types that were not updated by other colors in the data.""" config = chromaterm.cli.Config() rule1 = chromaterm.Rule('hello', color=chromaterm.Color('f#321321')) rule2 = chromaterm.Rule('world', color=chromaterm.Color('b#123123')) config.add_rule(rule1) config.add_rule(rule2) data = '\x1b[33mhello\x1b[m there \x1b[43mworld' expected = [ '\x1b[33m', rule1.color.color_code, 'hello', '\x1b[33m', '\x1b[m', ' there ', '\x1b[43m', rule2.color.color_code, 'world', '\x1b[43m' ] assert repr(config.highlight(data)) == repr(''.join(expected)) # The color of rule1 was reset to its default because a full reset came after # it, but the color of rule2 was already updated so it wasn't affected by the # full reset data = 'hello there world' expected = [ rule1.color.color_code, 'hello', rule1.color.color_reset, ' there ', rule2.color.color_code, 'world', '\x1b[43m' ] assert repr(config.highlight(data)) == repr(''.join(expected))
def test_config_highlight_encapsulate_type_different(): """Three rules, with matches that encapsulate each other, different color types. None of them should affect the rest as they are of different types. The order in which the rules are applied should not matter. 1: -- 2: ------ 3: ----------""" config = chromaterm.Config() rule1 = chromaterm.Rule('lo wo', color=chromaterm.Color('b#123123')) rule2 = chromaterm.Rule('llo wor', color=chromaterm.Color('f#321321')) rule3 = chromaterm.Rule('hello world', color=chromaterm.Color('bold')) config.add_rule(rule1) config.add_rule(rule2) config.add_rule(rule3) data = 'hello world' expected = [ rule3.color.color_code, 'he', rule2.color.color_code, 'l', rule1.color.color_code, 'lo wo', rule1.color.color_reset, 'r', rule2.color.color_reset, 'ld', rule3.color.color_reset ] assert repr(config.highlight(data)) == repr(''.join(expected)) config.remove_rule(rule1) config.remove_rule(rule2) config.add_rule(rule2) config.add_rule(rule1) assert repr(config.highlight(data)) == repr(''.join(expected))
def test_config_highlight_encapsulate_type_mixed(): """Three rules, with matches that encapsulate each other, mixed color types. The colors that are different should not affect each other, but those that are the same should correctly track each others colors and update their resets appropriately. 1: -- 2: ------ 3: ----------""" config = chromaterm.Config() rule1 = chromaterm.Rule('lo wo', color=chromaterm.Color('b#123123 italic')) rule2 = chromaterm.Rule('llo wor', color=chromaterm.Color('b#321321 bold')) rule3 = chromaterm.Rule('hello world', color=chromaterm.Color('bold')) config.add_rule(rule1) config.add_rule(rule2) config.add_rule(rule3) data = 'hello world' expected = [ rule3.color.color_code, 'he', rule2.color.color_code, 'l', rule1.color.color_code, 'lo wo', RESET_ITALIC, rule2.color.color_types[0][1], 'r', rule2.color.color_types[1][1], chromaterm.COLOR_TYPES[rule2.color.color_types[0][0]]['reset'], 'ld', rule3.color.color_reset ] assert repr(config.highlight(data)) == repr(''.join(expected)) config.remove_rule(rule1) config.remove_rule(rule2) config.add_rule(rule2) config.add_rule(rule1) assert repr(config.highlight(data)) == repr(''.join(expected))
def test_config_highlight_adjoin_type_mixed(): """Two rules with mixed color types, with one ending where the other starts. Both are applied without any overlap in the codes, independent of the order. 1: ------- 2: -------""" config = chromaterm.Config() rule1 = chromaterm.Rule('he', color=chromaterm.Color('b#123123 italic')) rule2 = chromaterm.Rule('llo', color=chromaterm.Color('b#321321 bold')) config.add_rule(rule1) config.add_rule(rule2) data = 'hello' expected = [ rule1.color.color_code, 'he', rule1.color.color_reset, rule2.color.color_code, 'llo', rule2.color.color_reset ] assert repr(config.highlight(data)) == repr(''.join(expected)) config.remove_rule(rule1) config.add_rule(rule1) assert repr(config.highlight(data)) == repr(''.join(expected))
def test_rule_change_color(pcre): '''Confirm that a color change overrides the old one.''' rule = chromaterm.Rule('hello', chromaterm.Color('bold'), pcre=pcre) old_color = rule.color rule.color = chromaterm.Color('b#123123') assert old_color is not rule.color
def test_rule_change_color(): """Confirm that a color change overrides the old one.""" rule = chromaterm.Rule('hello', color=chromaterm.Color('bold')) old_color = rule.color rule.color = chromaterm.Color('b#123123') assert old_color is not rule.color
def test_config_highlight_adjoin_type_mixed(pcre): '''Two rules with mixed color types, with one ending where the other starts. Both are applied without any overlap in the codes, independent of the order. 1: ------- 2: -------''' rule1 = chromaterm.Rule('he', chromaterm.Color('b#123123 blink'), pcre=pcre) rule2 = chromaterm.Rule('llo', chromaterm.Color('b#456456 bold'), pcre=pcre) config = chromaterm.Config() config.rules.append(rule1) config.rules.append(rule2) data = b'hello' expected = [ rule1.color.color_code, b'he', rule1.color.color_reset, rule2.color.color_code, b'llo', rule2.color.color_reset ] assert config.highlight(data) == b''.join(expected) config.rules.reverse() assert config.highlight(data) == b''.join(expected)
def test_config_highlight_encapsulate_type_mixed(pcre): '''Three rules, with matches that encapsulate each other, mixed color types. The colors that are different should not affect each other, but those that are the same should correctly track each others colors and update their resets appropriately. 1: -- 2: ------ 3: ----------''' rule1 = chromaterm.Rule('lo wo', chromaterm.Color('b#123123 italic'), pcre=pcre) rule2 = chromaterm.Rule('llo wor', chromaterm.Color('b#456456 bold'), pcre=pcre) rule3 = chromaterm.Rule('hello world', chromaterm.Color('bold'), pcre=pcre) config = chromaterm.Config() config.rules.append(rule1) config.rules.append(rule2) config.rules.append(rule3) data = b'hello world' expected = [ rule3.color.color_code, b'he', rule2.color.color_code, b'l', rule1.color.color_code, b'lo wo', RESET_ITALIC, rule2.color.color_types[0][1], b'r', rule2.color.color_types[1][1], chromaterm.COLOR_TYPES[rule2.color.color_types[0][0]]['reset'], b'ld', rule3.color.color_reset ] assert config.highlight(data) == b''.join(expected) config.rules.reverse() assert config.highlight(data) == b''.join(expected)
def test_config_highlight_encapsulate_type_different(pcre): '''Three rules, with matches that encapsulate each other, different color types. None of them should affect the rest as they are of different types. The order in which the rules are applied should not matter. 1: -- 2: ------ 3: ----------''' rule1 = chromaterm.Rule('lo wo', chromaterm.Color('b#123123'), pcre=pcre) rule2 = chromaterm.Rule('llo wor', chromaterm.Color('f#456456'), pcre=pcre) rule3 = chromaterm.Rule('hello world', chromaterm.Color('bold'), pcre=pcre) config = chromaterm.Config() config.rules.append(rule1) config.rules.append(rule2) config.rules.append(rule3) data = b'hello world' expected = [ rule3.color.color_code, b'he', rule2.color.color_code, b'l', rule1.color.color_code, b'lo wo', rule1.color.color_reset, b'r', rule2.color.color_reset, b'ld', rule3.color.color_reset ] assert config.highlight(data) == b''.join(expected) config.rules.reverse() assert config.highlight(data) == b''.join(expected)
def test_color___repr__(): """Confim Color's __repr__ format.""" color = chromaterm.Color('f#123123 bold b#123123 ') assert repr(color) == "Color('f#123123 bold b#123123')" color = chromaterm.Color('bold b#123123', rgb=True) assert repr(color) == "Color('bold b#123123', rgb=True)"
def test_config_highlight_encapsulate_type_same(pcre): '''Three rules, with matches that encapsulate each other, same color type. The reset of a match would be updated to the color of the encapsulating one. Once the second match updates the reset of the first one to a color, it is no longer considered a reset, and therefore the third match would not update it to its own color. The order in which the rules are applied should not matter. 1: -- 2: ------ 3: ----------''' rule1 = chromaterm.Rule('lo wo', chromaterm.Color('b#123123'), pcre=pcre) rule2 = chromaterm.Rule('llo wor', chromaterm.Color('b#456456'), pcre=pcre) rule3 = chromaterm.Rule('hello world', chromaterm.Color('b#abcabc'), pcre=pcre) config = chromaterm.Config() config.rules.append(rule1) config.rules.append(rule2) config.rules.append(rule3) data = b'hello world' expected = [ rule3.color.color_code, b'he', rule2.color.color_code, b'l', rule1.color.color_code, b'lo wo', rule2.color.color_code, b'r', rule3.color.color_code, b'ld', rule3.color.color_reset ] assert config.highlight(data) == b''.join(expected) config.rules.reverse() assert config.highlight(data) == b''.join(expected)
def test_color_invalid_value_background(): """Color with an incorrect background color.""" with pytest.raises(ValueError, match='invalid color format'): chromaterm.Color('b#12312') with pytest.raises(ValueError, match='invalid color format'): chromaterm.Color('b#12312x')
def test_config_highlight_overlap_partial_type_same(): """Two rules, partially overlapping matches, same color type. The reset of the first rule should be replaced with the color code of the second (most recent) rule to prevent the reset from interrupting the color. The behavior should be consistent regardless of the order of the rules. 1: ---------- 2: ----------""" config = chromaterm.Config() rule1 = chromaterm.Rule('hell', color=chromaterm.Color('b#123123')) rule2 = chromaterm.Rule('llo', color=chromaterm.Color('b#321321')) config.add_rule(rule1) config.add_rule(rule2) data = 'hello' expected = [ rule1.color.color_code, 'he', rule2.color.color_code, 'll', rule2.color.color_code, 'o', rule2.color.color_reset ] assert repr(config.highlight(data)) == repr(''.join(expected)) config.remove_rule(rule1) config.add_rule(rule1) assert repr(config.highlight(data)) == repr(''.join(expected))
def test_config_highlight_common_end_type_different(): """Two rules with different color types, and both sharing the same end of a match. The most recent rule will be closer to the match's end. 1: -------------- 2: -------""" config = chromaterm.Config() rule1 = chromaterm.Rule('hello', color=chromaterm.Color('b#123123')) rule2 = chromaterm.Rule('llo', color=chromaterm.Color('f#321321')) config.add_rule(rule1) config.add_rule(rule2) data = 'hello' expected = [ rule1.color.color_code, 'he', rule2.color.color_code, 'llo', rule2.color.color_reset, rule1.color.color_reset ] assert repr(config.highlight(data)) == repr(''.join(expected)) config.remove_rule(rule1) config.add_rule(rule1) # Flip end color expected[-1], expected[-2] = expected[-2], expected[-1] assert repr(config.highlight(data)) == repr(''.join(expected))
def test_config_highlight_overlap_partial_type_mixed(): """Two rules, partially overlapping matches, mixed color types. The different color types should not affect each other, but those that are the same should correctly update the reset that is in the middle of the other match to that of the match's color. Order of rules should not matter. 1: ---------- 2: ----------""" config = chromaterm.Config() rule1 = chromaterm.Rule('hell', color=chromaterm.Color('b#123123 bold')) rule2 = chromaterm.Rule('llo', color=chromaterm.Color('b#321321 italic')) config.add_rule(rule1) config.add_rule(rule2) data = 'hello' expected = [ rule1.color.color_code, 'he', rule2.color.color_code, 'll', RESET_BOLD, rule2.color.color_types[0][1], 'o', rule2.color.color_reset ] assert repr(config.highlight(data)) == repr(''.join(expected)) config.remove_rule(rule1) config.add_rule(rule1) assert repr(config.highlight(data)) == repr(''.join(expected))
def test_rule_format_color_dict(pcre): '''Accept a dictionary of groups and colors.''' colors = {1: chromaterm.Color('bold'), 2: chromaterm.Color('italic')} rule = chromaterm.Rule('h(e)(llo)', colors, pcre=pcre) assert rule.colors[1] is colors[1] assert rule.colors[2] is colors[2]
def test_color_invalid_value_foreground(): '''Color with an incorrect foreground color.''' with pytest.raises(ValueError, match='invalid color format'): chromaterm.Color('f#12312') with pytest.raises(ValueError, match='invalid color format'): chromaterm.Color('f#12312x')
def test_config_highlight_tracking_mixed_full_reset(pcre): '''Track multiple color types and ensure a full reset only defaults the types that were not updated by other colors in the data.''' rule1 = chromaterm.Rule('hello', chromaterm.Color('f#456456'), pcre=pcre) rule2 = chromaterm.Rule('world', chromaterm.Color('b#123123'), pcre=pcre) config = chromaterm.Config() config.rules.append(rule1) config.rules.append(rule2) data = b'\x1b[33mhello\x1b[0m there \x1b[43mworld' expected = [ b'\x1b[33m', rule1.color.color_code, b'hello', b'\x1b[33m', b'\x1b[0m', b' there ', b'\x1b[43m', rule2.color.color_code, b'world', b'\x1b[43m' ] assert config.highlight(data) == b''.join(expected) # The color of rule1 was reset to its default because a full reset came after # it, but the color of rule2 was already updated so it wasn't affected by the # full reset data = b'hello there world' expected = [ rule1.color.color_code, b'hello', rule1.color.color_reset, b' there ', rule2.color.color_code, b'world', b'\x1b[43m' ] assert config.highlight(data) == b''.join(expected)
def test_config_highlight_overlap_partial_type_same(pcre): '''Two rules, partially overlapping matches, same color type. The reset of the first rule should be replaced with the color code of the second (most recent) rule to prevent the reset from interrupting the color. The behavior should be consistent regardless of the order of the rules. 1: ---------- 2: ----------''' rule1 = chromaterm.Rule('hell', chromaterm.Color('b#123123 bold'), pcre=pcre) rule2 = chromaterm.Rule('llo', chromaterm.Color('b#456456 bold'), pcre=pcre) config = chromaterm.Config() config.rules.append(rule1) config.rules.append(rule2) data = b'hello' expected = [ rule1.color.color_code, b'he', rule2.color.color_code, b'll', rule2.color.color_types[1][1], rule2.color.color_types[0][1], b'o', rule2.color.color_reset ] assert config.highlight(data) == b''.join(expected) config.rules.reverse() assert config.highlight(data) == b''.join(expected)
def test_config_highlight_overlap_partial_type_mixed(pcre): '''Two rules, partially overlapping matches, mixed color types. The different color types should not affect each other, but those that are the same should correctly update the reset that is in the middle of the other match to that of the match's color. Order of rules should not matter. 1: ---------- 2: ----------''' rule1 = chromaterm.Rule('hell', chromaterm.Color('b#123123 bold'), pcre=pcre) rule2 = chromaterm.Rule('llo', chromaterm.Color('b#456456 italic'), pcre=pcre) config = chromaterm.Config() config.rules.append(rule1) config.rules.append(rule2) data = b'hello' expected = [ rule1.color.color_code, b'he', rule2.color.color_code, b'll', RESET_BOLD, rule2.color.color_types[0][1], b'o', rule2.color.color_reset ] assert config.highlight(data) == b''.join(expected) config.rules.reverse() assert config.highlight(data) == b''.join(expected)
def test_config___call__(): """Confim Config's decorator (__call__).""" config = chromaterm.Config() config.add_rule(chromaterm.Rule('hello', color=chromaterm.Color('bold'))) config.add_rule(chromaterm.Rule('world', color=chromaterm.Color('italic'))) @config def echo(*args): return ', '.join(args) assert repr(config.highlight('hello world')) == repr(echo('hello world'))
def test_rule_get_matches_groups(pcre): '''Get matches of rule that colors default and specific regex groups.''' colors = { 0: chromaterm.Color('bold'), 1: chromaterm.Color('b#123123'), 2: chromaterm.Color('f#456456') } rule = chromaterm.Rule('(h)(i)', colors, pcre=pcre) data = b'hi' expected = [(0, 2, colors[0]), (0, 1, colors[1]), (1, 2, colors[2])] assert rule.get_matches(data) == expected
def test_config_print(capsys): """Test the print wrapper for config.""" config = chromaterm.Config() rule1 = chromaterm.Rule('hello', color=chromaterm.Color('b#123123')) rule2 = chromaterm.Rule('world', color=chromaterm.Color('b#321321')) config.add_rule(rule1) config.add_rule(rule2) data = 'hello world' config.print(data) assert config.highlight(data) in capsys.readouterr().out
def test_rule___repr__(): """Confim Rule's __repr__ format.""" rule = chromaterm.Rule('hello') assert repr(rule) == "Rule('hello')" rule = chromaterm.Rule('hello', color=chromaterm.Color('bold')) assert repr(rule) == "Rule('hello', color=Color('bold'))" rule = chromaterm.Rule('hello', description='Yo') assert repr(rule) == "Rule('hello', description='Yo')" rule = chromaterm.Rule('hello', color=chromaterm.Color('bold'), description='Yo') assert repr(rule) == "Rule('hello', color=Color('bold'), description='Yo')"
def test_process_input_trailing_chunk(capsys, pcre): '''Ensure that a trailing chunk is joined with the next chunk if the latter arrives in time.''' pipe_r, pipe_w = os.pipe() config = chromaterm.__main__.Config() rule = chromaterm.Rule('hello world', chromaterm.Color('bold'), pcre=pcre) config.rules.append(rule) worker = threading.Thread(target=chromaterm.__main__.process_input, args=(config, pipe_r)) worker.start() # Write data, wait for it to be read, then write some more os.write(pipe_w, b'hello ') while select.select([pipe_r], [], [], 0)[0]: pass assert capsys.readouterr().out == '' os.write(pipe_w, b'world') os.close(pipe_w) worker.join() assert capsys.readouterr().out == '\x1b[1mhello world\x1b[22m'
def test_color_invalid_value_duplicate_style(): """Color with multiple background colors.""" styles = (k for k, v in chromaterm.COLOR_TYPES.items() if v.get('code')) for style in styles: with pytest.raises(ValueError, match='duplicate styles'): chromaterm.Color('{0} {0}'.format(style))
def test_rule_highlight_groups(): """Highlight with rule that colors default and specific regex groups.""" color1 = chromaterm.Color('bold') color2 = chromaterm.Color('b#123123') color3 = chromaterm.Color('f#321321') rule = chromaterm.Rule('(hello) (world)', color=color1) rule.add_color(color2, group=1) rule.add_color(color3, group=2) data = 'hello world' expected = [ color1.color_code, color2.color_code, 'hello', color2.color_reset, ' ', color3.color_code, 'world', color3.color_reset, color1.color_reset ] assert repr(rule.highlight(data)) == repr(''.join(expected))
def test_rule_highlight_zero_length_match(): """Highlight with rule that has a regex that matches zero-length data.""" color = chromaterm.Color('bold') rule = chromaterm.Rule('hello() world') rule.add_color(color, group=1) assert repr(rule.highlight('hello world')) == repr('hello world')
def test_rule_get_matches_new_line(pcre): '''Attempt to match a new line, which shouldn't be possible as it's considered as a separator (i.e. not passed to be highlighted). New lines are only used to replace data matched by exclusive rules.''' rule = chromaterm.Rule(r'hell\Wo', chromaterm.Color('bold'), pcre=pcre) assert not rule.get_matches(b'hell\no')