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()
