From db6ca155f10eebc0491049584167c17f0a4022f6 Mon Sep 17 00:00:00 2001 From: Delgan Date: Sat, 25 May 2019 11:16:20 +0200 Subject: [PATCH 1/2] Fix special ansi sequences not ignored and producing wrong colors --- colorama/ansitowin32.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/colorama/ansitowin32.py b/colorama/ansitowin32.py index 6039a054..4da8f632 100644 --- a/colorama/ansitowin32.py +++ b/colorama/ansitowin32.py @@ -222,13 +222,26 @@ 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 = False for param in params: + if skip: + if skip is not True: + skip -= 1 + continue + if param in (2, 5): + skip = 1 if param == 5 else 3 + continue + skip = 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': From b07eab9cc1b8b752b80898b79dac6ab66790b4c7 Mon Sep 17 00:00:00 2001 From: Delgan Date: Sun, 28 Nov 2021 12:08:36 +0100 Subject: [PATCH 2/2] Add unit test to check invalid ANSI sequences --- colorama/ansitowin32.py | 9 +++++---- colorama/tests/ansitowin32_test.py | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/colorama/ansitowin32.py b/colorama/ansitowin32.py index 4da8f632..52422114 100644 --- a/colorama/ansitowin32.py +++ b/colorama/ansitowin32.py @@ -223,16 +223,17 @@ 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 = False + skip, skip_count = False, None for param in params: if skip: - if skip is not True: - skip -= 1 + if skip_count is not None: + skip_count -= 1 continue if param in (2, 5): - skip = 1 if param == 5 else 3 + 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] diff --git a/colorama/tests/ansitowin32_test.py b/colorama/tests/ansitowin32_test.py index bbe99f47..a8fdca20 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()