diff --git a/colorama/ansitowin32.py b/colorama/ansitowin32.py index 6039a05..5242211 100644 --- a/colorama/ansitowin32.py +++ b/colorama/ansitowin32.py @@ -222,13 +222,27 @@ def extract_params(self, command, paramstring): def call_win32(self, command, params): if command == 'm': + # Ansi sequences started by specific param may need to be ignored, see #217 + skip, skip_count = False, None for param in params: + if skip: + if skip_count is not None: + skip_count -= 1 + continue + if param in (2, 5): + skip_count = 1 if param == 5 else 3 + continue + skip = False + skip_count = False if param in self.win32_calls: func_args = self.win32_calls[param] func = func_args[0] args = func_args[1:] kwargs = dict(on_stderr=self.on_stderr) func(*args, **kwargs) + elif param in (38, 48): + skip = True + elif command in 'J': winterm.erase_screen(params[0], on_stderr=self.on_stderr) elif command in 'K': diff --git a/colorama/tests/ansitowin32_test.py b/colorama/tests/ansitowin32_test.py index bbe99f4..a8fdca2 100644 --- a/colorama/tests/ansitowin32_test.py +++ b/colorama/tests/ansitowin32_test.py @@ -227,6 +227,30 @@ def test_osc_codes(self): for code in data: stream.write(code) self.assertEqual(winterm.set_title.call_count, 2) + + def testInvalidSequencesAreSkipped(self): + sequences = [ + (38, 5, 46), + (38, 2, 120, 33, 255), + (48, 5, 31), + (48, 2, 166, 226, 46), + (38, 48, 5, 46), + ] + for sequence in sequences: + listener = Mock() + stream = AnsiToWin32(listener) + stream.win32_calls = { + 2: (lambda *_, **__: listener(2),), + 5: (lambda *_, **__: listener(5),), + 33: (lambda *_, **__: listener(33),), + 46: (lambda *_, **__: listener(46),), + 166: (lambda *_, **__: listener(166),), + 226: (lambda *_, **__: listener(226),), + 255: (lambda *_, **__: listener(255),), + } + stream.call_win32('m', sequence) + self.assertFalse(listener.called) + if __name__ == '__main__': main()