cmd2 4.2.0__tar.gz → 4.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.
Files changed (223) hide show
  1. {cmd2-4.2.0 → cmd2-4.2.2}/.pre-commit-config.yaml +2 -2
  2. {cmd2-4.2.0 → cmd2-4.2.2}/CHANGELOG.md +15 -1
  3. {cmd2-4.2.0 → cmd2-4.2.2}/Makefile +9 -9
  4. {cmd2-4.2.0 → cmd2-4.2.2}/PKG-INFO +1 -1
  5. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/annotated.py +7 -4
  6. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/argparse_utils.py +7 -6
  7. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/cmd2.py +67 -38
  8. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/decorators.py +3 -3
  9. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/parsing.py +4 -4
  10. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/pt_utils.py +1 -1
  11. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/rich_utils.py +1 -1
  12. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2.egg-info/PKG-INFO +1 -1
  13. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2.egg-info/SOURCES.txt +2 -0
  14. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2.egg-info/scm_file_list.json +129 -128
  15. cmd2-4.2.2/cmd2.egg-info/scm_version.json +8 -0
  16. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/argument_processing.md +8 -8
  17. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/os.md +21 -33
  18. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/startup_commands.md +19 -6
  19. {cmd2-4.2.0 → cmd2-4.2.2}/docs/upgrades.md +9 -9
  20. {cmd2-4.2.0 → cmd2-4.2.2}/examples/README.md +4 -2
  21. cmd2-4.2.2/examples/cmd2_history.dat +0 -0
  22. {cmd2-4.2.0 → cmd2-4.2.2}/examples/cmd_as_argument.py +13 -31
  23. {cmd2-4.2.0 → cmd2-4.2.2}/pyproject.toml +2 -28
  24. {cmd2-4.2.0 → cmd2-4.2.2}/ruff.toml +2 -1
  25. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_annotated.py +43 -0
  26. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_cmd2.py +91 -1
  27. cmd2-4.2.2/ty.toml +8 -0
  28. cmd2-4.2.0/cmd2.egg-info/scm_version.json +0 -8
  29. {cmd2-4.2.0 → cmd2-4.2.2}/.prettierignore +0 -0
  30. {cmd2-4.2.0 → cmd2-4.2.2}/.prettierrc +0 -0
  31. {cmd2-4.2.0 → cmd2-4.2.2}/.typos.toml +0 -0
  32. {cmd2-4.2.0 → cmd2-4.2.2}/GEMINI.md +0 -0
  33. {cmd2-4.2.0 → cmd2-4.2.2}/LICENSE +0 -0
  34. {cmd2-4.2.0 → cmd2-4.2.2}/MANIFEST.in +0 -0
  35. {cmd2-4.2.0 → cmd2-4.2.2}/README.md +0 -0
  36. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/__init__.py +0 -0
  37. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/argparse_completer.py +0 -0
  38. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/clipboard.py +0 -0
  39. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/colors.py +0 -0
  40. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/command_set.py +0 -0
  41. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/completion.py +0 -0
  42. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/constants.py +0 -0
  43. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/exceptions.py +0 -0
  44. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/history.py +0 -0
  45. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/plugin.py +0 -0
  46. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/py.typed +0 -0
  47. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/py_bridge.py +0 -0
  48. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/string_utils.py +0 -0
  49. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/styles.py +0 -0
  50. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/theme.py +0 -0
  51. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/types.py +0 -0
  52. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2/utils.py +0 -0
  53. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2.egg-info/dependency_links.txt +0 -0
  54. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2.egg-info/requires.txt +0 -0
  55. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2.egg-info/top_level.txt +0 -0
  56. {cmd2-4.2.0 → cmd2-4.2.2}/cmd2.png +0 -0
  57. {cmd2-4.2.0 → cmd2-4.2.2}/codecov.yml +0 -0
  58. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/annotated.md +0 -0
  59. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/argparse_completer.md +0 -0
  60. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/argparse_utils.md +0 -0
  61. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/clipboard.md +0 -0
  62. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/cmd.md +0 -0
  63. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/colors.md +0 -0
  64. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/command_set.md +0 -0
  65. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/completion.md +0 -0
  66. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/constants.md +0 -0
  67. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/decorators.md +0 -0
  68. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/exceptions.md +0 -0
  69. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/history.md +0 -0
  70. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/index.md +0 -0
  71. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/parsing.md +0 -0
  72. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/plugin.md +0 -0
  73. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/pt_utils.md +0 -0
  74. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/py_bridge.md +0 -0
  75. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/rich_utils.md +0 -0
  76. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/string_utils.md +0 -0
  77. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/styles.md +0 -0
  78. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/theme.md +0 -0
  79. {cmd2-4.2.0 → cmd2-4.2.2}/docs/api/utils.md +0 -0
  80. {cmd2-4.2.0 → cmd2-4.2.2}/docs/doc_conventions.md +0 -0
  81. {cmd2-4.2.0 → cmd2-4.2.2}/docs/examples/alternate_event_loops.md +0 -0
  82. {cmd2-4.2.0 → cmd2-4.2.2}/docs/examples/examples.md +0 -0
  83. {cmd2-4.2.0 → cmd2-4.2.2}/docs/examples/getting_started.md +0 -0
  84. {cmd2-4.2.0 → cmd2-4.2.2}/docs/examples/index.md +0 -0
  85. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/annotated.md +0 -0
  86. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/async_commands.md +0 -0
  87. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/builtin_commands.md +0 -0
  88. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/clipboard.md +0 -0
  89. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/commands.md +0 -0
  90. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/completion.md +0 -0
  91. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/disable_commands.md +0 -0
  92. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/embedded_python_shells.md +0 -0
  93. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/generating_output.md +0 -0
  94. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/help.md +0 -0
  95. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/history.md +0 -0
  96. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/hooks.md +0 -0
  97. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/index.md +0 -0
  98. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/initialization.md +0 -0
  99. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/misc.md +0 -0
  100. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/modular_commands.md +0 -0
  101. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/multiline_commands.md +0 -0
  102. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/packaging.md +0 -0
  103. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/plugins.md +0 -0
  104. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/prompt.md +0 -0
  105. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/redirection.md +0 -0
  106. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/scripting.md +0 -0
  107. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/settings.md +0 -0
  108. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/shortcuts_aliases_macros.md +0 -0
  109. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/table_creation.md +0 -0
  110. {cmd2-4.2.0 → cmd2-4.2.2}/docs/features/theme.md +0 -0
  111. {cmd2-4.2.0 → cmd2-4.2.2}/docs/index.md +0 -0
  112. {cmd2-4.2.0 → cmd2-4.2.2}/docs/javascripts/readthedocs.js +0 -0
  113. {cmd2-4.2.0 → cmd2-4.2.2}/docs/migrating/incompatibilities.md +0 -0
  114. {cmd2-4.2.0 → cmd2-4.2.2}/docs/migrating/index.md +0 -0
  115. {cmd2-4.2.0 → cmd2-4.2.2}/docs/migrating/minimum.md +0 -0
  116. {cmd2-4.2.0 → cmd2-4.2.2}/docs/migrating/next_steps.md +0 -0
  117. {cmd2-4.2.0 → cmd2-4.2.2}/docs/migrating/why.md +0 -0
  118. {cmd2-4.2.0 → cmd2-4.2.2}/docs/mixins/index.md +0 -0
  119. {cmd2-4.2.0 → cmd2-4.2.2}/docs/mixins/mixin_template.md +0 -0
  120. {cmd2-4.2.0 → cmd2-4.2.2}/docs/overrides/main.html +0 -0
  121. {cmd2-4.2.0 → cmd2-4.2.2}/docs/overview/alternatives.md +0 -0
  122. {cmd2-4.2.0 → cmd2-4.2.2}/docs/overview/index.md +0 -0
  123. {cmd2-4.2.0 → cmd2-4.2.2}/docs/overview/installation.md +0 -0
  124. {cmd2-4.2.0 → cmd2-4.2.2}/docs/overview/integrating.md +0 -0
  125. {cmd2-4.2.0 → cmd2-4.2.2}/docs/overview/resources.md +0 -0
  126. {cmd2-4.2.0 → cmd2-4.2.2}/docs/stylesheets/cmd2.css +0 -0
  127. {cmd2-4.2.0 → cmd2-4.2.2}/docs/testing.md +0 -0
  128. {cmd2-4.2.0 → cmd2-4.2.2}/examples/.cmd2rc +0 -0
  129. {cmd2-4.2.0 → cmd2-4.2.2}/examples/annotated_example.py +0 -0
  130. {cmd2-4.2.0 → cmd2-4.2.2}/examples/argparse_completion.py +0 -0
  131. {cmd2-4.2.0 → cmd2-4.2.2}/examples/argparse_example.py +0 -0
  132. {cmd2-4.2.0 → cmd2-4.2.2}/examples/async_call.py +0 -0
  133. {cmd2-4.2.0 → cmd2-4.2.2}/examples/async_commands.py +0 -0
  134. {cmd2-4.2.0 → cmd2-4.2.2}/examples/async_printing.py +0 -0
  135. {cmd2-4.2.0 → cmd2-4.2.2}/examples/basic_completion.py +0 -0
  136. {cmd2-4.2.0 → cmd2-4.2.2}/examples/color.py +0 -0
  137. {cmd2-4.2.0 → cmd2-4.2.2}/examples/command_sets.py +0 -0
  138. {cmd2-4.2.0 → cmd2-4.2.2}/examples/completion_item_choices.py +0 -0
  139. {cmd2-4.2.0 → cmd2-4.2.2}/examples/custom_parser.py +0 -0
  140. {cmd2-4.2.0 → cmd2-4.2.2}/examples/custom_types.py +0 -0
  141. {cmd2-4.2.0 → cmd2-4.2.2}/examples/default_categories.py +0 -0
  142. {cmd2-4.2.0 → cmd2-4.2.2}/examples/dynamic_commands.py +0 -0
  143. {cmd2-4.2.0 → cmd2-4.2.2}/examples/environment.py +0 -0
  144. {cmd2-4.2.0 → cmd2-4.2.2}/examples/event_loops.py +0 -0
  145. {cmd2-4.2.0 → cmd2-4.2.2}/examples/exit_code.py +0 -0
  146. {cmd2-4.2.0 → cmd2-4.2.2}/examples/getting_started.py +0 -0
  147. {cmd2-4.2.0 → cmd2-4.2.2}/examples/hello_cmd2.py +0 -0
  148. {cmd2-4.2.0 → cmd2-4.2.2}/examples/help_categories.py +0 -0
  149. {cmd2-4.2.0 → cmd2-4.2.2}/examples/hooks.py +0 -0
  150. {cmd2-4.2.0 → cmd2-4.2.2}/examples/migrating.py +0 -0
  151. {cmd2-4.2.0 → cmd2-4.2.2}/examples/mixin.py +0 -0
  152. {cmd2-4.2.0 → cmd2-4.2.2}/examples/modular_commands/__init__.py +0 -0
  153. {cmd2-4.2.0 → cmd2-4.2.2}/examples/modular_commands/commandset_basic.py +0 -0
  154. {cmd2-4.2.0 → cmd2-4.2.2}/examples/modular_commands/commandset_complex.py +0 -0
  155. {cmd2-4.2.0 → cmd2-4.2.2}/examples/modular_commands/commandset_custominit.py +0 -0
  156. {cmd2-4.2.0 → cmd2-4.2.2}/examples/modular_commandsets.py +0 -0
  157. {cmd2-4.2.0 → cmd2-4.2.2}/examples/paged_output.py +0 -0
  158. {cmd2-4.2.0 → cmd2-4.2.2}/examples/persistent_history.py +0 -0
  159. {cmd2-4.2.0 → cmd2-4.2.2}/examples/pretty_print.py +0 -0
  160. {cmd2-4.2.0 → cmd2-4.2.2}/examples/python_scripting.py +0 -0
  161. {cmd2-4.2.0 → cmd2-4.2.2}/examples/read_input.py +0 -0
  162. {cmd2-4.2.0 → cmd2-4.2.2}/examples/remove_builtin_commands.py +0 -0
  163. {cmd2-4.2.0 → cmd2-4.2.2}/examples/remove_settable.py +0 -0
  164. {cmd2-4.2.0 → cmd2-4.2.2}/examples/rich_tables.py +0 -0
  165. {cmd2-4.2.0 → cmd2-4.2.2}/examples/rich_theme.py +0 -0
  166. {cmd2-4.2.0 → cmd2-4.2.2}/examples/scripts/arg_printer.py +0 -0
  167. {cmd2-4.2.0 → cmd2-4.2.2}/examples/scripts/conditional.py +0 -0
  168. {cmd2-4.2.0 → cmd2-4.2.2}/examples/scripts/nested.txt +0 -0
  169. {cmd2-4.2.0 → cmd2-4.2.2}/examples/scripts/quit.txt +0 -0
  170. {cmd2-4.2.0 → cmd2-4.2.2}/examples/scripts/save_help_text.py +0 -0
  171. {cmd2-4.2.0 → cmd2-4.2.2}/examples/scripts/script.py +0 -0
  172. {cmd2-4.2.0 → cmd2-4.2.2}/examples/scripts/script.txt +0 -0
  173. {cmd2-4.2.0 → cmd2-4.2.2}/examples/tmux_launch.sh +0 -0
  174. {cmd2-4.2.0 → cmd2-4.2.2}/examples/tmux_split.sh +0 -0
  175. {cmd2-4.2.0 → cmd2-4.2.2}/examples/unicode_commands.py +0 -0
  176. {cmd2-4.2.0 → cmd2-4.2.2}/mkdocs.yml +0 -0
  177. {cmd2-4.2.0 → cmd2-4.2.2}/package.json +0 -0
  178. {cmd2-4.2.0 → cmd2-4.2.2}/scripts/validate_tag.py +0 -0
  179. {cmd2-4.2.0 → cmd2-4.2.2}/setup.cfg +0 -0
  180. {cmd2-4.2.0 → cmd2-4.2.2}/tests/.cmd2rc +0 -0
  181. {cmd2-4.2.0 → cmd2-4.2.2}/tests/__init__.py +0 -0
  182. {cmd2-4.2.0 → cmd2-4.2.2}/tests/conftest.py +0 -0
  183. {cmd2-4.2.0 → cmd2-4.2.2}/tests/pyscript/echo.py +0 -0
  184. {cmd2-4.2.0 → cmd2-4.2.2}/tests/pyscript/environment.py +0 -0
  185. {cmd2-4.2.0 → cmd2-4.2.2}/tests/pyscript/help.py +0 -0
  186. {cmd2-4.2.0 → cmd2-4.2.2}/tests/pyscript/py_locals.py +0 -0
  187. {cmd2-4.2.0 → cmd2-4.2.2}/tests/pyscript/pyscript_dir.py +0 -0
  188. {cmd2-4.2.0 → cmd2-4.2.2}/tests/pyscript/raises_exception.py +0 -0
  189. {cmd2-4.2.0 → cmd2-4.2.2}/tests/pyscript/recursive.py +0 -0
  190. {cmd2-4.2.0 → cmd2-4.2.2}/tests/pyscript/self_in_py.py +0 -0
  191. {cmd2-4.2.0 → cmd2-4.2.2}/tests/pyscript/stop.py +0 -0
  192. {cmd2-4.2.0 → cmd2-4.2.2}/tests/pyscript/test_print.py +0 -0
  193. {cmd2-4.2.0 → cmd2-4.2.2}/tests/relative_multiple.txt +0 -0
  194. {cmd2-4.2.0 → cmd2-4.2.2}/tests/script.py +0 -0
  195. {cmd2-4.2.0 → cmd2-4.2.2}/tests/script.txt +0 -0
  196. {cmd2-4.2.0 → cmd2-4.2.2}/tests/scripts/binary.bin +0 -0
  197. {cmd2-4.2.0 → cmd2-4.2.2}/tests/scripts/empty.txt +0 -0
  198. {cmd2-4.2.0 → cmd2-4.2.2}/tests/scripts/help.txt +0 -0
  199. {cmd2-4.2.0 → cmd2-4.2.2}/tests/scripts/nested.txt +0 -0
  200. {cmd2-4.2.0 → cmd2-4.2.2}/tests/scripts/one_down.txt +0 -0
  201. {cmd2-4.2.0 → cmd2-4.2.2}/tests/scripts/postcmds.txt +0 -0
  202. {cmd2-4.2.0 → cmd2-4.2.2}/tests/scripts/precmds.txt +0 -0
  203. {cmd2-4.2.0 → cmd2-4.2.2}/tests/scripts/utf8.txt +0 -0
  204. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_argparse.py +0 -0
  205. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_argparse_completer.py +0 -0
  206. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_argparse_subcommands.py +0 -0
  207. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_argparse_utils.py +0 -0
  208. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_categories.py +0 -0
  209. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_commandset.py +0 -0
  210. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_completion.py +0 -0
  211. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_dynamic_complete_style.py +0 -0
  212. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_future_annotations.py +0 -0
  213. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_history.py +0 -0
  214. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_parsing.py +0 -0
  215. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_plugin.py +0 -0
  216. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_pt_utils.py +0 -0
  217. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_py_completion.py +0 -0
  218. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_rich_utils.py +0 -0
  219. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_run_pyscript.py +0 -0
  220. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_string_utils.py +0 -0
  221. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_theme.py +0 -0
  222. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_utils.py +0 -0
  223. {cmd2-4.2.0 → cmd2-4.2.2}/tests/test_utils_defining_class.py +0 -0
