From de7e6dcf47eb92f5a2caa8ff47465bf037ead73a Mon Sep 17 00:00:00 2001 From: Denis Bondar Date: Tue, 23 Jan 2024 16:12:42 +0200 Subject: [PATCH 1/2] Update ANSI_ESCAPE_PATTERN for discussion #313 --- scrapli/channel/base_channel.py | 12 +++++++----- tests/unit/channel/test_base_channel.py | 4 ++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/scrapli/channel/base_channel.py b/scrapli/channel/base_channel.py index 8c62f453..7b332147 100644 --- a/scrapli/channel/base_channel.py +++ b/scrapli/channel/base_channel.py @@ -11,13 +11,15 @@ from scrapli.transport.base import AsyncTransport, Transport ANSI_ESCAPE_PATTERN = re.compile( - rb"[\x1B\x9B]" - rb"[\[\]()#;?]*" + pattern=rb"[\x1B\x9B\x9D](\s)?" # Prefix ESC (^) or CSI (^[) or OSC (^]) rb"(" - rb"(([a-zA-Z0-9]*(;[a-zA-Z\d]*)*)?\x07)" + rb"([78ME])" # control cursor position rb"|" - rb"((\d{1,4}(;\d{0,4})*)?[\dA-PRZcf-ntqry=><~])" - rb")" + rb"([\x07])" # BEL (Terminal bell) + rb"|" + rb"(\[[{}();#=?0-9]*[A-Zhlnmsu~])" # control codes starts with `[` e.x. ESC [2;37;41m + rb")", + flags=re.VERBOSE, ) diff --git a/tests/unit/channel/test_base_channel.py b/tests/unit/channel/test_base_channel.py index aa786b15..e558a408 100644 --- a/tests/unit/channel/test_base_channel.py +++ b/tests/unit/channel/test_base_channel.py @@ -300,6 +300,10 @@ def test_process_output(base_channel): b"\x1b[7mCTRL+C\x1b[0m \x1b[7mESC\x1b[0m \x1b[7mq\x1b[0m Quit \x1b[7mSPACE\x1b[0m \x1b[7mn\x1b[0m Next Page \x1b[7mENTER\x1b[0m Next Entry \x1b[7ma\x1b[0m All\x1b[1A\x1b[59C\x1b[27m", b"CTRL+C ESC q Quit SPACE n Next Page ENTER Next Entry a All", ), + ( + b"\x1b7c\x1b8\x1b[1C\x1b7o\x1b8\x1b[1C\x1b7n\x1b8\x1b[1C\x1b7f\x1b8\x1b[1C\x1b7i\x1b8\x1b[1C\x1b7g\x1b8\x1b[1C\x1b7u\x1b8\x1b[1C\x1b7r\x1b8\x1b[1C\x1b7e\x1b8\x1b[1C", + b"configure", + ), ), ) def test_strip_ansi(base_channel, buf: bytes, expected: bytes): From a4261793d266746baa9b8e1443dbb8fbba2a18a1 Mon Sep 17 00:00:00 2001 From: Carl Montanari Date: Fri, 26 Jan 2024 17:31:05 -0800 Subject: [PATCH 2/2] test: add some more test cases! --- scrapli/channel/base_channel.py | 2 +- tests/unit/channel/test_base_channel.py | 44 +++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/scrapli/channel/base_channel.py b/scrapli/channel/base_channel.py index 7b332147..0e02221a 100644 --- a/scrapli/channel/base_channel.py +++ b/scrapli/channel/base_channel.py @@ -17,7 +17,7 @@ rb"|" rb"([\x07])" # BEL (Terminal bell) rb"|" - rb"(\[[{}();#=?0-9]*[A-Zhlnmsu~])" # control codes starts with `[` e.x. ESC [2;37;41m + rb"(\[[{}();#=?0-9]*[A-Zhglnmsu~])" # control codes starts with `[` e.x. ESC [2;37;41m rb")", flags=re.VERBOSE, ) diff --git a/tests/unit/channel/test_base_channel.py b/tests/unit/channel/test_base_channel.py index e558a408..f1afe1dd 100644 --- a/tests/unit/channel/test_base_channel.py +++ b/tests/unit/channel/test_base_channel.py @@ -300,6 +300,50 @@ def test_process_output(base_channel): b"\x1b[7mCTRL+C\x1b[0m \x1b[7mESC\x1b[0m \x1b[7mq\x1b[0m Quit \x1b[7mSPACE\x1b[0m \x1b[7mn\x1b[0m Next Page \x1b[7mENTER\x1b[0m Next Entry \x1b[7ma\x1b[0m All\x1b[1A\x1b[59C\x1b[27m", b"CTRL+C ESC q Quit SPACE n Next Page ENTER Next Entry a All", ), + ( + b"foo\x1B[4mcake\x1B[0m'", + b"foocake'", + ), + ( + b"\x1B[4mcake\x1B[0m", + b"cake", + ), + ( + b"foo\x1B[4mcake\x1B[0m", + b"foocake", + ), + ( + b"\x1B[0m\x1B[4m\x1B[42m\x1B[31mfoo\x1B[39m\x1B[49m\x1B[24mfoo\x1B[0m", + b"foofoo", + ), + ( + b"foo\x1B[mfoo", + b"foofoo", + ), + ( + b"\x1B[00;38;5;244m\x1B[m\x1B[00;38;5;33mfoo\x1B[0m", + b"foo", + ), + ( + b"\x1B[0;33;49;3;9;4mbar\x1B[0m", + b"bar", + ), + ( + b"foo\x1B[0;33;49;3;9;4mbar", + b"foobar", + ), + ( + b"foo\x1B[0gbar", + b"foobar", + ), + ( + b"foo\x1B[Kbar", + b"foobar", + ), + ( + b"foo\x1B[2Jbar", + b"foobar", + ), ( b"\x1b7c\x1b8\x1b[1C\x1b7o\x1b8\x1b[1C\x1b7n\x1b8\x1b[1C\x1b7f\x1b8\x1b[1C\x1b7i\x1b8\x1b[1C\x1b7g\x1b8\x1b[1C\x1b7u\x1b8\x1b[1C\x1b7r\x1b8\x1b[1C\x1b7e\x1b8\x1b[1C", b"configure",