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-06-08 14:05:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-cmd2 (Old)
 and      /work/SRC/openSUSE:Factory/.python-cmd2.new.2375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-cmd2"

Mon Jun  8 14:05:17 2026 rev:57 rq:1357682 version:3.5.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-cmd2/python-cmd2.changes  2026-03-17 
19:03:55.055229636 +0100
+++ /work/SRC/openSUSE:Factory/.python-cmd2.new.2375/python-cmd2.changes        
2026-06-08 14:05:39.200131920 +0200
@@ -1,0 +2,18 @@
+Sat Jun  6 15:42:06 UTC 2026 - Matej Cepl <[email protected]>
+
+- Add failing_tests.patch (gh#python-cmd2/cmd2!1678) to make the
+  test suite work with the latest version of rich.
+
+-------------------------------------------------------------------
+Fri May 29 20:33:47 UTC 2026 - Matej Cepl <[email protected]>
+
+- Update to 3.5.1:
+  - Fixed ArgparseCompleter.print_help() not passing file stream
+    to recursive call.
+  - Fixed issue where constants.REDIRECTION_TOKENS was being
+    mutated.
+- Update to 3.5.0:
+  - Fixed issue where Rich stripped colors from text in test
+    environments where TERM=dumb.
+
+-------------------------------------------------------------------

Old:
----
  cmd2-3.4.0.tar.gz

New:
----
  cmd2-3.5.1.tar.gz
  failing_tests.patch

----------(New B)----------
  New:
- Add failing_tests.patch (gh#python-cmd2/cmd2!1678) to make the
  test suite work with the latest version of rich.
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-cmd2.spec ++++++
--- /var/tmp/diff_new_pack.kx1XkK/_old  2026-06-08 14:05:40.188172884 +0200
+++ /var/tmp/diff_new_pack.kx1XkK/_new  2026-06-08 14:05:40.196173216 +0200
@@ -17,13 +17,18 @@
 
 
 Name:           python-cmd2
-Version:        3.4.0
+Version:        3.5.1
 Release:        0
 Summary:        Extra features for standard library's cmd module
 License:        MIT
 URL:            https://github.com/python-cmd2/cmd2
 Source:         
https://github.com/python-cmd2/cmd2/archive/refs/tags/%{version}.tar.gz#/cmd2-%{version}.tar.gz
+# PATCH-FIX-OPENSUSE cmd2-no-coverage-tests.patch [email protected]
+# switch off code coverage measurement
 Patch0:         cmd2-no-coverage-tests.patch
+# PATCH-FIX-UPSTREAM failing_tests.patch gh#python-cmd2/cmd2!1678 
[email protected]
+# recent rich package makes stylize() function to eat EOLs, acommodate tests
+Patch1:         failing_tests.patch
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module wheel}
 BuildRequires:  %{pythons}

++++++ cmd2-3.4.0.tar.gz -> cmd2-3.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cmd2-3.4.0/CHANGELOG.md new/cmd2-3.5.1/CHANGELOG.md
--- old/cmd2-3.4.0/CHANGELOG.md 2026-03-03 17:08:35.000000000 +0100
+++ new/cmd2-3.5.1/CHANGELOG.md 2026-04-24 16:49:54.000000000 +0200
@@ -1,3 +1,14 @@
+## 3.5.1 (April 24, 2026)
+
+- Bug Fixes
+    - Fixed `ArgparseCompleter.print_help()` not passing file stream to 
recursive call.
+    - Fixed issue where `constants.REDIRECTION_TOKENS` was being mutated.
+
+## 3.5.0 (April 13, 2026)
+
+- Bug Fixes
+    - Fixed issue where Rich stripped colors from text in test environments 
where TERM=dumb.
+
 ## 3.4.0 (March 3, 2026)
 
 - Enhancements
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cmd2-3.4.0/cmd2/argparse_completer.py 
new/cmd2-3.5.1/cmd2/argparse_completer.py
--- old/cmd2-3.4.0/cmd2/argparse_completer.py   2026-03-03 17:08:35.000000000 
+0100
+++ new/cmd2-3.5.1/cmd2/argparse_completer.py   2026-04-24 16:49:54.000000000 
+0200
@@ -368,7 +368,7 @@
                     action = remaining_positionals.popleft()
 
                     # Are we at a subcommand? If so, forward to the matching 
completer
-                    if action == self._subcommand_action:
+                    if self._subcommand_action is not None and action == 
self._subcommand_action:
                         if token in self._subcommand_action.choices:
                             # Merge self._parent_tokens and consumed_arg_values
                             parent_tokens = {**self._parent_tokens, 
**consumed_arg_values}
@@ -637,7 +637,7 @@
             if parser:
                 completer_type = 
self._cmd2_app._determine_ap_completer_type(parser)
                 completer = completer_type(parser, self._cmd2_app)
-                completer.print_help(tokens[1:])
+                completer.print_help(tokens[1:], file=file)
                 return
 
         self._parser.print_help(file=file)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cmd2-3.4.0/cmd2/cmd2.py new/cmd2-3.5.1/cmd2/cmd2.py
--- old/cmd2-3.4.0/cmd2/cmd2.py 2026-03-03 17:08:35.000000000 +0100
+++ new/cmd2-3.5.1/cmd2/cmd2.py 2026-04-24 16:49:54.000000000 +0200
@@ -1666,10 +1666,8 @@
                  **On Failure**
                  - Two empty lists
         """
-        import copy
-
         unclosed_quote = ''
-        quotes_to_try = copy.copy(constants.QUOTES)
+        quotes_to_try = [*constants.QUOTES]
 
         tmp_line = line[:endidx]
         tmp_endidx = endidx
@@ -3721,8 +3719,7 @@
             return
 
         # Unquote redirection and terminator tokens
-        tokens_to_unquote = constants.REDIRECTION_TOKENS
-        tokens_to_unquote.extend(self.statement_parser.terminators)
+        tokens_to_unquote = [*constants.REDIRECTION_TOKENS, 
*self.statement_parser.terminators]
         utils.unquote_specific_tokens(args.command_args, tokens_to_unquote)
 
         # Build the alias value string
@@ -3801,8 +3798,7 @@
         """List some or all aliases as 'alias create' commands."""
         self.last_result = {}  # dict[alias_name, alias_value]
 
-        tokens_to_quote = constants.REDIRECTION_TOKENS
-        tokens_to_quote.extend(self.statement_parser.terminators)
+        tokens_to_quote = [*constants.REDIRECTION_TOKENS, 
*self.statement_parser.terminators]
 
         to_list = utils.remove_duplicates(args.names) if args.names else 
sorted(self.aliases, key=self.default_sort_key)
 
@@ -3964,8 +3960,7 @@
             return
 
         # Unquote redirection and terminator tokens
-        tokens_to_unquote = constants.REDIRECTION_TOKENS
-        tokens_to_unquote.extend(self.statement_parser.terminators)
+        tokens_to_unquote = [*constants.REDIRECTION_TOKENS, 
*self.statement_parser.terminators]
         utils.unquote_specific_tokens(args.command_args, tokens_to_unquote)
 
         # Build the macro value string
@@ -4087,8 +4082,7 @@
         """List macros."""
         self.last_result = {}  # dict[macro_name, macro_value]
 
-        tokens_to_quote = constants.REDIRECTION_TOKENS
-        tokens_to_quote.extend(self.statement_parser.terminators)
+        tokens_to_quote = [*constants.REDIRECTION_TOKENS, 
*self.statement_parser.terminators]
 
         to_list = utils.remove_duplicates(args.names) if args.names else 
sorted(self.macros, key=self.default_sort_key)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cmd2-3.4.0/cmd2/constants.py 
new/cmd2-3.5.1/cmd2/constants.py
--- old/cmd2-3.4.0/cmd2/constants.py    2026-03-03 17:08:35.000000000 +0100
+++ new/cmd2-3.5.1/cmd2/constants.py    2026-04-24 16:49:54.000000000 +0200
@@ -7,12 +7,12 @@
 
 # Used for command parsing, output redirection, tab completion and word
 # breaks. Do not change.
-QUOTES = ['"', "'"]
+QUOTES = ('"', "'")
 REDIRECTION_PIPE = '|'
 REDIRECTION_OUTPUT = '>'
 REDIRECTION_APPEND = '>>'
-REDIRECTION_CHARS = [REDIRECTION_PIPE, REDIRECTION_OUTPUT]
-REDIRECTION_TOKENS = [REDIRECTION_PIPE, REDIRECTION_OUTPUT, REDIRECTION_APPEND]
+REDIRECTION_CHARS = (REDIRECTION_PIPE, REDIRECTION_OUTPUT)
+REDIRECTION_TOKENS = (REDIRECTION_PIPE, REDIRECTION_OUTPUT, REDIRECTION_APPEND)
 COMMENT_CHAR = '#'
 MULTILINE_TERMINATOR = ';'
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cmd2-3.4.0/cmd2/parsing.py 
new/cmd2-3.5.1/cmd2/parsing.py
--- old/cmd2-3.4.0/cmd2/parsing.py      2026-03-03 17:08:35.000000000 +0100
+++ new/cmd2-3.5.1/cmd2/parsing.py      2026-04-24 16:49:54.000000000 +0200
@@ -298,10 +298,12 @@
         #       the string (\Z matches the end of the string even if it
         #       contains multiple lines)
         #
-        invalid_command_chars = []
-        invalid_command_chars.extend(constants.QUOTES)
-        invalid_command_chars.extend(constants.REDIRECTION_CHARS)
-        invalid_command_chars.extend(self.terminators)
+        invalid_command_chars = (
+            *constants.QUOTES,
+            *constants.REDIRECTION_CHARS,
+            *self.terminators,
+        )
+
         # escape each item so it will for sure get treated as a literal
         second_group_items = [re.escape(x) for x in invalid_command_chars]
         # add the whitespace and end of string, not escaped because they
@@ -352,9 +354,8 @@
                     return False, errmsg
 
         errmsg = 'cannot contain: whitespace, quotes, '
-        errchars = []
-        errchars.extend(constants.REDIRECTION_CHARS)
-        errchars.extend(self.terminators)
+
+        errchars = (*constants.REDIRECTION_CHARS, *self.terminators)
         errmsg += ', '.join([shlex.quote(x) for x in errchars])
 
         match = self._command_pattern.search(word)
@@ -677,9 +678,8 @@
         :param tokens: the tokens as parsed by shlex
         :return: a new list of tokens, further split using punctuation
         """
-        punctuation: list[str] = []
-        punctuation.extend(self.terminators)
-        punctuation.extend(constants.REDIRECTION_CHARS)
+        # Using a set for faster lookups
+        punctuation = {*self.terminators, *constants.REDIRECTION_CHARS}
 
         punctuated_tokens = []
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cmd2-3.4.0/cmd2/rich_utils.py 
new/cmd2-3.5.1/cmd2/rich_utils.py
--- old/cmd2-3.4.0/cmd2/rich_utils.py   2026-03-03 17:08:35.000000000 +0100
+++ new/cmd2-3.5.1/cmd2/rich_utils.py   2026-04-24 16:49:54.000000000 +0200
@@ -136,8 +136,9 @@
         :param kwargs: keyword arguments passed to the parent Console class.
         :raises TypeError: if disallowed keyword argument is passed in.
         """
-        # Don't allow force_terminal or force_interactive to be passed in, as 
their
-        # behavior is controlled by the ALLOW_STYLE setting.
+        # These settings are controlled by the ALLOW_STYLE setting and cannot 
be overridden.
+        if "color_system" in kwargs:
+            raise TypeError("Passing 'color_system' is not allowed. Its 
behavior is controlled by the 'ALLOW_STYLE' setting.")
         if "force_terminal" in kwargs:
             raise TypeError(
                 "Passing 'force_terminal' is not allowed. Its behavior is 
controlled by the 'ALLOW_STYLE' setting."
@@ -157,18 +158,24 @@
 
         force_terminal: bool | None = None
         force_interactive: bool | None = None
+        allow_style = False
 
         if ALLOW_STYLE == AllowStyle.ALWAYS:
             force_terminal = True
+            allow_style = True
 
             # Turn off interactive mode if dest is not actually a terminal 
which supports it
             tmp_console = Console(file=file)
             force_interactive = tmp_console.is_interactive
+        elif ALLOW_STYLE == AllowStyle.TERMINAL:
+            tmp_console = Console(file=file)
+            allow_style = tmp_console.is_terminal
         elif ALLOW_STYLE == AllowStyle.NEVER:
             force_terminal = False
 
         super().__init__(
             file=file,
+            color_system="truecolor" if allow_style else None,
             force_terminal=force_terminal,
             force_interactive=force_interactive,
             theme=APP_THEME,
@@ -412,6 +419,7 @@
     """
     console = Console(
         force_terminal=True,
+        color_system="truecolor",
         soft_wrap=True,
         no_color=False,
         theme=APP_THEME,
@@ -477,64 +485,3 @@
             object_list[i] = Text.from_ansi(renderable_as_str)
 
     return tuple(object_list)
-
-
-###################################################################################
-# Rich Library Monkey Patches
-#
-# These patches fix specific bugs in the Rich library. They are conditional and
-# will only be applied if the bug is detected. When the bugs are fixed in a
-# future Rich release, these patches and their corresponding tests should be
-# removed.
-###################################################################################
-
-###################################################################################
-# Text.from_ansi() monkey patch
-###################################################################################
-
-# Save original Text.from_ansi() so we can call it in our wrapper
-_orig_text_from_ansi = Text.from_ansi
-
-
-@classmethod  # type: ignore[misc]
-def _from_ansi_wrapper(cls: type[Text], text: str, *args: Any, **kwargs: Any) 
-> Text:  # noqa: ARG001
-    r"""Wrap Text.from_ansi() to fix its trailing newline bug.
-
-    This wrapper handles an issue where Text.from_ansi() removes the
-    trailing line break from a string (e.g. "Hello\n" becomes "Hello").
-
-    There is currently a pull request on Rich to fix this.
-    https://github.com/Textualize/rich/pull/3793
-    """
-    result = _orig_text_from_ansi(text, *args, **kwargs)
-
-    # If the original string ends with a recognized line break character,
-    # then restore the missing newline. We use "\n" because Text.from_ansi()
-    # converts all line breaks into newlines.
-    # Source: https://docs.python.org/3/library/stdtypes.html#str.splitlines
-    line_break_chars = {
-        "\n",  # Line Feed
-        "\r",  # Carriage Return
-        "\v",  # Vertical Tab
-        "\f",  # Form Feed
-        "\x1c",  # File Separator
-        "\x1d",  # Group Separator
-        "\x1e",  # Record Separator
-        "\x85",  # Next Line (NEL)
-        "\u2028",  # Line Separator
-        "\u2029",  # Paragraph Separator
-    }
-    if text and text[-1] in line_break_chars:
-        result.append("\n")
-
-    return result
-
-
-def _from_ansi_has_newline_bug() -> bool:
-    """Check if Test.from_ansi() strips the trailing line break from a 
string."""
-    return Text.from_ansi("\n") == Text.from_ansi("")
-
-
-# Only apply the monkey patch if the bug is present
-if _from_ansi_has_newline_bug():
-    Text.from_ansi = _from_ansi_wrapper  # type: ignore[assignment]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cmd2-3.4.0/cmd2/utils.py new/cmd2-3.5.1/cmd2/utils.py
--- old/cmd2-3.4.0/cmd2/utils.py        2026-03-03 17:08:35.000000000 +0100
+++ new/cmd2-3.5.1/cmd2/utils.py        2026-04-24 16:49:54.000000000 +0200
@@ -75,7 +75,7 @@
         settable_object: object,
         *,
         settable_attrib_name: str | None = None,
-        onchange_cb: Callable[[str, _T, _T], Any] | None = None,
+        onchange_cb: Callable[[str, Any, Any], Any] | None = None,
         choices: Iterable[Any] | None = None,
         choices_provider: ChoicesProviderFunc | None = None,
         completer: CompleterFunc | None = None,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cmd2-3.4.0/pyproject.toml 
new/cmd2-3.5.1/pyproject.toml
--- old/cmd2-3.4.0/pyproject.toml       2026-03-03 17:08:35.000000000 +0100
+++ new/cmd2-3.5.1/pyproject.toml       2026-04-24 16:49:54.000000000 +0200
@@ -33,8 +33,8 @@
     "gnureadline>=8; platform_system == 'Darwin'",
     "pyperclip>=1.8.2",
     "pyreadline3>=3.4; platform_system == 'Windows'",
-    "rich>=14.3.0",
-    "rich-argparse>=1.7.1",
+    "rich>=15.0.0",
+    "rich-argparse>=1.7.2",
     "typing-extensions; python_version == '3.10'",
 ]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cmd2-3.4.0/tests/test_cmd2.py 
new/cmd2-3.5.1/tests/test_cmd2.py
--- old/cmd2-3.4.0/tests/test_cmd2.py   2026-03-03 17:08:35.000000000 +0100
+++ new/cmd2-3.5.1/tests/test_cmd2.py   2026-04-24 16:49:54.000000000 +0200
@@ -2964,7 +2964,6 @@
 
     def do_echo_error(self, args) -> None:
         self.poutput(args, style=Cmd2Style.ERROR)
-        # perror uses colors by default
         self.perror(args)
 
 
@@ -2974,21 +2973,18 @@
     mocker.patch.object(app.stdout, 'isatty', return_value=True)
     mocker.patch.object(sys.stderr, 'isatty', return_value=True)
 
+    expected_plain = 'oopsie\n'
+    expected_styled = su.stylize('oopsie\n', Cmd2Style.ERROR)
+
     app.onecmd_plus_hooks('echo_error oopsie')
     out, err = capsys.readouterr()
-    # if colors are on, the output should have some ANSI style sequences in it
-    assert len(out) > len('oopsie\n')
-    assert 'oopsie' in out
-    assert len(err) > len('oopsie\n')
-    assert 'oopsie' in err
+    assert out == expected_styled
+    assert err == expected_styled
 
-    # but this one shouldn't
     app.onecmd_plus_hooks('echo oopsie')
     out, err = capsys.readouterr()
-    assert out == 'oopsie\n'
-    # errors always have colors
-    assert len(err) > len('oopsie\n')
-    assert 'oopsie' in err
+    assert out == expected_plain
+    assert err == expected_styled
 
 
 @with_ansi_style(ru.AllowStyle.ALWAYS)
@@ -2997,21 +2993,18 @@
     mocker.patch.object(app.stdout, 'isatty', return_value=False)
     mocker.patch.object(sys.stderr, 'isatty', return_value=False)
 
+    expected_plain = 'oopsie\n'
+    expected_styled = su.stylize('oopsie\n', Cmd2Style.ERROR)
+
     app.onecmd_plus_hooks('echo_error oopsie')
     out, err = capsys.readouterr()
-    # if colors are on, the output should have some ANSI style sequences in it
-    assert len(out) > len('oopsie\n')
-    assert 'oopsie' in out
-    assert len(err) > len('oopsie\n')
-    assert 'oopsie' in err
+    assert out == expected_styled
+    assert err == expected_styled
 
-    # but this one shouldn't
     app.onecmd_plus_hooks('echo oopsie')
     out, err = capsys.readouterr()
-    assert out == 'oopsie\n'
-    # errors always have colors
-    assert len(err) > len('oopsie\n')
-    assert 'oopsie' in err
+    assert out == expected_plain
+    assert err == expected_styled
 
 
 @with_ansi_style(ru.AllowStyle.TERMINAL)
@@ -3020,20 +3013,18 @@
     mocker.patch.object(app.stdout, 'isatty', return_value=True)
     mocker.patch.object(sys.stderr, 'isatty', return_value=True)
 
+    expected_plain = 'oopsie\n'
+    expected_styled = su.stylize('oopsie\n', Cmd2Style.ERROR)
+
     app.onecmd_plus_hooks('echo_error oopsie')
-    # if colors are on, the output should have some ANSI style sequences in it
     out, err = capsys.readouterr()
-    assert len(out) > len('oopsie\n')
-    assert 'oopsie' in out
-    assert len(err) > len('oopsie\n')
-    assert 'oopsie' in err
+    assert out == expected_styled
+    assert err == expected_styled
 
-    # but this one shouldn't
     app.onecmd_plus_hooks('echo oopsie')
     out, err = capsys.readouterr()
-    assert out == 'oopsie\n'
-    assert len(err) > len('oopsie\n')
-    assert 'oopsie' in err
+    assert out == expected_plain
+    assert err == expected_styled
 
 
 @with_ansi_style(ru.AllowStyle.TERMINAL)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cmd2-3.4.0/tests/test_rich_utils.py 
new/cmd2-3.5.1/tests/test_rich_utils.py
--- old/cmd2-3.4.0/tests/test_rich_utils.py     2026-03-03 17:08:35.000000000 
+0100
+++ new/cmd2-3.5.1/tests/test_rich_utils.py     2026-04-24 16:49:54.000000000 
+0200
@@ -1,5 +1,7 @@
 """Unit testing for cmd2/rich_utils.py module"""
 
+from unittest import mock
+
 import pytest
 import rich.box
 from rich.console import Console
@@ -19,6 +21,10 @@
 def test_cmd2_base_console() -> None:
     # Test the keyword arguments which are not allowed.
     with pytest.raises(TypeError) as excinfo:
+        ru.Cmd2BaseConsole(color_system="auto")
+    assert 'color_system' in str(excinfo.value)
+
+    with pytest.raises(TypeError) as excinfo:
         ru.Cmd2BaseConsole(force_terminal=True)
     assert 'force_terminal' in str(excinfo.value)
 
@@ -74,7 +80,12 @@
     [
         (Text("Hello"), "Hello"),
         (Text("Hello\n"), "Hello\n"),
-        (Text("Hello", style="blue"), "\x1b[34mHello\x1b[0m"),
+        # Test standard color support
+        (Text("Standard", style="blue"), "\x1b[34mStandard\x1b[0m"),
+        # Test 256-color support
+        (Text("256-color", style=Color.NAVY_BLUE), 
"\x1b[38;5;17m256-color\x1b[0m"),
+        # Test 24-bit color (TrueColor) support
+        (Text("TrueColor", style="#123456"), 
"\x1b[38;2;18;52;86mTrueColor\x1b[0m"),
     ],
 )
 def test_rich_text_to_string(rich_text: Text, string: str) -> None:
@@ -110,42 +121,6 @@
     assert ru.APP_THEME.styles[rich_style_key] == theme[rich_style_key]
 
 
-def test_from_ansi_wrapper() -> None:
-    # Check if we are still patching Text.from_ansi(). If this check fails, 
then Rich
-    # has fixed the bug. Therefore, we can remove this test function and 
ru._from_ansi_wrapper.
-    assert Text.from_ansi.__func__ is ru._from_ansi_wrapper.__func__  # type: 
ignore[attr-defined]
-
-    # Line breaks recognized by str.splitlines().
-    # Source: https://docs.python.org/3/library/stdtypes.html#str.splitlines
-    line_breaks = {
-        "\n",  # Line Feed
-        "\r",  # Carriage Return
-        "\r\n",  # Carriage Return + Line Feed
-        "\v",  # Vertical Tab
-        "\f",  # Form Feed
-        "\x1c",  # File Separator
-        "\x1d",  # Group Separator
-        "\x1e",  # Record Separator
-        "\x85",  # Next Line (NEL)
-        "\u2028",  # Line Separator
-        "\u2029",  # Paragraph Separator
-    }
-
-    # Test all line breaks
-    for lb in line_breaks:
-        input_string = f"Text{lb}"
-        expected_output = input_string.replace(lb, "\n")
-        assert Text.from_ansi(input_string).plain == expected_output
-
-    # Test string without trailing line break
-    input_string = "No trailing\nline break"
-    assert Text.from_ansi(input_string).plain == input_string
-
-    # Test empty string
-    input_string = ""
-    assert Text.from_ansi(input_string).plain == input_string
-
-
 @with_ansi_style(ru.AllowStyle.ALWAYS)
 def test_cmd2_base_console_print() -> None:
     """Test that Cmd2BaseConsole.print() correctly propagates formatting 
overrides to structured renderables."""
@@ -192,3 +167,88 @@
     # Verify stack offset: the log line should point to this file, not 
rich_utils.py
     # Rich logs include the filename and line number on the right.
     assert "test_rich_utils.py" in result
+
+
+@with_ansi_style(ru.AllowStyle.ALWAYS)
+def test_cmd2_base_console_init_always_interactive_true() -> None:
+    """Test Cmd2BaseConsole initialization when ALLOW_STYLE is ALWAYS and 
is_interactive is True."""
+    with (
+        mock.patch('rich.console.Console.__init__', return_value=None) as 
mock_base_init,
+        mock.patch('cmd2.rich_utils.Console', autospec=True) as 
mock_detect_console_class,
+    ):
+        mock_detect_console = mock_detect_console_class.return_value
+        mock_detect_console.is_interactive = True
+
+        ru.Cmd2BaseConsole()
+
+        # Verify arguments passed to super().__init__
+        _, kwargs = mock_base_init.call_args
+        assert kwargs['color_system'] == "truecolor"
+        assert kwargs['force_terminal'] is True
+        assert kwargs['force_interactive'] is True
+
+
+@with_ansi_style(ru.AllowStyle.ALWAYS)
+def test_cmd2_base_console_init_always_interactive_false() -> None:
+    """Test Cmd2BaseConsole initialization when ALLOW_STYLE is ALWAYS and 
is_interactive is False."""
+    with (
+        mock.patch('rich.console.Console.__init__', return_value=None) as 
mock_base_init,
+        mock.patch('cmd2.rich_utils.Console', autospec=True) as 
mock_detect_console_class,
+    ):
+        mock_detect_console = mock_detect_console_class.return_value
+        mock_detect_console.is_interactive = False
+
+        ru.Cmd2BaseConsole()
+
+        _, kwargs = mock_base_init.call_args
+        assert kwargs['color_system'] == "truecolor"
+        assert kwargs['force_terminal'] is True
+        assert kwargs['force_interactive'] is False
+
+
+@with_ansi_style(ru.AllowStyle.TERMINAL)
+def test_cmd2_base_console_init_terminal_true() -> None:
+    """Test Cmd2BaseConsole initialization when ALLOW_STYLE is TERMINAL and it 
is a terminal."""
+    with (
+        mock.patch('rich.console.Console.__init__', return_value=None) as 
mock_base_init,
+        mock.patch('cmd2.rich_utils.Console', autospec=True) as 
mock_detect_console_class,
+    ):
+        mock_detect_console = mock_detect_console_class.return_value
+        mock_detect_console.is_terminal = True
+
+        ru.Cmd2BaseConsole()
+
+        _, kwargs = mock_base_init.call_args
+        assert kwargs['color_system'] == "truecolor"
+        assert kwargs['force_terminal'] is None
+        assert kwargs['force_interactive'] is None
+
+
+@with_ansi_style(ru.AllowStyle.TERMINAL)
+def test_cmd2_base_console_init_terminal_false() -> None:
+    """Test Cmd2BaseConsole initialization when ALLOW_STYLE is TERMINAL and it 
is not a terminal."""
+    with (
+        mock.patch('rich.console.Console.__init__', return_value=None) as 
mock_base_init,
+        mock.patch('cmd2.rich_utils.Console', autospec=True) as 
mock_detect_console_class,
+    ):
+        mock_detect_console = mock_detect_console_class.return_value
+        mock_detect_console.is_terminal = False
+
+        ru.Cmd2BaseConsole()
+
+        _, kwargs = mock_base_init.call_args
+        assert kwargs['color_system'] is None
+        assert kwargs['force_terminal'] is None
+        assert kwargs['force_interactive'] is None
+
+
+@with_ansi_style(ru.AllowStyle.NEVER)
+def test_cmd2_base_console_init_never() -> None:
+    """Test Cmd2BaseConsole initialization when ALLOW_STYLE is NEVER."""
+    with mock.patch('rich.console.Console.__init__', return_value=None) as 
mock_base_init:
+        ru.Cmd2BaseConsole()
+
+        _, kwargs = mock_base_init.call_args
+        assert kwargs['color_system'] is None
+        assert kwargs['force_terminal'] is False
+        assert kwargs['force_interactive'] is None

