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-03-17 19:02:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-cmd2 (Old) and /work/SRC/openSUSE:Factory/.python-cmd2.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-cmd2" Tue Mar 17 19:02:30 2026 rev:56 rq:1339303 version:3.4.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-cmd2/python-cmd2.changes 2026-02-24 15:38:27.786076594 +0100 +++ /work/SRC/openSUSE:Factory/.python-cmd2.new.8177/python-cmd2.changes 2026-03-17 19:03:55.055229636 +0100 @@ -1,0 +2,23 @@ +Mon Mar 16 09:23:31 UTC 2026 - Dirk Müller <[email protected]> + +- update to 3.4.0: + * Moved cmd2-specific printing logic from `Cmd.print_to()` into + `Cmd2BaseConsole.print()` and + * `Cmd2BaseConsole.log()`. This removes need to pass a console + object to `Cmd.print_to()`. + * Addressed a bug in `rich.console.Console` where complex + renderables (like `Table` and `Rule`) may not receive + formatting settings passed to `console.print()` and + `console.log()`. + * Renamed the `destination` parameter of `Cmd.print_to()` back + to `file` since you can no longer pass in a console. + * Added ability to pass a console object to `Cmd.print_to()`. + This provides support for things like wrapping a `print_to()` + call in a `console.status()` or `console.capture()` context + manager. + * Renamed the `file` parameter of `Cmd.print_to()` to + `destination` to support file-like objects and console objects. + * `Cmd2BaseConsole(file)` argument is now a keyword-only + argument to be consistent with the `rich.console.Console` class. + +------------------------------------------------------------------- Old: ---- cmd2-3.2.2.tar.gz New: ---- cmd2-3.4.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-cmd2.spec ++++++ --- /var/tmp/diff_new_pack.06t2ZE/_old 2026-03-17 19:03:55.639253839 +0100 +++ /var/tmp/diff_new_pack.06t2ZE/_new 2026-03-17 19:03:55.643254005 +0100 @@ -17,7 +17,7 @@ Name: python-cmd2 -Version: 3.2.2 +Version: 3.4.0 Release: 0 Summary: Extra features for standard library's cmd module License: MIT ++++++ cmd2-3.2.2.tar.gz -> cmd2-3.4.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.2/CHANGELOG.md new/cmd2-3.4.0/CHANGELOG.md --- old/cmd2-3.2.2/CHANGELOG.md 2026-02-21 19:40:19.000000000 +0100 +++ new/cmd2-3.4.0/CHANGELOG.md 2026-03-03 17:08:35.000000000 +0100 @@ -1,3 +1,28 @@ +## 3.4.0 (March 3, 2026) + +- Enhancements + - Moved cmd2-specific printing logic from `Cmd.print_to()` into `Cmd2BaseConsole.print()` and + `Cmd2BaseConsole.log()`. This removes need to pass a console object to `Cmd.print_to()`. + - Addressed a bug in `rich.console.Console` where complex renderables (like `Table` and `Rule`) + may not receive formatting settings passed to `console.print()` and `console.log()`. + +- Breaking Changes + - Renamed the `destination` parameter of `Cmd.print_to()` back to `file` since you can no longer + pass in a console. + +## 3.3.0 (March 1, 2026) + +- Enhancements + - Added ability to pass a console object to `Cmd.print_to()`. This provides support for things + like wrapping a `print_to()` call in a `console.status()` or `console.capture()` context + manager. + +- Breaking Changes + - Renamed the `file` parameter of `Cmd.print_to()` to `destination` to support file-like objects + and console objects. + - `Cmd2BaseConsole(file)` argument is now a keyword-only argument to be consistent with the + `rich.console.Console` class. + ## 3.2.2 (February 21, 2026) - Bug Fixes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.2/cmd2/argparse_custom.py new/cmd2-3.4.0/cmd2/argparse_custom.py --- old/cmd2-3.2.2/cmd2/argparse_custom.py 2026-02-21 19:40:19.000000000 +0100 +++ new/cmd2-3.4.0/cmd2/argparse_custom.py 2026-03-03 17:08:35.000000000 +0100 @@ -1361,10 +1361,10 @@ self.print_usage(sys.stderr) - # Add error style to message + # Use console to add style since it will respect ALLOW_STYLE's value console = self._get_formatter().console with console.capture() as capture: - console.print(formatted_message, style=Cmd2Style.ERROR, crop=False) + console.print(formatted_message, style=Cmd2Style.ERROR) formatted_message = f"{capture.get()}" self.exit(2, f'{formatted_message}\n') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.2/cmd2/cmd2.py new/cmd2-3.4.0/cmd2/cmd2.py --- old/cmd2-3.2.2/cmd2/cmd2.py 2026-02-21 19:40:19.000000000 +0100 +++ new/cmd2-3.4.0/cmd2/cmd2.py 2026-03-03 17:08:35.000000000 +0100 @@ -65,7 +65,10 @@ ) import rich.box -from rich.console import Group, RenderableType +from rich.console import ( + Group, + RenderableType, +) from rich.highlighter import ReprHighlighter from rich.rule import Rule from rich.style import Style, StyleType @@ -133,6 +136,7 @@ shlex_split, ) from .rich_utils import ( + Cmd2BaseConsole, Cmd2ExceptionConsole, Cmd2GeneralConsole, RichPrintKwargs, @@ -165,7 +169,7 @@ # Set up readline if rl_type == RlType.NONE: # pragma: no cover - Cmd2GeneralConsole(sys.stderr).print(rl_warning, style=Cmd2Style.WARNING) + Cmd2GeneralConsole(file=sys.stderr).print(rl_warning, style=Cmd2Style.WARNING) else: from .rl_utils import ( readline, @@ -1293,11 +1297,9 @@ See the Rich documentation for more details on emoji codes, markup tags, and highlighting. """ - prepared_objects = ru.prepare_objects_for_rendering(*objects) - try: - Cmd2GeneralConsole(file).print( - *prepared_objects, + Cmd2BaseConsole(file=file).print( + *objects, sep=sep, end=end, style=style, @@ -1314,7 +1316,7 @@ # warning message, then set the broken_pipe_warning attribute # to the message you want printed. if self.broken_pipe_warning and file != sys.stderr: - Cmd2GeneralConsole(sys.stderr).print(self.broken_pipe_warning) + Cmd2GeneralConsole(file=sys.stderr).print(self.broken_pipe_warning) def poutput( self, @@ -1447,7 +1449,7 @@ :param kwargs: Arbitrary keyword arguments. This allows subclasses to extend the signature of this method and still call `super()` without encountering unexpected keyword argument errors. """ - console = Cmd2ExceptionConsole(sys.stderr) + console = Cmd2ExceptionConsole(file=sys.stderr) # Only print a traceback if we're in debug mode and one exists. if self.debug and sys.exc_info() != (None, None, None): @@ -1581,17 +1583,15 @@ # Check if we are outputting to a pager. if functional_terminal and can_block: - prepared_objects = ru.prepare_objects_for_rendering(*objects) - # Chopping overrides soft_wrap if chop: soft_wrap = True # Generate the bytes to send to the pager - console = Cmd2GeneralConsole(self.stdout) + console = Cmd2BaseConsole(file=self.stdout) with console.capture() as capture: console.print( - *prepared_objects, + *objects, sep=sep, end=end, style=style, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.2/cmd2/rich_utils.py new/cmd2-3.4.0/cmd2/rich_utils.py --- old/cmd2-3.2.2/cmd2/rich_utils.py 2026-02-21 19:40:19.000000000 +0100 +++ new/cmd2-3.4.0/cmd2/rich_utils.py 2026-03-03 17:08:35.000000000 +0100 @@ -1,6 +1,7 @@ """Provides common utilities to support Rich in cmd2-based applications.""" import re +import threading from collections.abc import Mapping from enum import Enum from typing import ( @@ -124,6 +125,7 @@ def __init__( self, + *, file: IO[str] | None = None, **kwargs: Any, ) -> None: @@ -172,25 +174,167 @@ theme=APP_THEME, **kwargs, ) + self._thread_local = threading.local() def on_broken_pipe(self) -> None: """Override which raises BrokenPipeError instead of SystemExit.""" self.quiet = True raise BrokenPipeError + def render_str( + self, + text: str, + highlight: bool | None = None, + markup: bool | None = None, + emoji: bool | None = None, + **kwargs: Any, + ) -> Text: + """Override to ensure formatting overrides passed to print() and log() are respected.""" + if emoji is None: + emoji = getattr(self._thread_local, "emoji", None) + if markup is None: + markup = getattr(self._thread_local, "markup", None) + if highlight is None: + highlight = getattr(self._thread_local, "highlight", None) + + return super().render_str(text, highlight=highlight, markup=markup, emoji=emoji, **kwargs) + + def print( + self, + *objects: Any, + sep: str = " ", + end: str = "\n", + style: StyleType | None = None, + justify: JustifyMethod | None = None, + overflow: OverflowMethod | None = None, + no_wrap: bool | None = None, + emoji: bool | None = None, + markup: bool | None = None, + highlight: bool | None = None, + width: int | None = None, + height: int | None = None, + crop: bool = True, + soft_wrap: bool | None = None, + new_line_start: bool = False, + ) -> None: + """Override to support ANSI sequences and address a bug in Rich. + + This method calls [cmd2.rich_utils.prepare_objects_for_rendering][] on the + objects being printed. This ensures that strings containing ANSI style + sequences are converted to Rich Text objects, so that Rich can correctly + calculate their display width. + + Additionally, it works around a bug in Rich where complex renderables + (like Table and Rule) may not receive formatting settings passed to print(). + By temporarily injecting these settings into thread-local storage, we ensure + that all internal rendering calls within the print() operation respect the + requested overrides. + + There is an issue on Rich to fix the latter: + https://github.com/Textualize/rich/issues/4028 + """ + prepared_objects = prepare_objects_for_rendering(*objects) + + # Inject overrides into thread-local storage + self._thread_local.emoji = emoji + self._thread_local.markup = markup + self._thread_local.highlight = highlight + + try: + super().print( + *prepared_objects, + sep=sep, + end=end, + style=style, + justify=justify, + overflow=overflow, + no_wrap=no_wrap, + emoji=emoji, + markup=markup, + highlight=highlight, + width=width, + height=height, + crop=crop, + soft_wrap=soft_wrap, + new_line_start=new_line_start, + ) + finally: + # Clear overrides from thread-local storage + self._thread_local.emoji = None + self._thread_local.markup = None + self._thread_local.highlight = None + + def log( + self, + *objects: Any, + sep: str = " ", + end: str = "\n", + style: StyleType | None = None, + justify: JustifyMethod | None = None, + emoji: bool | None = None, + markup: bool | None = None, + highlight: bool | None = None, + log_locals: bool = False, + _stack_offset: int = 1, + ) -> None: + """Override to support ANSI sequences and address a bug in Rich. + + This method calls [cmd2.rich_utils.prepare_objects_for_rendering][] on the + objects being logged. This ensures that strings containing ANSI style + sequences are converted to Rich Text objects, so that Rich can correctly + calculate their display width. + + Additionally, it works around a bug in Rich where complex renderables + (like Table and Rule) may not receive formatting settings passed to log(). + By temporarily injecting these settings into thread-local storage, we ensure + that all internal rendering calls within the log() operation respect the + requested overrides. + + There is an issue on Rich to fix the latter: + https://github.com/Textualize/rich/issues/4028 + """ + prepared_objects = prepare_objects_for_rendering(*objects) + + # Inject overrides into thread-local storage + self._thread_local.emoji = emoji + self._thread_local.markup = markup + self._thread_local.highlight = highlight + + try: + # Increment _stack_offset because we added this wrapper frame + super().log( + *prepared_objects, + sep=sep, + end=end, + style=style, + justify=justify, + emoji=emoji, + markup=markup, + highlight=highlight, + log_locals=log_locals, + _stack_offset=_stack_offset + 1, + ) + finally: + # Clear overrides from thread-local storage + self._thread_local.emoji = None + self._thread_local.markup = None + self._thread_local.highlight = None + class Cmd2GeneralConsole(Cmd2BaseConsole): - """Rich console for general-purpose printing.""" + """Rich console for general-purpose printing. + + It enables soft wrap and disables Rich's automatic detection for markup, + emoji, and highlighting. These defaults can be overridden in calls to the + console's or cmd2's print methods. + """ - def __init__(self, file: IO[str] | None = None) -> None: + def __init__(self, *, file: IO[str] | None = None) -> None: """Cmd2GeneralConsole initializer. :param file: optional file object where the console should write to. Defaults to sys.stdout. """ - # This console is configured for general-purpose printing. It enables soft wrap - # and disables Rich's automatic detection for markup, emoji, and highlighting. - # These defaults can be overridden in calls to the console's or cmd2's print methods. super().__init__( file=file, soft_wrap=True, @@ -203,23 +347,25 @@ class Cmd2RichArgparseConsole(Cmd2BaseConsole): """Rich console for rich-argparse output. - This class ensures long lines in help text are not truncated by avoiding soft_wrap, + Ensures long lines in help text are not truncated by disabling soft_wrap, which conflicts with rich-argparse's explicit no_wrap and overflow settings. + + Since this console is used to print error messages which may not be intended + for Rich formatting, it disables Rich's automatic detection for markup, emoji, + and highlighting. Because rich-argparse does markup and highlighting without + involving the console, disabling these settings does not affect the library's + internal functionality. """ - def __init__(self, file: IO[str] | None = None) -> None: + def __init__(self, *, file: IO[str] | None = None) -> None: """Cmd2RichArgparseConsole initializer. :param file: optional file object where the console should write to. Defaults to sys.stdout. """ - # Since this console is used to print error messages which may not have - # been pre-formatted by rich-argparse, disable Rich's automatic detection - # for markup, emoji, and highlighting. rich-argparse does markup and - # highlighting without involving the console so these won't affect its - # internal functionality. super().__init__( file=file, + soft_wrap=False, markup=False, emoji=False, highlight=False, @@ -227,11 +373,27 @@ class Cmd2ExceptionConsole(Cmd2BaseConsole): - """Rich console for printing exceptions. + """Rich console for printing exceptions and Rich Tracebacks. - Ensures that long exception messages word wrap for readability by keeping soft_wrap disabled. + Ensures that output is always word-wrapped for readability and disables + Rich's automatic detection for markup, emoji, and highlighting to prevent + interference with raw error data. """ + def __init__(self, *, file: IO[str] | None = None) -> None: + """Cmd2ExceptionConsole initializer. + + :param file: optional file object where the console should write to. + Defaults to sys.stdout. + """ + super().__init__( + file=file, + soft_wrap=False, + markup=False, + emoji=False, + highlight=False, + ) + def console_width() -> int: """Return the width of the console.""" @@ -252,9 +414,6 @@ force_terminal=True, soft_wrap=True, no_color=False, - markup=False, - emoji=False, - highlight=False, theme=APP_THEME, ) with console.capture() as capture: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.2/tests/test_cmd2.py new/cmd2-3.4.0/tests/test_cmd2.py --- old/cmd2-3.2.2/tests/test_cmd2.py 2026-02-21 19:40:19.000000000 +0100 +++ new/cmd2-3.4.0/tests/test_cmd2.py 2026-03-03 17:08:35.000000000 +0100 @@ -6,9 +6,7 @@ import signal import sys import tempfile -from code import ( - InteractiveConsole, -) +from code import InteractiveConsole from typing import NoReturn from unittest import mock diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmd2-3.2.2/tests/test_rich_utils.py new/cmd2-3.4.0/tests/test_rich_utils.py --- old/cmd2-3.2.2/tests/test_rich_utils.py 2026-02-21 19:40:19.000000000 +0100 +++ new/cmd2-3.4.0/tests/test_rich_utils.py 2026-03-03 17:08:35.000000000 +0100 @@ -13,6 +13,8 @@ ) from cmd2 import rich_utils as ru +from .conftest import with_ansi_style + def test_cmd2_base_console() -> None: # Test the keyword arguments which are not allowed. @@ -142,3 +144,51 @@ # 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.""" + from rich.rule import Rule + + # Create a console that defaults to no formatting + console = ru.Cmd2BaseConsole(emoji=False, markup=False) + + # Use a Rule with emoji and markup in the title + rule = Rule(title="[green]Success :1234:[/green]") + + with console.capture() as capture: + # Override settings in the print() call + console.print(rule, emoji=True, markup=True) + + result = capture.get() + + # Verify that the overrides were respected by checking for the emoji and the color code + assert "🔢" in result + assert "\x1b[32mSuccess" in result + + +@with_ansi_style(ru.AllowStyle.ALWAYS) +def test_cmd2_base_console_log() -> None: + """Test that Cmd2BaseConsole.log() correctly propagates formatting overrides to structured renderables.""" + from rich.rule import Rule + + # Create a console that defaults to no formatting + console = ru.Cmd2BaseConsole(emoji=False, markup=False) + + # Use a Rule with emoji and markup in the title + rule = Rule(title="[green]Success :1234:[/green]") + + with console.capture() as capture: + # Override settings in the log() call + console.log(rule, emoji=True, markup=True) + + result = capture.get() + + # Verify that the formatting overrides were respected + assert "🔢" in result + assert "\x1b[32mSuccess" in result + + # 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