@@ -14,7 +14,7 @@ repos:
14
14
  - id: trailing-whitespace
15
15
 
16
16
  - repo: https://github.com/astral-sh/ruff-pre-commit
17
- rev: "v0.16.1"
17
+ rev: "v0.16.3"
18
18
  hooks:
19
19
  - id: ruff-format
20
20
  args: [--config=ruff.toml]
@@ -30,7 +30,7 @@ repos:
30
30
  - prettier-plugin-toml@2.0.6
31
31
 
32
32
  - repo: https://github.com/crate-ci/typos
33
- rev: v1.48.0
33
+ rev: v1.49.0
34
34
  hooks:
35
35
  - id: typos
36
36
  exclude: |
@@ -1,3 +1,17 @@
1
+ ## 4.2.2 (August 25, 2026)
2
+
3
+ - Documentation Improvements
4
+ - Improved documentation in attempt at making some recommended best-practices more discoverable
5
+ - Fixed the broken `cmd_as_argument` example
6
+
7
+ ## 4.2.1 (August 22, 2026)
8
+
9
+ - Enhancements
10
+ - Added bracketed paste support so multiple pasted commands execute sequentially and multiline
11
+ commands continue as expected.
12
+ - Bug Fixes
13
+ - Enabled Ctrl-Z suspension at the prompt
14
+
1
15
  ## 4.2.0 (August 6, 2026)
2
16
 
3
17
  - Enhancements
@@ -1886,7 +1900,7 @@ time reading the [rich documentation](https://rich.readthedocs.io/).
1886
1900
  - **with_argument_list** decorator to change argument type from str to List[str]
1887
1901
  - **do\_\*** commands get a single argument which is a list of strings, as pre-parsed by
1888
1902
  shlex.split()
1889
- - **with_arparser** decorator for strict argparse-based argument parsing of command
1903
+ - **with_argparser** decorator for strict argparse-based argument parsing of command
1890
1904
  arguments
1891
1905
  - **do\_\*** commands get a single argument which is the output of argparse.parse_args()
1892
1906
  - **with_argparser_and_unknown_args** decorator for argparse-based argument parsing, but
@@ -18,8 +18,8 @@ check: ## Run code quality tools.
18
18
  @uv lock --locked
19
19
  @echo "🚀 Auto-formatting/Linting code and documentation: Running prek"
20
20
  @uv run prek run -a
21
- @echo "🚀 Static type checking: Running mypy"
22
- @uv run mypy
21
+ @echo "🚀 Static type checking: Running ty"
22
+ @uv run ty check
23
23
 
24
24
  .PHONY: format
25
25
  format: ## Perform ruff formatting
@@ -31,7 +31,7 @@ lint: ## Perform ruff linting
31
31
 
32
32
  .PHONY: typecheck
33
33
  typecheck: ## Perform type checking
34
- @uv run mypy
34
+ @uv run ty check
35
35
 
36
36
  .PHONY: test
37
37
  test: ## Test the code with pytest.
@@ -76,7 +76,7 @@ publish: validate-tag build ## Publish a release to PyPI, uses token from ~/.pyp
76
76
  # Define variables for files/directories to clean
77
77
  BUILD_DIRS = build dist *.egg-info
78
78
  DOC_DIRS = build
79
- MYPY_DIRS = .mypy_cache dmypy.json dmypy.sock
79
+ TY_DIRS = .ty_cache .red_knot_cache
80
80
  TEST_DIRS = .cache .pytest_cache htmlcov
81
81
  TEST_FILES = .coverage coverage.xml
82
82
 
@@ -90,10 +90,10 @@ clean-docs: ## Clean documentation artifacts
90
90
  @echo "🚀 Removing documentation artifacts"
91
91
  @uv run python -c "import shutil; import os; [shutil.rmtree(d, ignore_errors=True) for d in '$(DOC_DIRS)'.split() if os.path.isdir(d)]"
92
92
 
93
- .PHONY: clean-mypy
94
- clean-mypy: ## Clean mypy artifacts
95
- @echo "🚀 Removing mypy artifacts"
96
- @uv run python -c "import shutil; import os; [shutil.rmtree(d, ignore_errors=True) for d in '$(MYPY_DIRS)'.split() if os.path.isdir(d)]"
93
+ .PHONY: clean-ty
94
+ clean-ty: ## Clean ty artifacts
95
+ @echo "🚀 Removing ty artifacts"
96
+ @uv run python -c "import shutil; import os; [shutil.rmtree(d, ignore_errors=True) for d in '$(TY_DIRS)'.split() if os.path.isdir(d)]"
97
97
 
98
98
  .PHONY: clean-pycache
99
99
  clean-pycache: ## Clean pycache artifacts
@@ -112,7 +112,7 @@ clean-test: ## Clean test artifacts
112
112
  @uv run python -c "from pathlib import Path; [Path(f).unlink(missing_ok=True) for f in '$(TEST_FILES)'.split()]"
113
113
 
114
114
  .PHONY: clean
115
- clean: clean-build clean-docs clean-mypy clean-pycache clean-ruff clean-test ## Clean all artifacts
115
+ clean: clean-build clean-docs clean-ty clean-pycache clean-ruff clean-test ## Clean all artifacts
116
116
  @echo "🚀 Cleaned all artifacts"
117
117
 
118
118
  .PHONY: help
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cmd2
3
- Version: 4.2.0
3
+ Version: 4.2.2
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
@@ -708,10 +708,10 @@ class _CollectionCastingAction(argparse._StoreAction):
708
708
 
709
709
  def __call__(
710
710
  self,
711
- _parser: argparse.ArgumentParser,
711
+ parser: argparse.ArgumentParser, # noqa: ARG002
712
712
  namespace: argparse.Namespace,
713
713
  values: Any,
714
- _option_string: str | None = None,
714
+ option_string: str | None = None, # noqa: ARG002
715
715
  ) -> None:
716
716
  result = values
717
717
  if self._container_factory is not None and isinstance(values, list):
@@ -879,7 +879,7 @@ def _resolve_union(
879
879
  raise TypeError(f"Union type {type_names} is ambiguous for auto-resolution.")
880
880
 
881
881
  parts = [_resolve_base_type(member, allow_unknown_entry=allow_unknown_entry) for member in non_none]
882
- # Every part is an Enum (guarded above), so each has a converter; the None-filter keeps mypy happy.
882
+ # Every part is an Enum (guarded above), so each has a converter; the None-filter keeps the type checker happy.
883
883
  converters = [part.converter for part in parts if part.converter is not None]
884
884
  choices = _dedupe_choices(choice for part in parts for choice in (part.choices or []))
885
885
 
@@ -2189,7 +2189,7 @@ def _find_argument_block(hint: Any) -> type[ArgumentBlock] | None:
2189
2189
  return None
2190
2190
 
2191
2191
 
2192
- def _init_field_names(dc_type: type) -> list[str]:
2192
+ def _init_field_names(dc_type: Any) -> list[str]:
2193
2193
  """Names of a dataclass's ``init`` fields in definition order (the flat argument names of a block)."""
2194
2194
  return [f.name for f in fields(dc_type) if f.init]
2195
2195
 
@@ -3113,6 +3113,9 @@ def with_annotated(
3113
3113
  except SystemExit as exc:
3114
3114
  raise Cmd2ArgparseError from exc
3115
3115
 
3116
+ if ns is None:
3117
+ raise ValueError("ns is None")
3118
+
3116
3119
  setattr(ns, constants.NS_ATTR_STATEMENT, statement)
3117
3120
  handler = getattr(ns, constants.NS_ATTR_SUBCOMMAND_FUNC, None)
3118
3121
  if base_command and handler is not None:
@@ -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:invalid-argument-type]
751
+ epilog=epilog, # type: ignore[arg-type, ty: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: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: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
@@ -831,7 +831,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
831
831
  temp_parser = Cmd2ArgumentParser(
832
832
  prog=self.prog,
833
833
  usage=None,
834
- formatter_class=self.formatter_class,
834
+ formatter_class=cast(type[Cmd2HelpFormatter], self.formatter_class),
835
835
  add_help=False,
836
836
  )
837
837
 
@@ -1037,7 +1037,8 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
1037
1037
 
1038
1038
  def _get_formatter(self, *_args: Any, **_kwargs: Any) -> Cmd2HelpFormatter:
1039
1039
  """Override with customizations for Cmd2HelpFormatter."""
1040
- return self.formatter_class(prog=self.prog, file=self._thread_locals.current_output_file)
1040
+ formatter_class = cast(type[Cmd2HelpFormatter], self.formatter_class)
1041
+ return formatter_class(prog=self.prog, file=self._thread_locals.current_output_file)
1041
1042
 
1042
1043
  def format_help(self, *args: Any, **kwargs: Any) -> str:
1043
1044
  """Override to add a newline."""
@@ -78,6 +78,8 @@ from prompt_toolkit.formatted_text import ANSI, AnyFormattedText
78
78
  from prompt_toolkit.history import InMemoryHistory
79
79
  from prompt_toolkit.input import DummyInput, create_input
80
80
  from prompt_toolkit.key_binding import KeyBindings
81
+ from prompt_toolkit.key_binding.key_processor import KeyPress, KeyPressEvent
82
+ from prompt_toolkit.keys import Keys
81
83
  from prompt_toolkit.output import DummyOutput, create_output
82
84
  from prompt_toolkit.patch_stdout import patch_stdout
83
85
  from prompt_toolkit.shortcuts import CompleteStyle, PromptSession, choice, set_title
@@ -740,6 +742,50 @@ class Cmd:
740
742
  # No macro found or already processed. The statement is complete.
741
743
  return False
742
744
 
745
+ def _create_key_bindings(self, completekey: str) -> KeyBindings:
746
+ """Create and configure custom key bindings for the PromptSession."""
747
+ key_bindings = KeyBindings()
748
+
749
+ if completekey != self.DEFAULT_COMPLETEKEY:
750
+
751
+ @key_bindings.add(completekey)
752
+ def _trigger_completion(event: KeyPressEvent) -> None: # pragma: no cover
753
+ """Trigger completion using the custom completion key."""
754
+ b = event.current_buffer
755
+ if b.complete_state:
756
+ b.complete_next()
757
+ else:
758
+ b.start_completion(select_first=False)
759
+
760
+ @key_bindings.add("enter", filter=filters.completion_is_selected)
761
+ def _accept_completion(event: KeyPressEvent) -> None: # pragma: no cover
762
+ """Accept a selected completion on Enter without submitting the command."""
763
+ event.current_buffer.complete_state = None
764
+
765
+ @key_bindings.add(Keys.BracketedPaste)
766
+ def _handle_bracketed_paste(event: KeyPressEvent) -> None:
767
+ """Handle bracketed paste by feeding lines as keystrokes separated by Enter.
768
+
769
+ By default, prompt_toolkit inserts pasted text as a single buffer blob.
770
+ Translating newlines into Enter keystrokes allows multiple pasted commands
771
+ to execute sequentially and multiline commands to continue as expected.
772
+ """
773
+ data = event.data.replace("\r\n", "\n").replace("\r", "\n")
774
+ if "\n" not in data:
775
+ event.current_buffer.insert_text(data)
776
+ return
777
+
778
+ key_presses = []
779
+ for i, line in enumerate(data.split("\n")):
780
+ if i > 0:
781
+ key_presses.append(KeyPress(Keys.ControlM, "\r"))
782
+ if line:
783
+ key_presses.append(KeyPress(Keys.Any, line))
784
+
785
+ event.key_processor.feed_multiple(key_presses)
786
+
787
+ return key_bindings
788
+
743
789
  def _create_main_session(
744
790
  self,
745
791
  *,
@@ -756,26 +802,6 @@ class Cmd:
756
802
  Otherwise, uses dummy drivers to support non-interactive streams like
757
803
  pipes or files.
758
804
  """
759
- # Configure custom key bindings
760
- key_bindings = KeyBindings()
761
-
762
- # Add a binding for 'enter' that triggers only when a completion is selected.
763
- # This allows accepting a completion without submitting the command.
764
- @key_bindings.add("enter", filter=filters.completion_is_selected)
765
- def _(event: Any) -> None: # pragma: no cover
766
- event.current_buffer.complete_state = None
767
-
768
- if completekey != self.DEFAULT_COMPLETEKEY:
769
- # Configure prompt_toolkit `KeyBindings` with the custom key for completion
770
- @key_bindings.add(completekey)
771
- def _(event: Any) -> None: # pragma: no cover
772
- """Trigger completion."""
773
- b = event.current_buffer
774
- if b.complete_state:
775
- b.complete_next()
776
- else:
777
- b.start_completion(select_first=False)
778
-
779
805
  # Base configuration
780
806
  kwargs: dict[str, Any] = {
781
807
  "auto_suggest": AutoSuggestFromHistory() if auto_suggest else None,
@@ -785,8 +811,9 @@ class Cmd:
785
811
  "complete_in_thread": complete_in_thread,
786
812
  "complete_while_typing": False,
787
813
  "completer": Cmd2Completer(self),
814
+ "enable_suspend": True,
788
815
  "history": Cmd2History(item.raw for item in self.history),
789
- "key_bindings": key_bindings,
816
+ "key_bindings": self._create_key_bindings(completekey),
790
817
  "lexer": Cmd2Lexer(self),
791
818
  "multiline": filters.Condition(self._should_continue_multiline),
792
819
  "prompt_continuation": self.continuation_prompt,
@@ -849,7 +876,7 @@ class Cmd:
849
876
  all_commandset_defs = CommandSet.__subclasses__()
850
877
  existing_commandset_types = [type(command_set) for command_set in self._installed_command_sets]
851
878
 
852
- def load_commandset_by_type(commandset_types: list[type[CommandSet[Any]]]) -> None:
879
+ def load_commandset_by_type(commandset_types: Sequence[type[CommandSet[Any]]]) -> None:
853
880
  for cmdset_type in commandset_types:
854
881
  # check if the type has sub-classes. We will only auto-load leaf class types.
855
882
  subclasses = cmdset_type.__subclasses__()
@@ -2547,11 +2574,11 @@ class Cmd:
2547
2574
  completer.complete, tokens=raw_tokens[1:] if spec.preserve_quotes else tokens[1:], cmd_set=cmd_set
2548
2575
  )
2549
2576
  else:
2550
- completer_func = self.completedefault # type: ignore[assignment]
2577
+ completer_func = self.completedefault # type: ignore[assignment, ty:invalid-assignment]
2551
2578
 
2552
2579
  # Not a recognized macro or command
2553
2580
  else:
2554
- completer_func = self.completedefault # type: ignore[assignment]
2581
+ completer_func = self.completedefault # type: ignore[assignment, ty:invalid-assignment]
2555
2582
 
2556
2583
  # Otherwise we are completing the command token or performing custom completion
2557
2584
  else:
@@ -2968,7 +2995,7 @@ class Cmd:
2968
2995
  with self.sigint_protection:
2969
2996
  if py_bridge_call:
2970
2997
  # Start saving command's stdout at this point
2971
- self.stdout.pause_storage = False # type: ignore[attr-defined]
2998
+ self.stdout.pause_storage = False # type: ignore[attr-defined, ty:invalid-assignment]
2972
2999
 
2973
3000
  redir_saved_state = self._redirect_output(statement)
2974
3001
 
@@ -3007,7 +3034,7 @@ class Cmd:
3007
3034
 
3008
3035
  if py_bridge_call:
3009
3036
  # Stop saving command's stdout before command finalization hooks run
3010
- self.stdout.pause_storage = True # type: ignore[attr-defined]
3037
+ self.stdout.pause_storage = True # type: ignore[attr-defined, ty:invalid-assignment]
3011
3038
  except (SkipPostcommandHooks, EmptyStatement):
3012
3039
  # Don't do anything, but do allow command finalization hooks to run
3013
3040
  pass
@@ -3512,7 +3539,7 @@ class Cmd:
3512
3539
  self.active_session = self.main_session
3513
3540
 
3514
3541
  # We're not at a terminal, so we're likely reading from a file or a pipe.
3515
- prompt_obj = prompt() if callable(prompt) else prompt
3542
+ prompt_obj = prompt if isinstance(prompt, (ANSI, str)) else prompt()
3516
3543
  prompt_str = prompt_obj.value if isinstance(prompt_obj, ANSI) else prompt_obj
3517
3544
 
3518
3545
  # If this is an interactive pipe, then display the prompt first
@@ -3613,6 +3640,7 @@ class Cmd:
3613
3640
  complete_in_thread=self.main_session.complete_in_thread,
3614
3641
  complete_while_typing=self.main_session.complete_while_typing,
3615
3642
  completer=completer_to_use,
3643
+ enable_suspend=self.main_session.enable_suspend,
3616
3644
  history=InMemoryHistory(history) if history is not None else InMemoryHistory(),
3617
3645
  key_bindings=self.main_session.key_bindings,
3618
3646
  input=self.main_session.input,
@@ -3635,6 +3663,7 @@ class Cmd:
3635
3663
  """
3636
3664
  temp_session: PromptSession[str] = PromptSession(
3637
3665
  color_depth=self.main_session.color_depth,
3666
+ enable_suspend=self.main_session.enable_suspend,
3638
3667
  input=self.main_session.input,
3639
3668
  output=self.main_session.output,
3640
3669
  style=self.main_session.style,
@@ -3800,7 +3829,7 @@ class Cmd:
3800
3829
  "An alias is a command that enables replacement of a word by another string.",
3801
3830
  )
3802
3831
  alias_parser = argparse_utils.DEFAULT_ARGUMENT_PARSER(description=alias_description)
3803
- alias_parser.epilog = TextGroup(
3832
+ alias_parser.epilog = TextGroup( # type: ignore[assignment, ty:invalid-assignment]
3804
3833
  "See Also",
3805
3834
  "macro",
3806
3835
  )
@@ -3832,7 +3861,7 @@ class Cmd:
3832
3861
  "for the actual command the alias resolves to."
3833
3862
  ),
3834
3863
  )
3835
- alias_create_parser.epilog = TextGroup("Notes", alias_create_notes)
3864
+ alias_create_parser.epilog = TextGroup("Notes", alias_create_notes) # type: ignore[assignment, ty:invalid-assignment]
3836
3865
 
3837
3866
  # Add arguments
3838
3867
  alias_create_parser.add_argument("name", help="name of this alias")
@@ -4014,7 +4043,7 @@ class Cmd:
4014
4043
  "A macro is similar to an alias, but it can contain argument placeholders.",
4015
4044
  )
4016
4045
  macro_parser = argparse_utils.DEFAULT_ARGUMENT_PARSER(description=macro_description)
4017
- macro_parser.epilog = TextGroup(
4046
+ macro_parser.epilog = TextGroup( # type: ignore[assignment, ty:invalid-assignment]
4018
4047
  "See Also",
4019
4048
  "alias",
4020
4049
  )
@@ -4077,7 +4106,7 @@ class Cmd:
4077
4106
  "This default behavior changes if custom completion for macro arguments has been implemented."
4078
4107
  ),
4079
4108
  )
4080
- macro_create_parser.epilog = TextGroup("Notes", macro_create_notes)
4109
+ macro_create_parser.epilog = TextGroup("Notes", macro_create_notes) # type: ignore[assignment, ty:invalid-assignment]
4081
4110
 
4082
4111
  # Add arguments
4083
4112
  macro_create_parser.add_argument("name", help="name of this macro")
@@ -4572,7 +4601,7 @@ class Cmd:
4572
4601
  @staticmethod
4573
4602
  def _build__eof_parser() -> Cmd2ArgumentParser:
4574
4603
  _eof_parser = argparse_utils.DEFAULT_ARGUMENT_PARSER(description="Called when Ctrl-D is pressed.")
4575
- _eof_parser.epilog = TextGroup(
4604
+ _eof_parser.epilog = TextGroup( # type: ignore[assignment, ty:invalid-assignment]
4576
4605
  "Note",
4577
4606
  "This command is for internal use and is not intended to be called from the command line.",
4578
4607
  )
@@ -5032,7 +5061,7 @@ class Cmd:
5032
5061
  # Check if we are running Python code
5033
5062
  if py_code_to_run:
5034
5063
  try: # noqa: SIM105
5035
- interp.runcode(py_code_to_run) # type: ignore[arg-type]
5064
+ interp.runcode(py_code_to_run) # type: ignore[arg-type, ty:invalid-argument-type]
5036
5065
  except BaseException: # noqa: BLE001, S110
5037
5066
  # We don't care about any exception that happened in the Python code
5038
5067
  pass
@@ -5418,11 +5447,11 @@ class Cmd:
5418
5447
  try:
5419
5448
  import lzma as decompress_lib
5420
5449
 
5421
- decompress_exceptions: tuple[type[Exception]] = (decompress_lib.LZMAError,)
5450
+ decompress_exceptions: tuple[type[Exception], ...] = (decompress_lib.LZMAError,)
5422
5451
  except ModuleNotFoundError: # pragma: no cover
5423
5452
  import bz2 as decompress_lib # type: ignore[no-redef]
5424
5453
 
5425
- decompress_exceptions: tuple[type[Exception]] = (OSError, ValueError) # type: ignore[no-redef]
5454
+ decompress_exceptions: tuple[type[Exception], ...] = (OSError, ValueError) # type: ignore[no-redef]
5426
5455
 
5427
5456
  try:
5428
5457
  history_json = decompress_lib.decompress(compressed_bytes).decode(encoding="utf-8")
@@ -5471,7 +5500,7 @@ class Cmd:
5471
5500
  def _build_edit_parser(cls) -> Cmd2ArgumentParser:
5472
5501
  edit_description = "Run a text editor and optionally open a file with it."
5473
5502
  edit_parser = argparse_utils.DEFAULT_ARGUMENT_PARSER(description=edit_description)
5474
- edit_parser.epilog = TextGroup(
5503
+ edit_parser.epilog = TextGroup( # type: ignore[assignment, ty:invalid-assignment]
5475
5504
  "Note",
5476
5505
  Text.assemble(
5477
5506
  "To set a new editor, run: ",
@@ -5593,7 +5622,7 @@ class Cmd:
5593
5622
  _relative_run_script_parser = cls._build_base_run_script_parser()
5594
5623
 
5595
5624
  # Append to existing description
5596
- _relative_run_script_parser.description = Group(
5625
+ _relative_run_script_parser.description = Group( # type: ignore[assignment, ty:invalid-assignment]
5597
5626
  cast(Group, _relative_run_script_parser.description),
5598
5627
  "\n",
5599
5628
  (
@@ -5602,7 +5631,7 @@ class Cmd:
5602
5631
  ),
5603
5632
  )
5604
5633
 
5605
- _relative_run_script_parser.epilog = TextGroup(
5634
+ _relative_run_script_parser.epilog = TextGroup( # type: ignore[assignment, ty:invalid-assignment]
5606
5635
  "Note",
5607
5636
  "This command is intended to be used from within a text script.",
5608
5637
  )
@@ -310,7 +310,7 @@ def with_argparser(
310
310
  :return: Function that takes raw input and converts to an argparse Namespace to passed to the wrapped function.
311
311
  """
312
312
 
313
- @functools.wraps(func)
313
+ @functools.wraps(func) # type: ignore[arg-type, ty:invalid-argument-type]
314
314
  def cmd_wrapper(*args: Any, **kwargs: Any) -> bool | None:
315
315
  """Command function wrapper which translates command line into argparse Namespace and call actual command function.
316
316
 
@@ -345,9 +345,9 @@ def with_argparser(
345
345
  parsing_results: tuple[argparse.Namespace] | tuple[argparse.Namespace, list[str]]
346
346
  with arg_parser.output_to(cmd_app.stdout):
347
347
  if with_unknown_args:
348
- parsing_results = arg_parser.parse_known_args(command_arg_list, initial_namespace)
348
+ parsing_results = arg_parser.parse_known_args(command_arg_list, initial_namespace) # type: ignore[assignment, ty:invalid-assignment]
349
349
  else:
350
- parsing_results = (arg_parser.parse_args(command_arg_list, initial_namespace),)
350
+ parsing_results = (arg_parser.parse_args(command_arg_list, initial_namespace),) # type: ignore[assignment, ty:invalid-assignment]
351
351
  except SystemExit as exc:
352
352
  raise Cmd2ArgparseError from exc
353
353
 
@@ -248,7 +248,7 @@ class PartialStatement:
248
248
 
249
249
  Note:
250
250
  Unlike [cmd2.parsing.Statement][], this is a simple data object
251
- and does not inherit from [str][].
251
+ and does not inherit from `str`.
252
252
 
253
253
  """
254
254
 
@@ -552,7 +552,7 @@ class StatementParser:
552
552
  def parse_command_only(self, rawinput: str) -> PartialStatement:
553
553
  """Identify the command and arguments from raw input.
554
554
 
555
- Partially parse input into a [cmd2.PartialStatement][] object.
555
+ Partially parse input into a [cmd2.parsing.PartialStatement][] object.
556
556
 
557
557
  The command is identified, and shortcuts and aliases are expanded.
558
558
  Multiline commands are identified, but terminators and output
@@ -561,7 +561,7 @@ class StatementParser:
561
561
  This method is optimized for completion code and gracefully handles
562
562
  unclosed quotes without raising exceptions.
563
563
 
564
- [cmd2.parsing.PartialStatement.args][] will include all output redirection
564
+ `cmd2.parsing.PartialStatement.args` will include all output redirection
565
565
  clauses and command terminators.
566
566
 
567
567
  Note:
@@ -571,7 +571,7 @@ class StatementParser:
571
571
  whitespace only if all quotes are closed.
572
572
 
573
573
  :param rawinput: the command line as entered by the user
574
- :return: a [cmd2.PartialStatement][] object representing the split input
574
+ :return: a `PartialStatement` object representing the split input
575
575
 
576
576
  """
577
577
  # Expand shortcuts and aliases
@@ -148,7 +148,7 @@ class Cmd2Completer(Completer):
148
148
  self._cmd_app = cmd_app
149
149
  self.custom_settings = custom_settings
150
150
 
151
- def get_completions(self, document: Document, _complete_event: object) -> Iterable[Completion]:
151
+ def get_completions(self, document: Document, complete_event: object) -> Iterable[Completion]: # noqa: ARG002
152
152
  """Get completions for the current input."""
153
153
  # Find the beginning of the current word based on delimiters
154
154
  line = document.text
@@ -105,7 +105,7 @@ class AllowStyle(Enum):
105
105
 
106
106
 
107
107
  # Controls when ANSI style sequences are allowed in output
108
- ALLOW_STYLE = AllowStyle.TERMINAL
108
+ ALLOW_STYLE: AllowStyle = AllowStyle.TERMINAL
109
109
 
110
110
 
111
111
  class Cmd2HelpFormatter(RichHelpFormatter):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cmd2
3
- Version: 4.2.0
3
+ Version: 4.2.2
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
@@ -14,6 +14,7 @@ mkdocs.yml
14
14
  package.json
15
15
  pyproject.toml
16
16
  ruff.toml
17
+ ty.toml
17
18
  cmd2/__init__.py
18
19
  cmd2/annotated.py
19
20
  cmd2/argparse_completer.py
@@ -128,6 +129,7 @@ examples/async_call.py
128
129
  examples/async_commands.py
129
130
  examples/async_printing.py
130
131
  examples/basic_completion.py
132
+ examples/cmd2_history.dat
131
133
  examples/cmd_as_argument.py
132
134
  examples/color.py
133
135
  examples/command_sets.py