++++++ cmd2-no-coverage-tests.patch ++++++
--- /var/tmp/diff_new_pack.kx1XkK/_old  2026-06-08 14:05:40.736195605 +0200
+++ /var/tmp/diff_new_pack.kx1XkK/_new  2026-06-08 14:05:40.748196103 +0200
@@ -1,8 +1,12 @@
-Index: cmd2-3.2.0/pyproject.toml
+---
+ pyproject.toml |    6 ------
+ 1 file changed, 6 deletions(-)
+
+Index: cmd2-3.5.1/pyproject.toml
 ===================================================================
---- cmd2-3.2.0.orig/pyproject.toml
-+++ cmd2-3.2.0/pyproject.toml
-@@ -97,12 +97,6 @@ warn_unused_ignores = false
+--- cmd2-3.5.1.orig/pyproject.toml     2026-04-24 16:49:54.000000000 +0200
++++ cmd2-3.5.1/pyproject.toml  2026-06-06 13:48:46.841665515 +0200
+@@ -97,12 +97,6 @@
  
  [tool.pytest.ini_options]
  testpaths = ["tests"]

++++++ failing_tests.patch ++++++
---
 tests/test_cmd2.py |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Index: cmd2-3.5.1/tests/test_cmd2.py
===================================================================
--- cmd2-3.5.1.orig/tests/test_cmd2.py  2026-04-24 16:49:54.000000000 +0200
+++ cmd2-3.5.1/tests/test_cmd2.py       2026-06-06 17:19:22.817175351 +0200
@@ -2974,7 +2974,7 @@
     mocker.patch.object(sys.stderr, 'isatty', return_value=True)
 
     expected_plain = 'oopsie\n'
-    expected_styled = su.stylize('oopsie\n', Cmd2Style.ERROR)
+    expected_styled = su.stylize('oopsie', Cmd2Style.ERROR) + '\n'
 
     app.onecmd_plus_hooks('echo_error oopsie')
     out, err = capsys.readouterr()
@@ -2994,7 +2994,7 @@
     mocker.patch.object(sys.stderr, 'isatty', return_value=False)
 
     expected_plain = 'oopsie\n'
-    expected_styled = su.stylize('oopsie\n', Cmd2Style.ERROR)
+    expected_styled = su.stylize('oopsie', Cmd2Style.ERROR) + '\n'
 
     app.onecmd_plus_hooks('echo_error oopsie')
     out, err = capsys.readouterr()
@@ -3014,7 +3014,7 @@
     mocker.patch.object(sys.stderr, 'isatty', return_value=True)
 
     expected_plain = 'oopsie\n'
-    expected_styled = su.stylize('oopsie\n', Cmd2Style.ERROR)
+    expected_styled = su.stylize('oopsie', Cmd2Style.ERROR) + '\n'
 
     app.onecmd_plus_hooks('echo_error oopsie')
     out, err = capsys.readouterr()

Reply via email to