cmd2 4.2.3__tar.gz → 4.3.0__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-4.2.3 → cmd2-4.3.0}/.pre-commit-config.yaml +2 -2
- {cmd2-4.2.3 → cmd2-4.3.0}/.prettierrc +1 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/AGENTS.md +2 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/CHANGELOG.md +44 -0
- cmd2-4.3.0/CLAUDE.md +126 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/GEMINI.md +2 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/Makefile +3 -3
- {cmd2-4.2.3 → cmd2-4.3.0}/PKG-INFO +9 -3
- {cmd2-4.2.3 → cmd2-4.3.0}/README.md +8 -2
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/annotated.py +13 -14
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/argparse_completer.py +6 -6
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/argparse_utils.py +18 -18
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/cmd2.py +274 -106
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/decorators.py +3 -3
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/rich_utils.py +10 -12
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/types.py +7 -4
- cmd2-4.3.0/cmd2/utils.py +1643 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2.egg-info/PKG-INFO +9 -3
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2.egg-info/SOURCES.txt +5 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2.egg-info/scm_file_list.json +4 -1
- cmd2-4.3.0/cmd2.egg-info/scm_version.json +8 -0
- cmd2-4.3.0/docs/.DS_Store +0 -0
- cmd2-4.3.0/docs/assets/cmd2-logo.png +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/annotated.md +2 -27
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/argument_processing.md +1 -5
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/redirection.md +4 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/testing.md +22 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/annotated_example.py +4 -4
- cmd2-4.3.0/examples/cmd2_history.dat +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/getting_started.py +4 -4
- {cmd2-4.2.3 → cmd2-4.3.0}/mkdocs.yml +2 -1
- {cmd2-4.2.3 → cmd2-4.3.0}/pyproject.toml +32 -4
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/conftest.py +49 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_annotated.py +8 -8
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_cmd2.py +552 -31
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_history.py +13 -12
- cmd2-4.3.0/tests/test_pipeline_job_control.py +1381 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_run_pyscript.py +1 -1
- cmd2-4.3.0/tests/test_suite_environment.py +122 -0
- cmd2-4.3.0/tests/test_utils.py +1978 -0
- cmd2-4.3.0/ty.toml +9 -0
- cmd2-4.2.3/cmd2/utils.py +0 -858
- cmd2-4.2.3/cmd2.egg-info/scm_version.json +0 -8
- cmd2-4.2.3/examples/cmd2_history.dat +0 -0
- cmd2-4.2.3/tests/test_utils.py +0 -435
- cmd2-4.2.3/ty.toml +0 -7
- {cmd2-4.2.3 → cmd2-4.3.0}/.prettierignore +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/.typos.toml +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/LICENSE +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/MANIFEST.in +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/__init__.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/clipboard.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/colors.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/command_set.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/completion.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/constants.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/exceptions.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/history.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/parsing.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/plugin.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/pt_utils.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/py.typed +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/py_bridge.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/string_utils.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/styles.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2/theme.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2.egg-info/dependency_links.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2.egg-info/requires.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/cmd2.egg-info/top_level.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/codecov.yml +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/annotated.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/argparse_completer.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/argparse_utils.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/clipboard.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/cmd.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/colors.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/command_set.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/completion.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/constants.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/decorators.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/exceptions.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/history.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/index.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/parsing.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/plugin.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/pt_utils.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/py_bridge.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/rich_utils.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/string_utils.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/styles.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/theme.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/api/utils.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/assets/cmd2-readme-demo.gif +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/assets/getting-started-demo.gif +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/doc_conventions.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/examples/alternate_event_loops.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/examples/examples.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/examples/getting_started.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/examples/index.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/async_commands.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/builtin_commands.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/clipboard.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/commands.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/completion.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/disable_commands.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/embedded_python_shells.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/generating_output.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/help.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/history.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/hooks.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/index.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/initialization.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/misc.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/modular_commands.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/multiline_commands.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/os.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/packaging.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/plugins.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/prompt.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/scripting.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/settings.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/shortcuts_aliases_macros.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/startup_commands.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/table_creation.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/features/theme.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/index.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/javascripts/readthedocs.js +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/migrating/incompatibilities.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/migrating/index.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/migrating/minimum.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/migrating/next_steps.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/migrating/why.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/mixins/index.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/mixins/mixin_template.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/overrides/main.html +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/overview/alternatives.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/overview/index.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/overview/installation.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/overview/integrating.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/overview/resources.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/stylesheets/cmd2.css +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/docs/upgrades.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/.cmd2rc +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/README.md +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/argparse_completion.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/argparse_example.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/async_call.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/async_commands.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/async_printing.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/basic_completion.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/cmd_as_argument.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/color.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/command_sets.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/completion_item_choices.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/custom_parser.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/custom_types.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/default_categories.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/dynamic_commands.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/environment.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/event_loops.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/exit_code.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/hello_cmd2.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/help_categories.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/hooks.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/migrating.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/mixin.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/modular_commands/__init__.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/modular_commands/commandset_basic.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/modular_commands/commandset_complex.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/modular_commands/commandset_custominit.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/modular_commandsets.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/paged_output.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/persistent_history.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/pretty_print.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/python_scripting.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/read_input.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/remove_builtin_commands.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/remove_settable.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/rich_tables.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/rich_theme.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/scripts/arg_printer.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/scripts/conditional.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/scripts/nested.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/scripts/quit.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/scripts/save_help_text.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/scripts/script.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/scripts/script.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/tmux_launch.sh +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/tmux_split.sh +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/examples/unicode_commands.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/package.json +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/ruff.toml +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/scripts/validate_tag.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/setup.cfg +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/.cmd2rc +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/__init__.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/pyscript/echo.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/pyscript/environment.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/pyscript/help.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/pyscript/py_locals.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/pyscript/pyscript_dir.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/pyscript/raises_exception.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/pyscript/recursive.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/pyscript/self_in_py.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/pyscript/stop.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/pyscript/test_print.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/relative_multiple.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/script.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/script.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/scripts/binary.bin +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/scripts/empty.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/scripts/help.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/scripts/nested.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/scripts/one_down.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/scripts/postcmds.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/scripts/precmds.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/scripts/utf8.txt +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_argparse.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_argparse_completer.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_argparse_subcommands.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_argparse_utils.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_categories.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_commandset.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_completion.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_dynamic_complete_style.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_future_annotations.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_parsing.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_plugin.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_pt_utils.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_py_completion.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_rich_utils.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_string_utils.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_theme.py +0 -0
- {cmd2-4.2.3 → cmd2-4.3.0}/tests/test_utils_defining_class.py +0 -0
|
@@ -15,7 +15,7 @@ repos:
|
|
|
15
15
|
- id: trailing-whitespace
|
|
16
16
|
|
|
17
17
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
18
|
-
rev: "v0.
|
|
18
|
+
rev: "v0.17.0"
|
|
19
19
|
hooks:
|
|
20
20
|
- id: ruff-format
|
|
21
21
|
args: [--config=ruff.toml]
|
|
@@ -31,7 +31,7 @@ repos:
|
|
|
31
31
|
- prettier-plugin-toml@2.0.6
|
|
32
32
|
|
|
33
33
|
- repo: https://github.com/crate-ci/typos
|
|
34
|
-
rev: v1.
|
|
34
|
+
rev: v1.51.1
|
|
35
35
|
hooks:
|
|
36
36
|
- id: typos
|
|
37
37
|
exclude: |
|
|
@@ -15,6 +15,8 @@ project, which utilizes `uv` for environment and package management.
|
|
|
15
15
|
- **New Dependencies:** If a new dependency is required, please state the reason for its inclusion.
|
|
16
16
|
- Do not commit spec, plan, or markdown documents to git without asking first.
|
|
17
17
|
- Save plans to `~/.superpowers/plans/` instead of the project directory.
|
|
18
|
+
- This project uses a 127 character maximum line length for all Python code, including for comments.
|
|
19
|
+
- This project uses a 100 character maximum line length for Markdown files.
|
|
18
20
|
|
|
19
21
|
## Python Code Standards
|
|
20
22
|
|
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
## 4.3.0 (October 13, 2026)
|
|
2
|
+
|
|
3
|
+
- Stabilized features
|
|
4
|
+
- `@with_annotated` is no longer experimental. It was introduced as an experimental feature in
|
|
5
|
+
4.0.0 and is now a fully supported way to define a command's arguments, alongside
|
|
6
|
+
`@with_argparser`. This covers the decorator and its supporting API in `cmd2.annotated`,
|
|
7
|
+
including `Argument`, `Option`, `Group`, and `ArgumentBlock`.
|
|
8
|
+
[Annotated Argument Processing](https://cmd2.readthedocs.io/en/latest/features/annotated/).
|
|
9
|
+
- Bug Fixes
|
|
10
|
+
- On POSIX, piping a command's output to an interactive program such as `less`
|
|
11
|
+
(`help -v | less`) now runs that program as the terminal's foreground job, as a shell pipeline
|
|
12
|
+
does. It had run in a separate session that never received the terminal, so Ctrl-Z and `fg`
|
|
13
|
+
did not suspend and resume it together with cmd2. The program now owns the terminal as it
|
|
14
|
+
starts, so a pager can set its terminal modes, and Ctrl-C and Ctrl-Z reach the whole pipeline.
|
|
15
|
+
Pipes started from a worker thread, or whose output does not go to the terminal, such as one
|
|
16
|
+
nested in a command whose own output is piped, still run in their own session
|
|
17
|
+
- A `shell` command piped to an interactive program, such as `shell git log | less`, now joins
|
|
18
|
+
the pipeline's job, so both processes receive Ctrl-C and Ctrl-Z
|
|
19
|
+
- On Windows, fixed piped output appearing garbled in console programs such as `more`
|
|
20
|
+
(`help -v | more`), a regression in 4.2.4. Pipes are written as UTF-8, but console programs
|
|
21
|
+
decode their input with the console's code page. While a pipe or the pager runs, cmd2 now sets
|
|
22
|
+
the console to UTF-8 (code page 65001, as `chcp 65001` does) and restores its code pages
|
|
23
|
+
afterward, so console programs and UTF-8 tools such as `rg` both read the output correctly
|
|
24
|
+
- When copying a command's output to the clipboard (`help >`) fails, later commands' output is
|
|
25
|
+
no longer written to the temporary file that held it
|
|
26
|
+
- When a pipe's process cannot be started, for instance because no more processes can be created
|
|
27
|
+
or `$SHELL` names a program that cannot run, both ends of the pipe are now closed rather than
|
|
28
|
+
left open
|
|
29
|
+
- When a pipe's process exits before the command runs, what it wrote, such as the shell's
|
|
30
|
+
"command not found", is no longer lost when cmd2 captures the output, as in a pyscript
|
|
31
|
+
|
|
32
|
+
## 4.2.4 (September 8, 2026)
|
|
33
|
+
|
|
34
|
+
- Bug Fixes
|
|
35
|
+
- Fixed output redirection and piping raising `UnicodeEncodeError` and leaving an empty file
|
|
36
|
+
behind. Command output is rendered by Rich and contains box-drawing characters, which no
|
|
37
|
+
`cp125x` Windows ANSI code page can represent, so redirecting or piping it failed. This
|
|
38
|
+
affects current Windows 11 with default settings on Python 3.11 through 3.14, not only older
|
|
39
|
+
systems. Redirection targets and pipes now use UTF-8 explicitly
|
|
40
|
+
- Fixed the right prompt being redrawn beside every accepted command line in the scrollback.
|
|
41
|
+
prompt-toolkit includes it in the final frame of each prompt, which is the frame left on the
|
|
42
|
+
terminal; it is now hidden there, as the bottom toolbar already was, and stays on the live
|
|
43
|
+
prompt line only
|
|
44
|
+
|
|
1
45
|
## 4.2.3 (September 2, 2026)
|
|
2
46
|
|
|
3
47
|
- Bug Fixes
|
cmd2-4.3.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this
|
|
4
|
+
repository.
|
|
5
|
+
|
|
6
|
+
## Project
|
|
7
|
+
|
|
8
|
+
`cmd2` is a framework for building interactive command-line applications (REPLs) in Python. It
|
|
9
|
+
extends the stdlib `cmd` module and is built on **prompt-toolkit** (interactive input, key bindings,
|
|
10
|
+
completion, toolbars) and **Rich** / **rich-argparse** (all output rendering, help formatting,
|
|
11
|
+
theming). Requires Python >= 3.11. Environment/package management is **uv**.
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
All work happens inside the uv-managed venv — run Python via `uv run ...`, and `uvx ...` for one-off
|
|
16
|
+
tools. Never `pip install`; if a new dependency is needed, state why before adding it.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
make install # create the venv, install prek git hooks + prettier (one time)
|
|
20
|
+
make check # lock check + prek (ruff format/lint, prettier, typos) + ty + mypy
|
|
21
|
+
make test # pytest with coverage over tests/
|
|
22
|
+
make docs-test # verify the docs build cleanly (zensical)
|
|
23
|
+
make docs # build + serve docs with live reload
|
|
24
|
+
make help # list all targets
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`make check`, `make test`, and `make docs-test` must all pass before committing. Run `make check`
|
|
28
|
+
before creating or modifying any `.py` file as well.
|
|
29
|
+
|
|
30
|
+
Narrower targets: `make format`, `make lint`, `make mypy`, `make ty`, `make typecheck`.
|
|
31
|
+
|
|
32
|
+
Running a single test or file (coverage flags come from `pyproject.toml` `addopts`, so pass
|
|
33
|
+
`--no-cov` when you just want a fast run):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uv run pytest tests/test_cmd2.py --no-cov
|
|
37
|
+
uv run pytest tests/test_cmd2.py::test_base_help -x --no-cov
|
|
38
|
+
uv run pytest -k "toolbar" --no-cov
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
On Windows-sensitive code, note `make test` runs pytest under `python -Xutf8`.
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
|
|
45
|
+
### Command dispatch
|
|
46
|
+
|
|
47
|
+
`cmd2/cmd2.py` (the `Cmd` class) is the core and by far the largest module. The flow for one line of
|
|
48
|
+
input is:
|
|
49
|
+
|
|
50
|
+
1. `cmdloop()` → `_cmdloop()` drives a prompt-toolkit `PromptSession` (created in
|
|
51
|
+
`_create_prompt_session`), not readline. Completion, history, lexing, and key bindings are all
|
|
52
|
+
supplied by prompt-toolkit adapters in `cmd2/pt_utils.py` (`Cmd2Completer`, `Cmd2History`,
|
|
53
|
+
`Cmd2Lexer`).
|
|
54
|
+
2. `onecmd_plus_hooks()` parses the line into a `Statement` (`cmd2/parsing.py` — handles shortcuts,
|
|
55
|
+
aliases, macros, terminators, multiline commands, redirection and pipe tokens), then runs the
|
|
56
|
+
plugin hook chain.
|
|
57
|
+
3. `_redirect_output()` swaps `self.stdout` for a file or subprocess pipe when the statement has
|
|
58
|
+
redirection, and restores it in the `finally` path.
|
|
59
|
+
4. `onecmd()` looks up and calls the `do_*` method.
|
|
60
|
+
|
|
61
|
+
Hooks (`cmd2/plugin.py` dataclasses, registered via `register_postparsing_hook`,
|
|
62
|
+
`register_precmd_hook`, `register_postcmd_hook`, `register_cmdfinalization_hook`,
|
|
63
|
+
`register_preloop_hook`, `register_postloop_hook`) are the supported extension points; the legacy
|
|
64
|
+
`precmd`/`postcmd` overrides still exist but are weaker.
|
|
65
|
+
|
|
66
|
+
### Argument parsing and completion
|
|
67
|
+
|
|
68
|
+
Three layers, all producing a `Cmd2ArgumentParser`:
|
|
69
|
+
|
|
70
|
+
- `cmd2/argparse_utils.py` — `Cmd2ArgumentParser` plus monkey-patching that extends argparse with
|
|
71
|
+
range `nargs` tuples, per-argument completion metadata, and subcommand records.
|
|
72
|
+
- `cmd2/decorators.py` — `@with_argparser`, `@with_argument_list`, `@with_category`,
|
|
73
|
+
`@as_subcommand_to` attach parsers/metadata to `do_*` methods.
|
|
74
|
+
- `cmd2/annotated.py` — the newer Typer-style path (experimental in 4.0.0, stable as of 4.3.0):
|
|
75
|
+
`@with_annotated` builds a parser from a function's type hints, with `Argument`/`Option` metadata
|
|
76
|
+
via `typing.Annotated`.
|
|
77
|
+
|
|
78
|
+
Parsers are built lazily and cached by the `CommandParsers` class in `cmd2.py` (`_build_parser`), so
|
|
79
|
+
that `CommandSet`-supplied subcommands can be attached and detached at runtime.
|
|
80
|
+
`cmd2/argparse_completer.py` walks a parser to produce tab completions; completion results are
|
|
81
|
+
`Completions`/`CompletionItem` objects from `cmd2/completion.py`.
|
|
82
|
+
|
|
83
|
+
### Output and theming
|
|
84
|
+
|
|
85
|
+
Never print directly — go through `Cmd.print_to` / `poutput` / `perror` / `pwarning` / `pfeedback` /
|
|
86
|
+
`ppaged`, which route to Rich consoles defined in `cmd2/rich_utils.py` (`Cmd2GeneralConsole`,
|
|
87
|
+
`Cmd2RichArgparseConsole`, `Cmd2ExceptionConsole`). Styling flows one way: `cmd2/styles.py`
|
|
88
|
+
(style-name StrEnum + defaults) → `cmd2/theme.py` (single global theme, updated in-place for Rich
|
|
89
|
+
and exposed to prompt-toolkit through a `DynamicStyle`) → `cmd2/pt_utils.py` (`rich_to_pt_style`
|
|
90
|
+
converts Rich styles into prompt-toolkit ones). Adding a color or style means touching
|
|
91
|
+
`styles.py`/`colors.py`/`theme.py`, not hardcoding ANSI.
|
|
92
|
+
|
|
93
|
+
`cmd2/command_toolbar.py` and `cmd2/pager.py` are the trickiest parts of the codebase: they keep a
|
|
94
|
+
prompt-toolkit application alive _during_ synchronous command execution (bottom toolbar refresh,
|
|
95
|
+
paging) while stdout is proxied and redirection may be active. Changes there need care around
|
|
96
|
+
threads, signals, and Windows behavior.
|
|
97
|
+
|
|
98
|
+
### Modularity
|
|
99
|
+
|
|
100
|
+
`cmd2/command_set.py` (`CommandSet`) lets commands live in separate classes that are registered and
|
|
101
|
+
unregistered at runtime via `Cmd.register_command_set`; `cmd2/py_bridge.py` exposes the app to
|
|
102
|
+
embedded Python/IPython shells and `run_pyscript` while keeping isolation.
|
|
103
|
+
|
|
104
|
+
## Conventions
|
|
105
|
+
|
|
106
|
+
- Ruff is authoritative for format and lint (`ruff.toml`, line length 127, double quotes). Do not
|
|
107
|
+
suppress lint errors in code you write; broad ignores already exist for `examples/` and `tests/`.
|
|
108
|
+
- Both `mypy --strict` and `ty` must pass on the `cmd2` package. Full type annotations are required
|
|
109
|
+
on all library code (excluded: `tests/`, `examples/`, `docs/`).
|
|
110
|
+
- Docstrings are enforced by pydocstyle rules; public API items are documented in `docs/api/*.md`
|
|
111
|
+
and rendered by mkdocstrings, so keep docstrings accurate when changing signatures.
|
|
112
|
+
- Anything not documented under `docs/api/` is not public API (`cmd2/constants.py` says so
|
|
113
|
+
explicitly).
|
|
114
|
+
- Add user-visible changes to `CHANGELOG.md` under the current in-progress version heading.
|
|
115
|
+
- `main` is the branch for the next release, whether PATCH, MINOR, or MAJOR. Feature branches merge
|
|
116
|
+
into `main`, and all releases are tagged and published from it.
|
|
117
|
+
- Do not commit spec, plan, or markdown documents without asking first. Save plans to
|
|
118
|
+
`~/.superpowers/plans/` rather than the project directory.
|
|
119
|
+
- This project uses a 127 character maximum line length for all Python code, including for comments.
|
|
120
|
+
- This project uses a 100 character maximum line length for Markdown files.
|
|
121
|
+
|
|
122
|
+
## Commit conventions
|
|
123
|
+
|
|
124
|
+
Never add "Co-Authored-By" lines to commits. Do not include Claude attribution in commit messages,
|
|
125
|
+
PR descriptions, or any git metadata. Do not include Claude session URL in commit messages, PR
|
|
126
|
+
descriptions, or any git metadata.
|
|
@@ -15,6 +15,8 @@ Python project, which utilizes `uv` for environment and package management.
|
|
|
15
15
|
- **New Dependencies:** If a new dependency is required, please state the reason for its inclusion.
|
|
16
16
|
- Do not commit spec, plan, or markdown documents to git without asking first.
|
|
17
17
|
- Save plans to `~/.superpowers/plans/` instead of the project directory.
|
|
18
|
+
- This project uses a 127 character maximum line length for all Python code, including for comments.
|
|
19
|
+
- This project uses a 100 character maximum line length for Markdown files.
|
|
18
20
|
|
|
19
21
|
## Python Code Standards
|
|
20
22
|
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
.PHONY: install
|
|
6
6
|
install: ## Install the virtual environment with dependencies
|
|
7
7
|
@echo "🚀 Creating uv Python virtual environment"
|
|
8
|
-
@uv python install 3.
|
|
9
|
-
@uv sync --python=3.
|
|
8
|
+
@uv python install 3.15
|
|
9
|
+
@uv sync --python=3.15
|
|
10
10
|
@echo "🚀 Installing Git prek hooks locally"
|
|
11
11
|
@uv run prek install -f
|
|
12
12
|
@echo "🚀 Installing Prettier using npm"
|
|
@@ -47,7 +47,7 @@ typecheck: ## Perform type checking using both mypy and ty
|
|
|
47
47
|
.PHONY: test
|
|
48
48
|
test: ## Test the code with pytest.
|
|
49
49
|
@echo "🚀 Testing code: Running pytest"
|
|
50
|
-
@uv run python -Xutf8 -m pytest
|
|
50
|
+
@uv run python -Xutf8 -m pytest tests
|
|
51
51
|
|
|
52
52
|
.PHONY: docs-test
|
|
53
53
|
docs-test: ## Test if documentation can be built without warnings or errors
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cmd2
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.3.0
|
|
4
4
|
Summary: cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python
|
|
5
5
|
Author: cmd2 Contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -27,7 +27,10 @@ Requires-Dist: rich>=15.0.0
|
|
|
27
27
|
Requires-Dist: rich-argparse>=1.7.2
|
|
28
28
|
Dynamic: license-file
|
|
29
29
|
|
|
30
|
-
<
|
|
30
|
+
<p align="center">
|
|
31
|
+
<a href="https://github.com/python-cmd2/cmd2"><img src="https://raw.githubusercontent.com/python-cmd2/cmd2/main/docs/assets/cmd2-logo.png" alt="cmd2 logo" width="160"></a>
|
|
32
|
+
</p>
|
|
33
|
+
<h1 align="center">cmd2: build feature-rich command-line apps in Python</h1>
|
|
31
34
|
|
|
32
35
|
[](https://pypi.python.org/pypi/cmd2/)
|
|
33
36
|
[](https://github.com/python-cmd2/cmd2/actions/workflows/tests.yml)
|
|
@@ -115,7 +118,9 @@ to build a more complete application.
|
|
|
115
118
|
|
|
116
119
|
- Define commands as Python methods and use familiar
|
|
117
120
|
[`argparse`](https://cmd2.readthedocs.io/en/latest/features/argument_processing/) parsers for
|
|
118
|
-
arguments and subcommands
|
|
121
|
+
arguments and subcommands, or plain type hints via
|
|
122
|
+
[`@with_annotated`](https://cmd2.readthedocs.io/en/latest/features/annotated/). A single parser
|
|
123
|
+
definition drives validation, help, and completion.
|
|
119
124
|
- Render Rich tables and other styled objects, with consistent helpers for
|
|
120
125
|
[normal output, errors, warnings, and paging](https://cmd2.readthedocs.io/en/latest/features/generating_output/).
|
|
121
126
|
- Organize large applications into independently testable and dynamically loadable
|
|
@@ -251,6 +256,7 @@ reproduce the bug. At a minimum, please state the following:
|
|
|
251
256
|
| [Falcon Toolkit](https://github.com/CrowdStrike/Falcon-Toolkit) | Unleash the power of the CrowdStrike Falcon Platform at the CLI | [CrowdStrike](https://github.com/CrowdStrike) |
|
|
252
257
|
| [EXPLIoT](https://gitlab.com/expliot_framework/expliot) | Internet of Things Security Testing and Exploitation framework | [expliot_framework](https://gitlab.com/expliot_framework/) |
|
|
253
258
|
| [Pobshell](https://github.com/pdalloz/pobshell) | A Bash‑like shell for live Python objects: `cd`, `ls`, `cat`, `find` and _CLI piping_ for object code, str values & more | [Peter Dalloz](https://www.linkedin.com/in/pdalloz) |
|
|
259
|
+
| [Wtsh](https://gitee.com/wazzge/wtsh) | WTSH is a shell built with Python cmd2(v4), which uses third-party plugins to construct a universal shell installed via Pip | [wazzge](https://gitee.com/wazzge) |
|
|
254
260
|
|
|
255
261
|
Possibly defunct but still good examples
|
|
256
262
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
<
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://github.com/python-cmd2/cmd2"><img src="https://raw.githubusercontent.com/python-cmd2/cmd2/main/docs/assets/cmd2-logo.png" alt="cmd2 logo" width="160"></a>
|
|
3
|
+
</p>
|
|
4
|
+
<h1 align="center">cmd2: build feature-rich command-line apps in Python</h1>
|
|
2
5
|
|
|
3
6
|
[](https://pypi.python.org/pypi/cmd2/)
|
|
4
7
|
[](https://github.com/python-cmd2/cmd2/actions/workflows/tests.yml)
|
|
@@ -86,7 +89,9 @@ to build a more complete application.
|
|
|
86
89
|
|
|
87
90
|
- Define commands as Python methods and use familiar
|
|
88
91
|
[`argparse`](https://cmd2.readthedocs.io/en/latest/features/argument_processing/) parsers for
|
|
89
|
-
arguments and subcommands
|
|
92
|
+
arguments and subcommands, or plain type hints via
|
|
93
|
+
[`@with_annotated`](https://cmd2.readthedocs.io/en/latest/features/annotated/). A single parser
|
|
94
|
+
definition drives validation, help, and completion.
|
|
90
95
|
- Render Rich tables and other styled objects, with consistent helpers for
|
|
91
96
|
[normal output, errors, warnings, and paging](https://cmd2.readthedocs.io/en/latest/features/generating_output/).
|
|
92
97
|
- Organize large applications into independently testable and dynamically loadable
|
|
@@ -222,6 +227,7 @@ reproduce the bug. At a minimum, please state the following:
|
|
|
222
227
|
| [Falcon Toolkit](https://github.com/CrowdStrike/Falcon-Toolkit) | Unleash the power of the CrowdStrike Falcon Platform at the CLI | [CrowdStrike](https://github.com/CrowdStrike) |
|
|
223
228
|
| [EXPLIoT](https://gitlab.com/expliot_framework/expliot) | Internet of Things Security Testing and Exploitation framework | [expliot_framework](https://gitlab.com/expliot_framework/) |
|
|
224
229
|
| [Pobshell](https://github.com/pdalloz/pobshell) | A Bash‑like shell for live Python objects: `cd`, `ls`, `cat`, `find` and _CLI piping_ for object code, str values & more | [Peter Dalloz](https://www.linkedin.com/in/pdalloz) |
|
|
230
|
+
| [Wtsh](https://gitee.com/wazzge/wtsh) | WTSH is a shell built with Python cmd2(v4), which uses third-party plugins to construct a universal shell installed via Pip | [wazzge](https://gitee.com/wazzge) |
|
|
225
231
|
|
|
226
232
|
Possibly defunct but still good examples
|
|
227
233
|
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
"""Build argparse parsers from type-annotated function signatures.
|
|
2
2
|
|
|
3
|
-
!!! warning "Experimental"
|
|
4
|
-
|
|
5
|
-
This module is experimental and its behavior may change in future releases.
|
|
6
|
-
|
|
7
3
|
The [`with_annotated`][cmd2.annotated.with_annotated] decorator inspects a command function's type hints and
|
|
8
4
|
default values to build a ``Cmd2ArgumentParser``. [`Argument`][cmd2.annotated.Argument] and
|
|
9
5
|
[`Option`][cmd2.annotated.Option] metadata classes give finer per-parameter control via
|
|
@@ -313,6 +309,7 @@ from .rich_utils import Cmd2HelpFormatter, HelpContent
|
|
|
313
309
|
from .types import (
|
|
314
310
|
BoundCommandFunc,
|
|
315
311
|
CmdOrSetT,
|
|
312
|
+
CmdOrSetT_contra,
|
|
316
313
|
UnboundChoicesProvider,
|
|
317
314
|
UnboundCompleter,
|
|
318
315
|
)
|
|
@@ -712,7 +709,7 @@ def _make_enum_type(enum_class: type[enum.Enum], *, allow_unknown_entry: bool =
|
|
|
712
709
|
raise _invalid_choice(value, _value_map)
|
|
713
710
|
|
|
714
711
|
_convert.__name__ = enum_class.__name__
|
|
715
|
-
_convert._cmd2_enum_class = enum_class # type: ignore[attr-defined
|
|
712
|
+
_convert._cmd2_enum_class = enum_class # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
716
713
|
return _convert
|
|
717
714
|
|
|
718
715
|
|
|
@@ -988,7 +985,7 @@ def _unwrap_optional(tp: Any) -> tuple[Any, bool]:
|
|
|
988
985
|
there alone, so this helper never validates union members itself.
|
|
989
986
|
"""
|
|
990
987
|
origin = get_origin(tp)
|
|
991
|
-
if origin is Union or origin is types.UnionType:
|
|
988
|
+
if origin is Union or origin is types.UnionType:
|
|
992
989
|
all_args = get_args(tp)
|
|
993
990
|
non_none = [a for a in all_args if a is not type(None)]
|
|
994
991
|
has_none = len(non_none) < len(all_args)
|
|
@@ -1013,14 +1010,14 @@ def _normalize_annotation(annotation: Any) -> _NormalizedAnnotation:
|
|
|
1013
1010
|
tp, unwrapped = _unwrap_optional(tp)
|
|
1014
1011
|
if unwrapped:
|
|
1015
1012
|
is_optional = True
|
|
1016
|
-
if get_origin(tp) is Annotated:
|
|
1013
|
+
if get_origin(tp) is Annotated:
|
|
1017
1014
|
inner_tp = get_args(tp)[0]
|
|
1018
1015
|
inner_origin = get_origin(inner_tp)
|
|
1019
|
-
inner_is_union = inner_origin is Union or inner_origin is types.UnionType
|
|
1016
|
+
inner_is_union = inner_origin is Union or inner_origin is types.UnionType
|
|
1020
1017
|
if not (inner_is_union and type(None) in get_args(inner_tp)):
|
|
1021
1018
|
raise TypeError("Annotated[T, meta] | None is ambiguous. Use Annotated[T | None, meta] instead.")
|
|
1022
1019
|
|
|
1023
|
-
if get_origin(tp) is Annotated:
|
|
1020
|
+
if get_origin(tp) is Annotated:
|
|
1024
1021
|
args = get_args(tp)
|
|
1025
1022
|
tp = args[0]
|
|
1026
1023
|
for meta in args[1:]:
|
|
@@ -1118,7 +1115,7 @@ def _compose_preprocess(preprocess: Callable[[str], str], converter: Callable[[s
|
|
|
1118
1115
|
_convert.__name__ = getattr(converter, "__name__", "preprocess")
|
|
1119
1116
|
enum_class = getattr(converter, "_cmd2_enum_class", None)
|
|
1120
1117
|
if enum_class is not None:
|
|
1121
|
-
_convert._cmd2_enum_class = enum_class # type: ignore[attr-defined
|
|
1118
|
+
_convert._cmd2_enum_class = enum_class # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
1122
1119
|
return _convert
|
|
1123
1120
|
|
|
1124
1121
|
|
|
@@ -2907,23 +2904,25 @@ class _BoundAnnotatedCommand(Protocol[_CommandParams, _CommandReturn_co]):
|
|
|
2907
2904
|
def __call__(self, *args: _CommandParams.args, **kwargs: _CommandParams.kwargs) -> _CommandReturn_co: ...
|
|
2908
2905
|
|
|
2909
2906
|
|
|
2910
|
-
class _AnnotatedCommand(Protocol[
|
|
2907
|
+
class _AnnotatedCommand(Protocol[CmdOrSetT_contra, _CommandParams, _CommandReturn_co]):
|
|
2911
2908
|
"""A callable command method with the metadata used by ``with_annotated``."""
|
|
2912
2909
|
|
|
2913
2910
|
__name__: str
|
|
2914
2911
|
__qualname__: str
|
|
2915
2912
|
|
|
2916
2913
|
def __call__(
|
|
2917
|
-
self, __self:
|
|
2914
|
+
self, __self: CmdOrSetT_contra, /, *args: _CommandParams.args, **kwargs: _CommandParams.kwargs
|
|
2918
2915
|
) -> _CommandReturn_co: ...
|
|
2919
2916
|
|
|
2920
2917
|
@overload
|
|
2921
2918
|
def __get__(
|
|
2922
2919
|
self, instance: None, owner: Any = ...
|
|
2923
|
-
) -> "_AnnotatedCommand[
|
|
2920
|
+
) -> "_AnnotatedCommand[CmdOrSetT_contra, _CommandParams, _CommandReturn_co]": ...
|
|
2924
2921
|
|
|
2925
2922
|
@overload
|
|
2926
|
-
def __get__(
|
|
2923
|
+
def __get__(
|
|
2924
|
+
self, instance: CmdOrSetT_contra, owner: Any = ...
|
|
2925
|
+
) -> _BoundAnnotatedCommand[_CommandParams, _CommandReturn_co]: ...
|
|
2927
2926
|
|
|
2928
2927
|
|
|
2929
2928
|
class _WithAnnotatedDecorator(Protocol):
|
|
@@ -52,7 +52,7 @@ ARG_TOKENS = "arg_tokens"
|
|
|
52
52
|
def _build_hint(parser: Cmd2ArgumentParser, arg_action: argparse.Action) -> str:
|
|
53
53
|
"""Build completion hint for a given argument."""
|
|
54
54
|
# Check if hinting is disabled for this argument
|
|
55
|
-
suppress_hint = arg_action.get_suppress_tab_hint() # type: ignore[attr-defined
|
|
55
|
+
suppress_hint = arg_action.get_suppress_tab_hint() # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
56
56
|
if suppress_hint or arg_action.help == argparse.SUPPRESS:
|
|
57
57
|
return ""
|
|
58
58
|
|
|
@@ -104,7 +104,7 @@ class _ArgumentState:
|
|
|
104
104
|
self.is_remainder = self.action.nargs == argparse.REMAINDER
|
|
105
105
|
|
|
106
106
|
# Check if nargs is a range
|
|
107
|
-
nargs_range: tuple[int, int | float] | None = self.action.get_nargs_range() # type: ignore[attr-defined
|
|
107
|
+
nargs_range: tuple[int, int | float] | None = self.action.get_nargs_range() # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
108
108
|
if nargs_range is not None:
|
|
109
109
|
self.min = nargs_range[0]
|
|
110
110
|
self.max = nargs_range[1]
|
|
@@ -575,7 +575,7 @@ class ArgparseCompleter:
|
|
|
575
575
|
|
|
576
576
|
:raises ValueError: if there is an error with the data.
|
|
577
577
|
"""
|
|
578
|
-
table_columns = arg_state.action.get_table_columns() # type: ignore[attr-defined
|
|
578
|
+
table_columns = arg_state.action.get_table_columns() # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
579
579
|
has_table_data = any(item.table_data for item in completions)
|
|
580
580
|
|
|
581
581
|
if table_columns is None:
|
|
@@ -606,7 +606,7 @@ class ArgparseCompleter:
|
|
|
606
606
|
|
|
607
607
|
table_columns = cast(
|
|
608
608
|
Sequence[str | Column] | None,
|
|
609
|
-
arg_state.action.get_table_columns(), # type: ignore[attr-defined
|
|
609
|
+
arg_state.action.get_table_columns(), # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
610
610
|
)
|
|
611
611
|
|
|
612
612
|
# Skip table generation if results are outside thresholds or no columns are defined
|
|
@@ -761,7 +761,7 @@ class ArgparseCompleter:
|
|
|
761
761
|
:raises CompletionError: if the completer or choices function this calls raises one
|
|
762
762
|
"""
|
|
763
763
|
# Check if the argument uses a completer
|
|
764
|
-
completer = arg_state.action.get_completer() # type: ignore[attr-defined
|
|
764
|
+
completer = arg_state.action.get_completer() # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
765
765
|
if completer is not None:
|
|
766
766
|
args, kwargs = self._prepare_callable_params(
|
|
767
767
|
completer,
|
|
@@ -775,7 +775,7 @@ class ArgparseCompleter:
|
|
|
775
775
|
|
|
776
776
|
# Otherwise it uses a choices provider or choices list
|
|
777
777
|
else:
|
|
778
|
-
choices_provider = arg_state.action.get_choices_provider() # type: ignore[attr-defined
|
|
778
|
+
choices_provider = arg_state.action.get_choices_provider() # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
779
779
|
if choices_provider is not None:
|
|
780
780
|
args, kwargs = self._prepare_callable_params(
|
|
781
781
|
choices_provider,
|
|
@@ -232,8 +232,8 @@ import threading
|
|
|
232
232
|
from argparse import ArgumentError
|
|
233
233
|
from collections.abc import (
|
|
234
234
|
Callable,
|
|
235
|
+
Generator,
|
|
235
236
|
Iterable,
|
|
236
|
-
Iterator,
|
|
237
237
|
Sequence,
|
|
238
238
|
)
|
|
239
239
|
from dataclasses import dataclass
|
|
@@ -564,11 +564,11 @@ def _ActionsContainer_add_argument( # noqa: N802
|
|
|
564
564
|
new_arg = orig_actions_container_add_argument(self, *args, **kwargs)
|
|
565
565
|
|
|
566
566
|
# Set the cmd2-specific attributes
|
|
567
|
-
new_arg.set_nargs_range(nargs_range) # type: ignore[attr-defined
|
|
568
|
-
new_arg.set_choices_provider(choices_provider) # type: ignore[attr-defined
|
|
569
|
-
new_arg.set_completer(completer) # type: ignore[attr-defined
|
|
570
|
-
new_arg.set_suppress_tab_hint(suppress_tab_hint) # type: ignore[attr-defined
|
|
571
|
-
new_arg.set_table_columns(table_columns) # type: ignore[attr-defined
|
|
567
|
+
new_arg.set_nargs_range(nargs_range) # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
568
|
+
new_arg.set_choices_provider(choices_provider) # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
569
|
+
new_arg.set_completer(completer) # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
570
|
+
new_arg.set_suppress_tab_hint(suppress_tab_hint) # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
571
|
+
new_arg.set_table_columns(table_columns) # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
572
572
|
|
|
573
573
|
# Set other registered custom attributes
|
|
574
574
|
for keyword, value in custom_attribs.items():
|
|
@@ -666,14 +666,14 @@ def _SubParsersAction_remove_all_parsers( # noqa: N802
|
|
|
666
666
|
# Get the next subcommand name. remove_parser() will remove
|
|
667
667
|
# it and any associated aliases from _name_parser_map.
|
|
668
668
|
name = next(iter(self._name_parser_map))
|
|
669
|
-
record = self.remove_parser(name) # type: ignore[attr-defined
|
|
669
|
+
record = self.remove_parser(name) # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
670
670
|
records.append(record)
|
|
671
671
|
|
|
672
672
|
return records
|
|
673
673
|
|
|
674
674
|
|
|
675
|
-
argparse._SubParsersAction.remove_parser = _SubParsersAction_remove_parser # type: ignore[attr-defined
|
|
676
|
-
argparse._SubParsersAction.remove_all_parsers = _SubParsersAction_remove_all_parsers # type: ignore[attr-defined
|
|
675
|
+
argparse._SubParsersAction.remove_parser = _SubParsersAction_remove_parser # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
676
|
+
argparse._SubParsersAction.remove_all_parsers = _SubParsersAction_remove_all_parsers # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
677
677
|
|
|
678
678
|
|
|
679
679
|
@dataclass
|
|
@@ -695,7 +695,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
|
695
695
|
_thread_locals: ClassVar[_ParserThreadLocals] = _ParserThreadLocals()
|
|
696
696
|
|
|
697
697
|
@contextlib.contextmanager
|
|
698
|
-
def output_to(self, file: IO[str] | None) ->
|
|
698
|
+
def output_to(self, file: IO[str] | None) -> Generator[None]:
|
|
699
699
|
"""Context manager to temporarily set the output stream during argparse operations.
|
|
700
700
|
|
|
701
701
|
This is helpful for directing output for functions like `parse_args()`, which
|
|
@@ -747,8 +747,8 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
|
747
747
|
super().__init__(
|
|
748
748
|
prog=prog,
|
|
749
749
|
usage=usage,
|
|
750
|
-
description=description, # type: ignore[arg-type
|
|
751
|
-
epilog=epilog, # type: ignore[arg-type
|
|
750
|
+
description=description, # type: ignore[arg-type] # ty: ignore[invalid-argument-type]
|
|
751
|
+
epilog=epilog, # type: ignore[arg-type] # ty: ignore[invalid-argument-type]
|
|
752
752
|
parents=parents,
|
|
753
753
|
formatter_class=formatter_class,
|
|
754
754
|
prefix_chars=prefix_chars,
|
|
@@ -772,7 +772,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
|
772
772
|
self.description: HelpContent | None # type: ignore[assignment]
|
|
773
773
|
self.epilog: HelpContent | None # type: ignore[assignment]
|
|
774
774
|
|
|
775
|
-
def print_usage(self, file: IO[str] | None = None) -> None: # type: ignore[override
|
|
775
|
+
def print_usage(self, file: IO[str] | None = None) -> None: # type: ignore[override] # ty: ignore[invalid-method-override]
|
|
776
776
|
"""Override to ensure the formatter is aware of the target file."""
|
|
777
777
|
if file is None:
|
|
778
778
|
file = self._thread_locals.current_output_file
|
|
@@ -780,7 +780,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
|
780
780
|
with self.output_to(file):
|
|
781
781
|
super().print_usage(file)
|
|
782
782
|
|
|
783
|
-
def print_help(self, file: IO[str] | None = None) -> None: # type: ignore[override
|
|
783
|
+
def print_help(self, file: IO[str] | None = None) -> None: # type: ignore[override] # ty: ignore[invalid-method-override]
|
|
784
784
|
"""Override to ensure the formatter is aware of the target file."""
|
|
785
785
|
if file is None:
|
|
786
786
|
file = self._thread_locals.current_output_file
|
|
@@ -984,7 +984,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
|
984
984
|
try:
|
|
985
985
|
record = cast(
|
|
986
986
|
SubcommandRecord,
|
|
987
|
-
subparsers_action.remove_parser(subcommand), # type: ignore[attr-defined
|
|
987
|
+
subparsers_action.remove_parser(subcommand), # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
988
988
|
)
|
|
989
989
|
except ValueError:
|
|
990
990
|
raise ValueError(f"Subcommand '{subcommand}' does not exist for '{target_parser.prog}'") from None
|
|
@@ -1006,7 +1006,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
|
1006
1006
|
|
|
1007
1007
|
records = cast(
|
|
1008
1008
|
list[SubcommandRecord],
|
|
1009
|
-
subparsers_action.remove_all_parsers(), # type: ignore[attr-defined
|
|
1009
|
+
subparsers_action.remove_all_parsers(), # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
1010
1010
|
)
|
|
1011
1011
|
# Update command for each detached subcommand
|
|
1012
1012
|
for record in records:
|
|
@@ -1046,7 +1046,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
|
1046
1046
|
|
|
1047
1047
|
def _get_nargs_pattern(self, action: argparse.Action) -> str:
|
|
1048
1048
|
"""Override to support nargs ranges."""
|
|
1049
|
-
nargs_range = action.get_nargs_range() # type: ignore[attr-defined
|
|
1049
|
+
nargs_range = action.get_nargs_range() # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
1050
1050
|
if nargs_range:
|
|
1051
1051
|
range_max = "" if nargs_range[1] == constants.INFINITY else nargs_range[1]
|
|
1052
1052
|
nargs_pattern = f"(-*A{{{nargs_range[0]},{range_max}}}-*)"
|
|
@@ -1066,7 +1066,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
|
1066
1066
|
|
|
1067
1067
|
# raise an exception if we weren't able to find a match
|
|
1068
1068
|
if match is None:
|
|
1069
|
-
nargs_range = action.get_nargs_range() # type: ignore[attr-defined
|
|
1069
|
+
nargs_range = action.get_nargs_range() # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
|
|
1070
1070
|
if nargs_range is not None:
|
|
1071
1071
|
raise ArgumentError(action, build_range_error(nargs_range[0], nargs_range[1]))
|
|
1072
1072
|
|