cmd2 3.2.0__tar.gz → 3.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cmd2-3.2.0 → cmd2-3.2.2}/CHANGELOG.md +14 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/PKG-INFO +1 -1
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/cmd2.py +2 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/rich_utils.py +5 -2
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/string_utils.py +4 -1
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2.egg-info/PKG-INFO +1 -1
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2.egg-info/SOURCES.txt +1 -0
- cmd2-3.2.2/tests/test_async_alert.py +50 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_string_utils.py +38 -5
- {cmd2-3.2.0 → cmd2-3.2.2}/.pre-commit-config.yaml +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/.prettierignore +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/.prettierrc +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/GEMINI.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/LICENSE +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/MANIFEST.in +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/Makefile +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/README.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/__init__.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/argparse_completer.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/argparse_custom.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/clipboard.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/colors.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/command_definition.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/constants.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/decorators.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/exceptions.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/history.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/parsing.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/plugin.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/py.typed +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/py_bridge.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/rl_utils.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/styles.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/terminal_utils.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/transcript.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2/utils.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2.egg-info/dependency_links.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2.egg-info/requires.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2.egg-info/top_level.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/cmd2.png +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/codecov.yml +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/argparse_completer.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/argparse_custom.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/clipboard.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/cmd.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/colors.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/command_definition.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/constants.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/decorators.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/exceptions.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/history.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/index.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/parsing.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/plugin.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/py_bridge.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/rich_utils.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/rl_utils.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/string_utils.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/styles.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/terminal_utils.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/transcript.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/api/utils.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/doc_conventions.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/examples/alternate_event_loops.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/examples/examples.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/examples/getting_started.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/examples/index.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/argument_processing.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/builtin_commands.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/clipboard.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/commands.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/completion.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/disable_commands.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/embedded_python_shells.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/generating_output.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/help.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/history.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/hooks.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/index.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/initialization.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/misc.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/modular_commands.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/multiline_commands.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/os.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/packaging.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/plugins.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/prompt.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/redirection.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/scripting.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/settings.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/shortcuts_aliases_macros.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/startup_commands.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/table_creation.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/theme.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/features/transcripts.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/index.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/javascripts/readthedocs.js +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/migrating/incompatibilities.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/migrating/index.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/migrating/minimum.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/migrating/next_steps.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/migrating/why.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/mixins/index.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/mixins/mixin_template.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/overrides/main.html +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/overview/alternatives.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/overview/index.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/overview/installation.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/overview/integrating.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/overview/resources.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/stylesheets/cmd2.css +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/testing.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/docs/upgrades.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/.cmd2rc +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/README.md +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/argparse_completion.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/argparse_example.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/async_call.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/async_printing.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/basic_completion.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/cmd_as_argument.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/color.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/command_sets.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/custom_parser.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/custom_types.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/default_categories.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/dynamic_commands.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/environment.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/event_loops.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/exit_code.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/getting_started.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/hello_cmd2.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/help_categories.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/hooks.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/migrating.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/mixin.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/modular_commands/__init__.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/modular_commands/commandset_basic.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/modular_commands/commandset_complex.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/modular_commands/commandset_custominit.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/modular_commands.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/paged_output.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/persistent_history.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/pretty_print.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/python_scripting.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/read_input.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/remove_builtin_commands.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/remove_settable.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/rich_tables.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/rich_theme.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/scripts/arg_printer.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/scripts/conditional.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/scripts/nested.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/scripts/quit.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/scripts/save_help_text.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/scripts/script.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/scripts/script.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/tmux_launch.sh +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/tmux_split.sh +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/transcript_example.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/transcripts/exampleSession.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/transcripts/pirate.transcript +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/transcripts/quit.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/transcripts/transcript_regex.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/examples/unicode_commands.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/mkdocs.yml +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/package.json +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/pyproject.toml +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/ruff.toml +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/scripts/validate_tag.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/setup.cfg +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/.cmd2rc +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/__init__.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/conftest.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/pyscript/echo.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/pyscript/environment.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/pyscript/help.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/pyscript/py_locals.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/pyscript/pyscript_dir.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/pyscript/raises_exception.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/pyscript/recursive.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/pyscript/self_in_py.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/pyscript/stdout_capture.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/pyscript/stop.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/relative_multiple.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/script.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/script.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/scripts/binary.bin +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/scripts/empty.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/scripts/help.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/scripts/nested.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/scripts/one_down.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/scripts/postcmds.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/scripts/precmds.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/scripts/utf8.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_argparse.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_argparse_completer.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_argparse_custom.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_argparse_subcommands.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_categories.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_cmd2.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_commandset.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_completion.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_future_annotations.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_history.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_parsing.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_plugin.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_rich_utils.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_run_pyscript.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_terminal_utils.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_transcript.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_utils.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/test_utils_defining_class.py +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/bol_eol.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/characterclass.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/dotstar.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/extension_notation.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/failure.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/from_cmdloop.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/multiline_no_regex.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/multiline_regex.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/no_output.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/no_output_last.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/singleslash.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/slashes_escaped.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/slashslash.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/spaces.txt +0 -0
- {cmd2-3.2.0 → cmd2-3.2.2}/tests/transcripts/word_boundaries.txt +0 -0
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 3.2.2 (February 21, 2026)
|
|
2
|
+
|
|
3
|
+
- Bug Fixes
|
|
4
|
+
- Updated `rich_utils.ANSI_STYLE_SEQUENCE_RE` to only match ANSI SGR (Select Graphic Rendition)
|
|
5
|
+
sequences for text styling. It previously also matched DEC Private Mode sequences.
|
|
6
|
+
|
|
7
|
+
## 3.2.1 (February 21, 2026)
|
|
8
|
+
|
|
9
|
+
- Bug Fixes
|
|
10
|
+
- The `async_alert` and `async_prompt_update` methods of `cmd2.Cmd` now respect the current
|
|
11
|
+
value of the `allow_style` settable
|
|
12
|
+
- If `allow_style` is `NEVER`, all style-related ANSI escape codes will be stripped to
|
|
13
|
+
ensure plain text output
|
|
14
|
+
|
|
1
15
|
## 3.2.0 (February 5, 2026)
|
|
2
16
|
|
|
3
17
|
- Bug Fixes
|
|
@@ -30,8 +30,11 @@ from rich_argparse import RichHelpFormatter
|
|
|
30
30
|
|
|
31
31
|
from .styles import DEFAULT_CMD2_STYLES
|
|
32
32
|
|
|
33
|
-
#
|
|
34
|
-
|
|
33
|
+
# Matches ANSI SGR (Select Graphic Rendition) sequences for text styling.
|
|
34
|
+
# \x1b[ - the CSI (Control Sequence Introducer)
|
|
35
|
+
# [0-9;]* - zero or more digits or semicolons (parameters for the style)
|
|
36
|
+
# m - the SGR final character
|
|
37
|
+
ANSI_STYLE_SEQUENCE_RE = re.compile(r"\x1b\[[0-9;]*m")
|
|
35
38
|
|
|
36
39
|
|
|
37
40
|
class AllowStyle(Enum):
|
|
@@ -95,7 +95,10 @@ def stylize(val: str, style: StyleType) -> str:
|
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
def strip_style(val: str) -> str:
|
|
98
|
-
"""Strip all ANSI style sequences from a string.
|
|
98
|
+
"""Strip all ANSI style sequences (colors, bold, etc.) from a string.
|
|
99
|
+
|
|
100
|
+
This targets SGR sequences specifically and leaves other terminal
|
|
101
|
+
control codes intact.
|
|
99
102
|
|
|
100
103
|
:param val: string to be stripped
|
|
101
104
|
:return: the stripped string
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from unittest.mock import MagicMock, patch
|
|
3
|
+
|
|
4
|
+
import cmd2
|
|
5
|
+
import cmd2.cmd2 # to patch vt100_support
|
|
6
|
+
from cmd2 import rich_utils as ru
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestAsyncAlert(unittest.TestCase):
|
|
10
|
+
def test_async_alert_strips_ansi_when_allow_style_is_never(self):
|
|
11
|
+
app = cmd2.Cmd()
|
|
12
|
+
|
|
13
|
+
# Patch vt100_support to True
|
|
14
|
+
with patch('cmd2.cmd2.vt100_support', True):
|
|
15
|
+
# Patch threading functions
|
|
16
|
+
mock_current_thread = MagicMock()
|
|
17
|
+
mock_current_thread.name = "NotMainThread"
|
|
18
|
+
|
|
19
|
+
with (
|
|
20
|
+
patch('threading.current_thread', return_value=mock_current_thread),
|
|
21
|
+
patch('threading.main_thread', return_value=MagicMock()),
|
|
22
|
+
patch('cmd2.cmd2.rl_get_display_prompt', return_value='(Cmd) '),
|
|
23
|
+
patch('cmd2.cmd2.readline.get_line_buffer', return_value=''),
|
|
24
|
+
patch('cmd2.cmd2.rl_get_point', return_value=0),
|
|
25
|
+
patch('cmd2.cmd2.rl_force_redisplay'),
|
|
26
|
+
patch('sys.stdout', new_callable=MagicMock) as mock_stdout,
|
|
27
|
+
):
|
|
28
|
+
# Set allow_style to NEVER
|
|
29
|
+
app.allow_style = ru.AllowStyle.NEVER
|
|
30
|
+
|
|
31
|
+
# Styled message
|
|
32
|
+
msg = "\033[31mError\033[0m"
|
|
33
|
+
|
|
34
|
+
# Call async_alert
|
|
35
|
+
app.async_alert(msg)
|
|
36
|
+
|
|
37
|
+
# Capture calls to write
|
|
38
|
+
# mock_stdout.write.call_args_list -> [call(str), call(str)...]
|
|
39
|
+
# We look at all written strings
|
|
40
|
+
written_content = "".join([call.args[0] for call in mock_stdout.write.call_args_list])
|
|
41
|
+
|
|
42
|
+
# Check that ANSI codes for color are NOT present
|
|
43
|
+
if "\033[31m" in written_content:
|
|
44
|
+
raise AssertionError(f"Found ANSI color code in output: {written_content!r}")
|
|
45
|
+
if "Error" not in written_content:
|
|
46
|
+
raise AssertionError(f"Message 'Error' not found in output: {written_content!r}")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if __name__ == '__main__':
|
|
50
|
+
unittest.main()
|
|
@@ -126,11 +126,44 @@ def test_stylize() -> None:
|
|
|
126
126
|
assert restyled_string == "\x1b[1;4;9;32;44mHello, world!\x1b[0m"
|
|
127
127
|
|
|
128
128
|
|
|
129
|
-
def
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
assert
|
|
133
|
-
assert
|
|
129
|
+
def test_strip_basic_styles() -> None:
|
|
130
|
+
# Test bold, colors, and resets
|
|
131
|
+
assert su.strip_style("\x1b[1mBold\x1b[0m") == "Bold"
|
|
132
|
+
assert su.strip_style("\x1b[31mRed\x1b[0m") == "Red"
|
|
133
|
+
assert su.strip_style("\x1b[4;32mUnderline Green\x1b[0m") == "Underline Green"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_strip_complex_colors() -> None:
|
|
137
|
+
# Test 256-color and RGB (TrueColor) sequences
|
|
138
|
+
# These use semicolons as separators and end in 'm'
|
|
139
|
+
assert su.strip_style("\x1b[38;5;208mOrange\x1b[0m") == "Orange"
|
|
140
|
+
assert su.strip_style("\x1b[38;2;255;87;51mCustom RGB\x1b[0m") == "Custom RGB"
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_preserve_non_style_csi() -> None:
|
|
144
|
+
# Test that cursor movements and other CSI codes are not stripped
|
|
145
|
+
# Cursor Up (\x1b[A) and Cursor Position (\x1b[10;5H)
|
|
146
|
+
cursor_up = "\x1b[A"
|
|
147
|
+
cursor_pos = "\x1b[10;5H"
|
|
148
|
+
assert su.strip_style(cursor_up) == cursor_up
|
|
149
|
+
assert su.strip_style(cursor_pos) == cursor_pos
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def test_preserve_private_modes() -> None:
|
|
153
|
+
# Test that DEC Private Modes (containing '?') are not stripped
|
|
154
|
+
# Hide cursor (\x1b[?25l) and Show cursor (\x1b[?25h)
|
|
155
|
+
hide_cursor = "\x1b[?25l"
|
|
156
|
+
show_cursor = "\x1b[?25h"
|
|
157
|
+
assert su.strip_style(hide_cursor) == hide_cursor
|
|
158
|
+
assert su.strip_style(show_cursor) == show_cursor
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def test_mixed_content() -> None:
|
|
162
|
+
# Test a string that has both style and control sequences
|
|
163
|
+
# Red text + Hide Cursor
|
|
164
|
+
mixed = "\x1b[31mRed Text\x1b[0m\x1b[?25l"
|
|
165
|
+
# Only the red style should be removed
|
|
166
|
+
assert su.strip_style(mixed) == "Red Text\x1b[?25l"
|
|
134
167
|
|
|
135
168
|
|
|
136
169
|
def test_str_width() -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|