Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-cmd2 for openSUSE:Factory checked in at 2026-02-24 15:38:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-cmd2 (Old) and /work/SRC/openSUSE:Factory/.python-cmd2.new.1977 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-cmd2" Tue Feb 24 15:38:06 2026 rev:55 rq:1334455 version:3.2.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-cmd2/python-cmd2.changes 2026-02-18 17:04:45.516047511 +0100 +++ /work/SRC/openSUSE:Factory/.python-cmd2.new.1977/python-cmd2.changes 2026-02-24 15:38:27.786076594 +0100 @@ -1,0 +2,12 @@ +Mon Feb 23 10:12:27 UTC 2026 - Dirk Müller <[email protected]> + +- update to 3.2.2: + * Updated `rich_utils.ANSI_STYLE_SEQUENCE_RE` to only match + ANSI SGR (Select Graphic Rendition) sequences for text styling. + * The `async_alert` and `async_prompt_update` methods of + `cmd2.Cmd` now respect the current value of the `allow_style` + settable + * If `allow_style` is `NEVER`, all style-related ANSI escape + codes will be stripped to ensure plain text output + +------------------------------------------------------------------- Old: ---- cmd2-3.2.0.tar.gz New: ---- cmd2-3.2.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-cmd2.spec ++++++ --- /var/tmp/diff_new_pack.J0uhb4/_old 2026-02-24 15:38:28.370100837 +0100 +++ /var/tmp/diff_new_pack.J0uhb4/_new 2026-02-24 15:38:28.370100837 +0100 @@ -17,7 +17,7 @@ Name: python-cmd2 -Version: 3.2.0 +Version: 3.2.2 Release: 0 Summary: Extra features for standard library's cmd module License: MIT ++++++ cmd2-3.2.0.tar.gz -> cmd2-3.2.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.0/CHANGELOG.md new/cmd2-3.2.2/CHANGELOG.md --- old/cmd2-3.2.0/CHANGELOG.md 2026-02-05 07:48:05.000000000 +0100 +++ new/cmd2-3.2.2/CHANGELOG.md 2026-02-21 19:40:19.000000000 +0100 @@ -1,3 +1,17 @@ +## 3.2.2 (February 21, 2026) + +- Bug Fixes + - Updated `rich_utils.ANSI_STYLE_SEQUENCE_RE` to only match ANSI SGR (Select Graphic Rendition) + sequences for text styling. It previously also matched DEC Private Mode sequences. + +## 3.2.1 (February 21, 2026) + +- Bug Fixes + - The `async_alert` and `async_prompt_update` methods of `cmd2.Cmd` now respect the current + value of the `allow_style` settable + - If `allow_style` is `NEVER`, all style-related ANSI escape codes will be stripped to + ensure plain text output + ## 3.2.0 (February 5, 2026) - Bug Fixes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.0/cmd2/cmd2.py new/cmd2-3.2.2/cmd2/cmd2.py --- old/cmd2-3.2.0/cmd2/cmd2.py 2026-02-05 07:48:05.000000000 +0100 +++ new/cmd2-3.2.2/cmd2/cmd2.py 2026-02-21 19:40:19.000000000 +0100 @@ -5744,6 +5744,8 @@ update_terminal = False if alert_msg: + if self.allow_style == ru.AllowStyle.NEVER: + alert_msg = su.strip_style(alert_msg) alert_msg += '\n' update_terminal = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.0/cmd2/rich_utils.py new/cmd2-3.2.2/cmd2/rich_utils.py --- old/cmd2-3.2.0/cmd2/rich_utils.py 2026-02-05 07:48:05.000000000 +0100 +++ new/cmd2-3.2.2/cmd2/rich_utils.py 2026-02-21 19:40:19.000000000 +0100 @@ -30,8 +30,11 @@ from .styles import DEFAULT_CMD2_STYLES -# A compiled regular expression to detect ANSI style sequences. -ANSI_STYLE_SEQUENCE_RE = re.compile(r"\x1b\[[0-9;?]*m") +# Matches ANSI SGR (Select Graphic Rendition) sequences for text styling. +# \x1b[ - the CSI (Control Sequence Introducer) +# [0-9;]* - zero or more digits or semicolons (parameters for the style) +# m - the SGR final character +ANSI_STYLE_SEQUENCE_RE = re.compile(r"\x1b\[[0-9;]*m") class AllowStyle(Enum): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.0/cmd2/string_utils.py new/cmd2-3.2.2/cmd2/string_utils.py --- old/cmd2-3.2.0/cmd2/string_utils.py 2026-02-05 07:48:05.000000000 +0100 +++ new/cmd2-3.2.2/cmd2/string_utils.py 2026-02-21 19:40:19.000000000 +0100 @@ -95,7 +95,10 @@ def strip_style(val: str) -> str: - """Strip all ANSI style sequences from a string. + """Strip all ANSI style sequences (colors, bold, etc.) from a string. + + This targets SGR sequences specifically and leaves other terminal + control codes intact. :param val: string to be stripped :return: the stripped string diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.0/tests/test_async_alert.py new/cmd2-3.2.2/tests/test_async_alert.py --- old/cmd2-3.2.0/tests/test_async_alert.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cmd2-3.2.2/tests/test_async_alert.py 2026-02-21 19:40:19.000000000 +0100 @@ -0,0 +1,50 @@ +import unittest +from unittest.mock import MagicMock, patch + +import cmd2 +import cmd2.cmd2 # to patch vt100_support +from cmd2 import rich_utils as ru + + +class TestAsyncAlert(unittest.TestCase): + def test_async_alert_strips_ansi_when_allow_style_is_never(self): + app = cmd2.Cmd() + + # Patch vt100_support to True + with patch('cmd2.cmd2.vt100_support', True): + # Patch threading functions + mock_current_thread = MagicMock() + mock_current_thread.name = "NotMainThread" + + with ( + patch('threading.current_thread', return_value=mock_current_thread), + patch('threading.main_thread', return_value=MagicMock()), + patch('cmd2.cmd2.rl_get_display_prompt', return_value='(Cmd) '), + patch('cmd2.cmd2.readline.get_line_buffer', return_value=''), + patch('cmd2.cmd2.rl_get_point', return_value=0), + patch('cmd2.cmd2.rl_force_redisplay'), + patch('sys.stdout', new_callable=MagicMock) as mock_stdout, + ): + # Set allow_style to NEVER + app.allow_style = ru.AllowStyle.NEVER + + # Styled message + msg = "\033[31mError\033[0m" + + # Call async_alert + app.async_alert(msg) + + # Capture calls to write + # mock_stdout.write.call_args_list -> [call(str), call(str)...] + # We look at all written strings + written_content = "".join([call.args[0] for call in mock_stdout.write.call_args_list]) + + # Check that ANSI codes for color are NOT present + if "\033[31m" in written_content: + raise AssertionError(f"Found ANSI color code in output: {written_content!r}") + if "Error" not in written_content: + raise AssertionError(f"Message 'Error' not found in output: {written_content!r}") + + +if __name__ == '__main__': + unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.0/tests/test_string_utils.py new/cmd2-3.2.2/tests/test_string_utils.py --- old/cmd2-3.2.0/tests/test_string_utils.py 2026-02-05 07:48:05.000000000 +0100 +++ new/cmd2-3.2.2/tests/test_string_utils.py 2026-02-21 19:40:19.000000000 +0100 @@ -126,11 +126,44 @@ assert restyled_string == "\x1b[1;4;9;32;44mHello, world!\x1b[0m" -def test_strip_style() -> None: - base_str = HELLO_WORLD - styled_str = su.stylize(base_str, style=Color.GREEN) - assert base_str != styled_str - assert base_str == su.strip_style(styled_str) +def test_strip_basic_styles() -> None: + # Test bold, colors, and resets + assert su.strip_style("\x1b[1mBold\x1b[0m") == "Bold" + assert su.strip_style("\x1b[31mRed\x1b[0m") == "Red" + assert su.strip_style("\x1b[4;32mUnderline Green\x1b[0m") == "Underline Green" + + +def test_strip_complex_colors() -> None: + # Test 256-color and RGB (TrueColor) sequences + # These use semicolons as separators and end in 'm' + assert su.strip_style("\x1b[38;5;208mOrange\x1b[0m") == "Orange" + assert su.strip_style("\x1b[38;2;255;87;51mCustom RGB\x1b[0m") == "Custom RGB" + + +def test_preserve_non_style_csi() -> None: + # Test that cursor movements and other CSI codes are not stripped + # Cursor Up (\x1b[A) and Cursor Position (\x1b[10;5H) + cursor_up = "\x1b[A" + cursor_pos = "\x1b[10;5H" + assert su.strip_style(cursor_up) == cursor_up + assert su.strip_style(cursor_pos) == cursor_pos + + +def test_preserve_private_modes() -> None: + # Test that DEC Private Modes (containing '?') are not stripped + # Hide cursor (\x1b[?25l) and Show cursor (\x1b[?25h) + hide_cursor = "\x1b[?25l" + show_cursor = "\x1b[?25h" + assert su.strip_style(hide_cursor) == hide_cursor + assert su.strip_style(show_cursor) == show_cursor + + +def test_mixed_content() -> None: + # Test a string that has both style and control sequences + # Red text + Hide Cursor + mixed = "\x1b[31mRed Text\x1b[0m\x1b[?25l" + # Only the red style should be removed + assert su.strip_style(mixed) == "Red Text\x1b[?25l" def test_str_width() -> None:
