cmd2 3.0.0rc1__tar.gz → 3.1.1__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 (338) hide show
  1. {cmd2-3.0.0rc1 → cmd2-3.1.1}/.pre-commit-config.yaml +2 -2
  2. cmd2-3.1.1/.prettierignore +5 -0
  3. {cmd2-3.0.0rc1 → cmd2-3.1.1}/CHANGELOG.md +29 -1
  4. cmd2-3.1.1/LICENSE +18 -0
  5. {cmd2-3.0.0rc1 → cmd2-3.1.1}/MANIFEST.in +1 -1
  6. {cmd2-3.0.0rc1 → cmd2-3.1.1}/Makefile +54 -16
  7. {cmd2-3.0.0rc1 → cmd2-3.1.1}/PKG-INFO +9 -8
  8. {cmd2-3.0.0rc1 → cmd2-3.1.1}/README.md +5 -5
  9. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/argparse_completer.py +1 -1
  10. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/argparse_custom.py +59 -22
  11. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/cmd2.py +66 -46
  12. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/parsing.py +6 -4
  13. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/py_bridge.py +1 -1
  14. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/rich_utils.py +1 -74
  15. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/styles.py +2 -4
  16. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/transcript.py +1 -1
  17. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2.egg-info/PKG-INFO +9 -8
  18. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2.egg-info/SOURCES.txt +2 -104
  19. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2.egg-info/requires.txt +2 -2
  20. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/doc_conventions.md +1 -1
  21. cmd2-3.1.1/docs/examples/examples.md +3 -0
  22. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/examples/getting_started.md +1 -3
  23. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/argument_processing.md +2 -2
  24. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/clipboard.md +5 -0
  25. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/generating_output.md +1 -1
  26. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/history.md +1 -1
  27. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/initialization.md +1 -3
  28. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/modular_commands.md +17 -16
  29. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/settings.md +5 -6
  30. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/index.md +19 -26
  31. cmd2-3.1.1/docs/javascripts/readthedocs.js +8 -0
  32. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/migrating/minimum.md +4 -4
  33. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/migrating/why.md +5 -0
  34. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/README.md +4 -2
  35. cmd2-3.1.1/examples/async_call.py +80 -0
  36. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/cmd2_history.dat +0 -0
  37. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/modular_commands/commandset_custominit.py +2 -3
  38. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/modular_commands.py +3 -3
  39. cmd2-3.1.1/examples/pretty_print.py +44 -0
  40. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/rich_tables.py +7 -0
  41. {cmd2-3.0.0rc1 → cmd2-3.1.1}/mkdocs.yml +11 -20
  42. {cmd2-3.0.0rc1 → cmd2-3.1.1}/package.json +1 -1
  43. {cmd2-3.0.0rc1 → cmd2-3.1.1}/pyproject.toml +26 -35
  44. {cmd2-3.0.0rc1 → cmd2-3.1.1}/ruff.toml +3 -0
  45. cmd2-3.1.1/scripts/validate_tag.py +88 -0
  46. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_argparse_custom.py +49 -11
  47. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_cmd2.py +15 -0
  48. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_completion.py +8 -10
  49. cmd2-3.1.1/tests/test_rich_utils.py +144 -0
  50. cmd2-3.0.0rc1/.prettierignore +0 -2
  51. cmd2-3.0.0rc1/LICENSE +0 -21
  52. cmd2-3.0.0rc1/docs/examples/examples.md +0 -5
  53. cmd2-3.0.0rc1/docs/javascripts/readthedocs.js +0 -33
  54. cmd2-3.0.0rc1/docs/stylesheets/readthedocs.css +0 -11
  55. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/@plugins_snapshot.json +0 -1
  56. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/_ast.data.json +0 -1
  57. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/_ast.meta.json +0 -1
  58. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/_codecs.data.json +0 -1
  59. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/_codecs.meta.json +0 -1
  60. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/_collections_abc.data.json +0 -1
  61. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/_collections_abc.meta.json +0 -1
  62. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/_typeshed/__init__.data.json +0 -1
  63. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/_typeshed/__init__.meta.json +0 -1
  64. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/_typeshed/importlib.data.json +0 -1
  65. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/_typeshed/importlib.meta.json +0 -1
  66. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/abc.data.json +0 -1
  67. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/abc.meta.json +0 -1
  68. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/argparse.data.json +0 -1
  69. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/argparse.meta.json +0 -1
  70. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/builtins.data.json +0 -1
  71. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/builtins.meta.json +0 -1
  72. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/codecs.data.json +0 -1
  73. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/codecs.meta.json +0 -1
  74. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/collections/__init__.data.json +0 -1
  75. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/collections/__init__.meta.json +0 -1
  76. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/collections/abc.data.json +0 -1
  77. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/collections/abc.meta.json +0 -1
  78. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/contextlib.data.json +0 -1
  79. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/contextlib.meta.json +0 -1
  80. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/dataclasses.data.json +0 -1
  81. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/dataclasses.meta.json +0 -1
  82. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/__init__.data.json +0 -1
  83. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/__init__.meta.json +0 -1
  84. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/_policybase.data.json +0 -1
  85. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/_policybase.meta.json +0 -1
  86. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/charset.data.json +0 -1
  87. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/charset.meta.json +0 -1
  88. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/contentmanager.data.json +0 -1
  89. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/contentmanager.meta.json +0 -1
  90. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/errors.data.json +0 -1
  91. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/errors.meta.json +0 -1
  92. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/header.data.json +0 -1
  93. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/header.meta.json +0 -1
  94. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/message.data.json +0 -1
  95. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/message.meta.json +0 -1
  96. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/policy.data.json +0 -1
  97. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/email/policy.meta.json +0 -1
  98. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/enum.data.json +0 -1
  99. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/enum.meta.json +0 -1
  100. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/genericpath.data.json +0 -1
  101. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/genericpath.meta.json +0 -1
  102. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/__init__.data.json +0 -1
  103. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/__init__.meta.json +0 -1
  104. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/_abc.data.json +0 -1
  105. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/_abc.meta.json +0 -1
  106. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/abc.data.json +0 -1
  107. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/abc.meta.json +0 -1
  108. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/machinery.data.json +0 -1
  109. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/machinery.meta.json +0 -1
  110. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/metadata/__init__.data.json +0 -1
  111. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/metadata/__init__.meta.json +0 -1
  112. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/metadata/_meta.data.json +0 -1
  113. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/metadata/_meta.meta.json +0 -1
  114. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/readers.data.json +0 -1
  115. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/readers.meta.json +0 -1
  116. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/resources/__init__.data.json +0 -1
  117. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/resources/__init__.meta.json +0 -1
  118. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/resources/abc.data.json +0 -1
  119. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/importlib/resources/abc.meta.json +0 -1
  120. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/io.data.json +0 -1
  121. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/io.meta.json +0 -1
  122. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/os/__init__.data.json +0 -1
  123. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/os/__init__.meta.json +0 -1
  124. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/os/path.data.json +0 -1
  125. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/os/path.meta.json +0 -1
  126. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/pathlib.data.json +0 -1
  127. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/pathlib.meta.json +0 -1
  128. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/posixpath.data.json +0 -1
  129. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/posixpath.meta.json +0 -1
  130. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/re.data.json +0 -1
  131. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/re.meta.json +0 -1
  132. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/resource.data.json +0 -1
  133. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/resource.meta.json +0 -1
  134. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/sre_compile.data.json +0 -1
  135. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/sre_compile.meta.json +0 -1
  136. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/sre_constants.data.json +0 -1
  137. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/sre_constants.meta.json +0 -1
  138. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/sre_parse.data.json +0 -1
  139. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/sre_parse.meta.json +0 -1
  140. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/subprocess.data.json +0 -1
  141. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/subprocess.meta.json +0 -1
  142. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/sys/__init__.data.json +0 -1
  143. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/sys/__init__.meta.json +0 -1
  144. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/sys/_monitoring.data.json +0 -1
  145. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/sys/_monitoring.meta.json +0 -1
  146. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/types.data.json +0 -1
  147. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/types.meta.json +0 -1
  148. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/typing.data.json +0 -1
  149. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/typing.meta.json +0 -1
  150. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/typing_extensions.data.json +0 -1
  151. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/typing_extensions.meta.json +0 -1
  152. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/zipfile/__init__.data.json +0 -1
  153. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/zipfile/__init__.meta.json +0 -1
  154. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/zipfile/_path.data.json +0 -1
  155. cmd2-3.0.0rc1/examples/.mypy_cache/3.12/zipfile/_path.meta.json +0 -1
  156. cmd2-3.0.0rc1/examples/.mypy_cache/CACHEDIR.TAG +0 -3
  157. cmd2-3.0.0rc1/examples/pretty_print.py +0 -29
  158. cmd2-3.0.0rc1/tasks.py +0 -322
  159. cmd2-3.0.0rc1/tests/test_rich_utils.py +0 -331
  160. {cmd2-3.0.0rc1 → cmd2-3.1.1}/.prettierrc +0 -0
  161. {cmd2-3.0.0rc1 → cmd2-3.1.1}/GEMINI.md +0 -0
  162. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/__init__.py +0 -0
  163. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/clipboard.py +0 -0
  164. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/colors.py +0 -0
  165. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/command_definition.py +0 -0
  166. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/constants.py +0 -0
  167. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/decorators.py +0 -0
  168. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/exceptions.py +0 -0
  169. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/history.py +0 -0
  170. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/plugin.py +0 -0
  171. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/py.typed +0 -0
  172. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/rl_utils.py +0 -0
  173. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/string_utils.py +0 -0
  174. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/terminal_utils.py +0 -0
  175. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2/utils.py +0 -0
  176. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2.egg-info/dependency_links.txt +0 -0
  177. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2.egg-info/top_level.txt +0 -0
  178. {cmd2-3.0.0rc1 → cmd2-3.1.1}/cmd2.png +0 -0
  179. {cmd2-3.0.0rc1 → cmd2-3.1.1}/codecov.yml +0 -0
  180. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/argparse_completer.md +0 -0
  181. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/argparse_custom.md +0 -0
  182. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/clipboard.md +0 -0
  183. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/cmd.md +0 -0
  184. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/colors.md +0 -0
  185. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/command_definition.md +0 -0
  186. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/constants.md +0 -0
  187. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/decorators.md +0 -0
  188. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/exceptions.md +0 -0
  189. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/history.md +0 -0
  190. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/index.md +0 -0
  191. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/parsing.md +0 -0
  192. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/plugin.md +0 -0
  193. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/py_bridge.md +0 -0
  194. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/rich_utils.md +0 -0
  195. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/rl_utils.md +0 -0
  196. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/string_utils.md +0 -0
  197. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/styles.md +0 -0
  198. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/terminal_utils.md +0 -0
  199. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/transcript.md +0 -0
  200. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/api/utils.md +0 -0
  201. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/examples/alternate_event_loops.md +0 -0
  202. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/examples/index.md +0 -0
  203. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/builtin_commands.md +0 -0
  204. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/commands.md +0 -0
  205. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/completion.md +0 -0
  206. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/disable_commands.md +0 -0
  207. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/embedded_python_shells.md +0 -0
  208. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/help.md +0 -0
  209. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/hooks.md +0 -0
  210. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/index.md +0 -0
  211. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/misc.md +0 -0
  212. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/multiline_commands.md +0 -0
  213. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/os.md +0 -0
  214. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/packaging.md +0 -0
  215. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/plugins.md +0 -0
  216. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/prompt.md +0 -0
  217. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/redirection.md +0 -0
  218. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/scripting.md +0 -0
  219. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/shortcuts_aliases_macros.md +0 -0
  220. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/startup_commands.md +0 -0
  221. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/table_creation.md +0 -0
  222. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/theme.md +0 -0
  223. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/features/transcripts.md +0 -0
  224. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/migrating/incompatibilities.md +0 -0
  225. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/migrating/index.md +0 -0
  226. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/migrating/next_steps.md +0 -0
  227. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/mixins/index.md +0 -0
  228. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/mixins/mixin_template.md +0 -0
  229. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/overrides/main.html +0 -0
  230. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/overview/alternatives.md +0 -0
  231. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/overview/index.md +0 -0
  232. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/overview/installation.md +0 -0
  233. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/overview/integrating.md +0 -0
  234. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/overview/resources.md +0 -0
  235. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/stylesheets/cmd2.css +0 -0
  236. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/testing.md +0 -0
  237. {cmd2-3.0.0rc1 → cmd2-3.1.1}/docs/upgrades.md +0 -0
  238. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/.cmd2rc +0 -0
  239. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/argparse_completion.py +0 -0
  240. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/argparse_example.py +0 -0
  241. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/async_printing.py +0 -0
  242. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/basic_completion.py +0 -0
  243. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/cmd_as_argument.py +0 -0
  244. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/color.py +0 -0
  245. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/command_sets.py +0 -0
  246. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/custom_parser.py +0 -0
  247. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/custom_types.py +0 -0
  248. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/default_categories.py +0 -0
  249. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/dynamic_commands.py +0 -0
  250. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/environment.py +0 -0
  251. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/event_loops.py +0 -0
  252. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/exit_code.py +0 -0
  253. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/getting_started.py +0 -0
  254. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/hello_cmd2.py +0 -0
  255. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/help_categories.py +0 -0
  256. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/hooks.py +0 -0
  257. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/migrating.py +0 -0
  258. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/mixin.py +0 -0
  259. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/modular_commands/__init__.py +0 -0
  260. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/modular_commands/commandset_basic.py +0 -0
  261. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/modular_commands/commandset_complex.py +0 -0
  262. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/paged_output.py +0 -0
  263. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/persistent_history.py +0 -0
  264. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/python_scripting.py +0 -0
  265. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/read_input.py +0 -0
  266. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/remove_builtin_commands.py +0 -0
  267. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/remove_settable.py +0 -0
  268. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/rich_theme.py +0 -0
  269. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/scripts/arg_printer.py +0 -0
  270. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/scripts/conditional.py +0 -0
  271. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/scripts/nested.txt +0 -0
  272. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/scripts/quit.txt +0 -0
  273. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/scripts/save_help_text.py +0 -0
  274. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/scripts/script.py +0 -0
  275. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/scripts/script.txt +0 -0
  276. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/tmux_launch.sh +0 -0
  277. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/tmux_split.sh +0 -0
  278. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/transcript_example.py +0 -0
  279. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/transcripts/exampleSession.txt +0 -0
  280. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/transcripts/pirate.transcript +0 -0
  281. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/transcripts/quit.txt +0 -0
  282. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/transcripts/transcript_regex.txt +0 -0
  283. {cmd2-3.0.0rc1 → cmd2-3.1.1}/examples/unicode_commands.py +0 -0
  284. {cmd2-3.0.0rc1 → cmd2-3.1.1}/setup.cfg +0 -0
  285. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/.cmd2rc +0 -0
  286. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/__init__.py +0 -0
  287. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/conftest.py +0 -0
  288. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/pyscript/echo.py +0 -0
  289. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/pyscript/environment.py +0 -0
  290. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/pyscript/help.py +0 -0
  291. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/pyscript/py_locals.py +0 -0
  292. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/pyscript/pyscript_dir.py +0 -0
  293. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/pyscript/raises_exception.py +0 -0
  294. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/pyscript/recursive.py +0 -0
  295. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/pyscript/self_in_py.py +0 -0
  296. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/pyscript/stdout_capture.py +0 -0
  297. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/pyscript/stop.py +0 -0
  298. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/relative_multiple.txt +0 -0
  299. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/script.py +0 -0
  300. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/script.txt +0 -0
  301. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/scripts/binary.bin +0 -0
  302. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/scripts/empty.txt +0 -0
  303. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/scripts/help.txt +0 -0
  304. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/scripts/nested.txt +0 -0
  305. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/scripts/one_down.txt +0 -0
  306. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/scripts/postcmds.txt +0 -0
  307. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/scripts/precmds.txt +0 -0
  308. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/scripts/utf8.txt +0 -0
  309. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_argparse.py +0 -0
  310. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_argparse_completer.py +0 -0
  311. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_argparse_subcommands.py +0 -0
  312. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_categories.py +0 -0
  313. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_commandset.py +0 -0
  314. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_future_annotations.py +0 -0
  315. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_history.py +0 -0
  316. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_parsing.py +0 -0
  317. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_plugin.py +0 -0
  318. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_run_pyscript.py +0 -0
  319. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_string_utils.py +0 -0
  320. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_terminal_utils.py +0 -0
  321. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_transcript.py +0 -0
  322. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_utils.py +0 -0
  323. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/test_utils_defining_class.py +0 -0
  324. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/bol_eol.txt +0 -0
  325. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/characterclass.txt +0 -0
  326. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/dotstar.txt +0 -0
  327. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/extension_notation.txt +0 -0
  328. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/failure.txt +0 -0
  329. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/from_cmdloop.txt +0 -0
  330. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/multiline_no_regex.txt +0 -0
  331. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/multiline_regex.txt +0 -0
  332. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/no_output.txt +0 -0
  333. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/no_output_last.txt +0 -0
  334. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/singleslash.txt +0 -0
  335. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/slashes_escaped.txt +0 -0
  336. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/slashslash.txt +0 -0
  337. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/spaces.txt +0 -0
  338. {cmd2-3.0.0rc1 → cmd2-3.1.1}/tests/transcripts/word_boundaries.txt +0 -0
@@ -9,7 +9,7 @@ repos:
9
9
  - id: trailing-whitespace
10
10
 
11
11
  - repo: https://github.com/astral-sh/ruff-pre-commit
12
- rev: "v0.13.2"
12
+ rev: "v0.14.14"
13
13
  hooks:
14
14
  - id: ruff-format
15
15
  args: [--config=ruff.toml]
@@ -21,5 +21,5 @@ repos:
21
21
  hooks:
22
22
  - id: prettier
23
23
  additional_dependencies:
24
- - prettier@3.6.2
24
+ - prettier@3.8.0
25
25
  - prettier-plugin-toml@2.0.6
@@ -0,0 +1,5 @@
1
+ # File is nicely lined up
2
+ .github/CODEOWNERS
3
+
4
+ # Markdown documentation files with non-standard syntax for mkdocstrings that Prettier should not auto-format
5
+ docs/features/initialization.md
@@ -1,4 +1,16 @@
1
- ## 3.0.0 (October TBD, 2025)
1
+ ## 3.1.1 (January 26, 2026)
2
+
3
+ - Bug Fixes
4
+ - Fixed bug where `rich-argparse` was not coloring cmd2's custom `nargs` formatting
5
+
6
+ ## 3.1.0 (December 25, 2025)
7
+
8
+ - Potentially Breaking Changes
9
+ - `cmd2` no longer has a dependency on `cmd` and `cmd2.Cmd` no longer inherits from `cmd.Cmd`
10
+ - We don't _think_ this should impact users, but there is theoretically a possibility
11
+ - This opens the door for more impactful changes in the next major release
12
+
13
+ ## 3.0.0 (December 7, 2025)
2
14
 
3
15
  ### Summary
4
16
 
@@ -16,6 +28,8 @@ time reading the [rich documentation](https://rich.readthedocs.io/).
16
28
  [rich_tables.py](https://github.com/python-cmd2/cmd2/blob/main/examples/rich_tables.py)
17
29
  example for more info)
18
30
  - Moved all string-related functions from `utils.py` to a new `string_utils.py` module
31
+ - Removed redundant `string` from some of the names so `quote_string` is now just
32
+ `quote` and `quote_string_if_needed` is now `quote_if_needed`
19
33
  - Consolidated all string styling functions from `ansi.py` into `string_utils.py`
20
34
  - Replaced all text style enums from `ansi.py` with modern `rich` styles
21
35
  - Renamed `ansi.py` to `terminal_utils.py` to better reflect its purpose
@@ -25,6 +39,20 @@ time reading the [rich documentation](https://rich.readthedocs.io/).
25
39
  - Removed redundant setting of a parser's `prog` value in the `with_argparser()` decorator, as
26
40
  this is now handled centrally in `Cmd._build_parser()`
27
41
  - The `auto_load_commands` argument to `cmd2.Cmd.__init__` now defaults to `False`
42
+ - `argparse_custom` module breaking changes:
43
+ - `descriptive_header: str` replaced with `descriptive_headers: Sequence[str | rich.Column]`
44
+ - Applies to parameter name when adding an argument to a parser as well as
45
+ `set_descriptive_headers` and `get_descriptive_headers`
46
+ - `CompletionItem.description: str` changed to
47
+ `CompletionItem.descriptive_data: Sequence[str | rich.Column]`
48
+ - `decorators` module breaking changes:
49
+ - `_set_parser_prog` renamed to `set_parser_prog` (without the leading underscore) and moved
50
+ to `argparse_custom` module
51
+ - Renamed history `--output_file` to `--output-file` to follow common command-line practices
52
+ - `cmd2.Cmd.ppretty` method removed - `rich` has more and better options for pretty printing,
53
+ see the
54
+ [pretty_print.py](https://github.com/python-cmd2/cmd2/blob/main/examples/pretty_print.py)
55
+ example for a demonstration of pretty-printing JSON data
28
56
 
29
57
  - Enhancements
30
58
  - Enhanced all print methods (`poutput()`, `perror()`, `ppaged()`, etc.) to natively render
cmd2-3.1.1/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2008-2026 Catherine Devlin and others
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction,
7
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
8
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
17
+ OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,4 +1,4 @@
1
- include LICENSE README.md CHANGELOG.md mkdocs.yml pyproject.toml ruff.toml tasks.py
1
+ include LICENSE README.md CHANGELOG.md Makefile mkdocs.yml pyproject.toml ruff.toml
2
2
  recursive-include examples *
3
3
  recursive-include tests *
4
4
  recursive-include docs *
@@ -1,9 +1,12 @@
1
1
  # Simple Makefile for use with a uv-based development environment
2
+ # The at (@) prefix tells make to suppress output from the command
3
+ # The hyphen (-) prefix tells make to ignore errors (e.g., if a directory doesn't exist)
4
+
2
5
  .PHONY: install
3
6
  install: ## Install the virtual environment with dependencies
4
7
  @echo "🚀 Creating uv Python virtual environment"
5
- @uv python install 3.13
6
- @uv sync --python=3.13
8
+ @uv python install 3.14
9
+ @uv sync --python=3.14
7
10
  @echo "🚀 Installing Git pre-commit hooks locally"
8
11
  @uv run pre-commit install
9
12
  @echo "🚀 Installing Prettier using npm"
@@ -37,21 +40,16 @@ test: ## Test the code with pytest.
37
40
 
38
41
  .PHONY: docs-test
39
42
  docs-test: ## Test if documentation can be built without warnings or errors
40
- @uv run mkdocs build -s
43
+ @uv run zensical build -s
41
44
 
42
45
  .PHONY: docs
43
- docs: ## Build and serve the documentation
44
- @uv run mkdocs serve
46
+ docs: ## Build and serve the documentation (and open in default browser)
47
+ @uv run zensical serve -o
45
48
 
46
49
  .PHONY: build
47
50
  build: clean-build ## Build wheel file
48
51
  @echo "🚀 Creating wheel file"
49
- @uvx --from build pyproject-build --installer uv
50
-
51
- .PHONY: clean-build
52
- clean-build: ## Clean build artifacts
53
- @echo "🚀 Removing build artifacts"
54
- @uv run python -c "import shutil; import os; shutil.rmtree('dist') if os.path.exists('dist') else None"
52
+ @uv build
55
53
 
56
54
  .PHONY: tag
57
55
  tag: ## Add a Git tag and push it to origin with syntax: make tag TAG=tag_name
@@ -63,17 +61,57 @@ tag: ## Add a Git tag and push it to origin with syntax: make tag TAG=tag_name
63
61
  .PHONY: validate-tag
64
62
  validate-tag: ## Check to make sure that a tag exists for the current HEAD and it looks like a valid version number
65
63
  @echo "🚀 Validating version tag"
66
- @uv run inv validatetag
64
+ @uv run scripts/validate_tag.py
67
65
 
68
66
  .PHONY: publish-test
69
- publish-test: validate-tag build ## Test publishing a release to PyPI.
67
+ publish-test: validate-tag build ## Test publishing a release to PyPI, uses token from ~/.pypirc file.
70
68
  @echo "🚀 Publishing: Dry run."
71
- @uvx twine upload --repository testpypi dist/*
69
+ @uv run uv-publish --repository testpypi
72
70
 
73
71
  .PHONY: publish
74
- publish: validate-tag build ## Publish a release to PyPI.
72
+ publish: validate-tag build ## Publish a release to PyPI, uses token from ~/.pypirc file.
75
73
  @echo "🚀 Publishing."
76
- @uvx twine upload dist/*
74
+ @uv run uv-publish
75
+
76
+ # Define variables for files/directories to clean
77
+ BUILD_DIRS = build dist *.egg-info
78
+ DOC_DIRS = build
79
+ MYPY_DIRS = .mypy_cache dmypy.json dmypy.sock
80
+ TEST_DIRS = .cache .coverage .pytest_cache htmlcov
81
+
82
+ .PHONY: clean-build
83
+ clean-build: ## Clean build artifacts
84
+ @echo "🚀 Removing build artifacts"
85
+ @uv run python -c "import shutil; import os; [shutil.rmtree(d, ignore_errors=True) for d in '$(BUILD_DIRS)'.split() if os.path.isdir(d)]"
86
+
87
+ .PHONY: clean-docs
88
+ clean-docs: ## Clean documentation artifacts
89
+ @echo "🚀 Removing documentation artifacts"
90
+ @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)]"
91
+
92
+ .PHONY: clean-mypy
93
+ clean-mypy: ## Clean mypy artifacts
94
+ @echo "🚀 Removing mypy artifacts"
95
+ @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)]"
96
+
97
+ .PHONY: clean-pycache
98
+ clean-pycache: ## Clean pycache artifacts
99
+ @echo "🚀 Removing pycache artifacts"
100
+ @-find . -type d -name "__pycache__" -exec rm -r {} +
101
+
102
+ .PHONY: clean-ruff
103
+ clean-ruff: ## Clean ruff artifacts
104
+ @echo "🚀 Removing ruff artifacts"
105
+ @uv run ruff clean
106
+
107
+ .PHONY: clean-test
108
+ clean-test: ## Clean test artifacts
109
+ @echo "🚀 Removing test artifacts"
110
+ @uv run python -c "import shutil; import os; [shutil.rmtree(d, ignore_errors=True) for d in '$(TEST_DIRS)'.split() if os.path.isdir(d)]"
111
+
112
+ .PHONY: clean
113
+ clean: clean-build clean-docs clean-mypy clean-pycache clean-ruff clean-test ## Clean all artifacts
114
+ @echo "🚀 Cleaned all artifacts"
77
115
 
78
116
  .PHONY: help
79
117
  help:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cmd2
3
- Version: 3.0.0rc1
3
+ Version: 3.1.1
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
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Programming Language :: Python :: 3.15
19
20
  Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable
20
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
22
  Requires-Python: >=3.10
@@ -23,16 +24,16 @@ Description-Content-Type: text/markdown
23
24
  License-File: LICENSE
24
25
  Requires-Dist: backports.strenum; python_version == "3.10"
25
26
  Requires-Dist: gnureadline>=8; platform_system == "Darwin"
26
- Requires-Dist: pyperclip>=1.8
27
+ Requires-Dist: pyperclip>=1.8.2
27
28
  Requires-Dist: pyreadline3>=3.4; platform_system == "Windows"
28
- Requires-Dist: rich>=14.1.0
29
+ Requires-Dist: rich>=14.3.0
29
30
  Requires-Dist: rich-argparse>=1.7.1
30
31
  Dynamic: license-file
31
32
 
32
33
  <h1 align="center">cmd2 : immersive interactive command line applications</h1>
33
34
 
34
35
  [![Latest Version](https://img.shields.io/pypi/v/cmd2.svg?style=flat-square&label=latest%20stable%20version)](https://pypi.python.org/pypi/cmd2/)
35
- [![GitHub Actions](https://github.com/python-cmd2/cmd2/workflows/CI/badge.svg)](https://github.com/python-cmd2/cmd2/actions?query=workflow%3ACI)
36
+ [![Tests](https://github.com/python-cmd2/cmd2/actions/workflows/tests.yml/badge.svg)](https://github.com/python-cmd2/cmd2/actions/workflows/tests.yml)
36
37
  [![codecov](https://codecov.io/gh/python-cmd2/cmd2/branch/main/graph/badge.svg)](https://codecov.io/gh/python-cmd2/cmd2)
37
38
  [![Documentation Status](https://readthedocs.org/projects/cmd2/badge/?version=latest)](http://cmd2.readthedocs.io/en/latest/?badge=latest)
38
39
  <a href="https://discord.gg/RpVG6tk"><img src="https://img.shields.io/badge/chat-on%20discord-7289da.svg" alt="Chat"></a>
@@ -56,10 +57,10 @@ applications. It provides a simple API which is an extension of Python's built-i
56
57
  of cmd to make your life easier and eliminates much of the boilerplate code which would be necessary
57
58
  when using cmd.
58
59
 
59
- > :warning: **cmd2 is now "feature complete" for the `2.x` branch and is actively working on the
60
- > 3.0.0 release on the `main` branch. New features will only be addressed in 3.x moving forwards. If
61
- > need be, we will still fix bugs in 2.x. A beta version, 3.0.0b2, is available for testing and we
62
- > would appreciate feedback.**
60
+ > :warning: **`cmd2` 3.0.0 has been released and there are some significant backwards
61
+ > incompatibilities from version `2.x`. Please see the
62
+ > [Migration Guide](https://cmd2.readthedocs.io/en/latest/upgrades/) for tips on upgrading from
63
+ > `cmd2` 2.x to 3.x.**
63
64
 
64
65
  ## The developers toolbox
65
66
 
@@ -1,7 +1,7 @@
1
1
  <h1 align="center">cmd2 : immersive interactive command line applications</h1>
2
2
 
3
3
  [![Latest Version](https://img.shields.io/pypi/v/cmd2.svg?style=flat-square&label=latest%20stable%20version)](https://pypi.python.org/pypi/cmd2/)
4
- [![GitHub Actions](https://github.com/python-cmd2/cmd2/workflows/CI/badge.svg)](https://github.com/python-cmd2/cmd2/actions?query=workflow%3ACI)
4
+ [![Tests](https://github.com/python-cmd2/cmd2/actions/workflows/tests.yml/badge.svg)](https://github.com/python-cmd2/cmd2/actions/workflows/tests.yml)
5
5
  [![codecov](https://codecov.io/gh/python-cmd2/cmd2/branch/main/graph/badge.svg)](https://codecov.io/gh/python-cmd2/cmd2)
6
6
  [![Documentation Status](https://readthedocs.org/projects/cmd2/badge/?version=latest)](http://cmd2.readthedocs.io/en/latest/?badge=latest)
7
7
  <a href="https://discord.gg/RpVG6tk"><img src="https://img.shields.io/badge/chat-on%20discord-7289da.svg" alt="Chat"></a>
@@ -25,10 +25,10 @@ applications. It provides a simple API which is an extension of Python's built-i
25
25
  of cmd to make your life easier and eliminates much of the boilerplate code which would be necessary
26
26
  when using cmd.
27
27
 
28
- > :warning: **cmd2 is now "feature complete" for the `2.x` branch and is actively working on the
29
- > 3.0.0 release on the `main` branch. New features will only be addressed in 3.x moving forwards. If
30
- > need be, we will still fix bugs in 2.x. A beta version, 3.0.0b2, is available for testing and we
31
- > would appreciate feedback.**
28
+ > :warning: **`cmd2` 3.0.0 has been released and there are some significant backwards
29
+ > incompatibilities from version `2.x`. Please see the
30
+ > [Migration Guide](https://cmd2.readthedocs.io/en/latest/upgrades/) for tips on upgrading from
31
+ > `cmd2` 2.x to 3.x.**
32
32
 
33
33
  ## The developers toolbox
34
34
 
@@ -39,7 +39,7 @@ from .exceptions import CompletionError
39
39
  from .styles import Cmd2Style
40
40
 
41
41
  # If no descriptive headers are supplied, then this will be used instead
42
- DEFAULT_DESCRIPTIVE_HEADERS: Sequence[str | Column] = ('Description',)
42
+ DEFAULT_DESCRIPTIVE_HEADERS: Sequence[str | Column] = ['Description']
43
43
 
44
44
  # Name of the choice/completer function argument that, if present, will be passed a dictionary of
45
45
  # command line tokens up through the token being completed mapped to their argparse destination name.
@@ -258,14 +258,11 @@ sub-parser from a sub-parsers group. See _SubParsersAction_remove_parser` for mo
258
258
  import argparse
259
259
  import re
260
260
  import sys
261
- from argparse import (
262
- ONE_OR_MORE,
263
- ZERO_OR_MORE,
264
- ArgumentError,
265
- )
261
+ from argparse import ArgumentError
266
262
  from collections.abc import (
267
263
  Callable,
268
264
  Iterable,
265
+ Iterator,
269
266
  Sequence,
270
267
  )
271
268
  from gettext import gettext
@@ -293,6 +290,7 @@ from rich_argparse import (
293
290
  RawTextRichHelpFormatter,
294
291
  RichHelpFormatter,
295
292
  )
293
+ from typing_extensions import Self
296
294
 
297
295
  from . import constants
298
296
  from . import rich_utils as ru
@@ -380,7 +378,7 @@ class CompletionItem(str): # noqa: SLOT000
380
378
  See header of this file for more information
381
379
  """
382
380
 
383
- def __new__(cls, value: object, *_args: Any, **_kwargs: Any) -> 'CompletionItem':
381
+ def __new__(cls, value: object, *_args: Any, **_kwargs: Any) -> Self:
384
382
  """Responsible for creating and returning a new instance, called before __init__ when an object is instantiated."""
385
383
  return super().__new__(cls, value)
386
384
 
@@ -804,7 +802,7 @@ def _add_argument_wrapper(
804
802
  choices_provider: ChoicesProviderFunc | None = None,
805
803
  completer: CompleterFunc | None = None,
806
804
  suppress_tab_hint: bool = False,
807
- descriptive_headers: list[Column | str] | None = None,
805
+ descriptive_headers: Sequence[str | Column] | None = None,
808
806
  **kwargs: Any,
809
807
  ) -> argparse.Action:
810
808
  """Wrap ActionsContainer.add_argument() which supports more settings used by cmd2.
@@ -1295,29 +1293,68 @@ class Cmd2HelpFormatter(RichHelpFormatter):
1295
1293
 
1296
1294
  return format_tuple
1297
1295
 
1296
+ def _build_nargs_range_str(self, nargs_range: tuple[int, int | float]) -> str:
1297
+ """Generate nargs range string for help text."""
1298
+ if nargs_range[1] == constants.INFINITY:
1299
+ # {min+}
1300
+ range_str = f"{{{nargs_range[0]}+}}"
1301
+ else:
1302
+ # {min..max}
1303
+ range_str = f"{{{nargs_range[0]}..{nargs_range[1]}}}"
1304
+
1305
+ return range_str
1306
+
1298
1307
  def _format_args(self, action: argparse.Action, default_metavar: str) -> str:
1299
- """Handle ranged nargs and make other output less verbose."""
1308
+ """Override to handle cmd2's custom nargs formatting.
1309
+
1310
+ All formats in this function need to be handled by _rich_metavar_parts().
1311
+ """
1300
1312
  metavar = self._determine_metavar(action, default_metavar)
1301
1313
  metavar_formatter = self._metavar_formatter(action, default_metavar)
1302
1314
 
1303
1315
  # Handle nargs specified as a range
1304
1316
  nargs_range = action.get_nargs_range() # type: ignore[attr-defined]
1305
1317
  if nargs_range is not None:
1306
- range_str = f'{nargs_range[0]}+' if nargs_range[1] == constants.INFINITY else f'{nargs_range[0]}..{nargs_range[1]}'
1307
-
1308
- return '{}{{{}}}'.format('%s' % metavar_formatter(1), range_str) # noqa: UP031
1309
-
1310
- # Make this output less verbose. Do not customize the output when metavar is a
1311
- # tuple of strings. Allow argparse's formatter to handle that instead.
1312
- if isinstance(metavar, str):
1313
- if action.nargs == ZERO_OR_MORE:
1314
- return '[%s [...]]' % metavar_formatter(1) # noqa: UP031
1315
- if action.nargs == ONE_OR_MORE:
1316
- return '%s [...]' % metavar_formatter(1) # noqa: UP031
1317
- if isinstance(action.nargs, int) and action.nargs > 1:
1318
- return '{}{{{}}}'.format('%s' % metavar_formatter(1), action.nargs) # noqa: UP031
1318
+ arg_str = '%s' % metavar_formatter(1) # noqa: UP031
1319
+ range_str = self._build_nargs_range_str(nargs_range)
1320
+ return f"{arg_str}{range_str}"
1321
+
1322
+ # When nargs is just a number, argparse repeats the arg in the help text.
1323
+ # For instance, when nargs=5 the help text looks like: 'command arg arg arg arg arg'.
1324
+ # To make this less verbose, format it like: 'command arg{5}'.
1325
+ # Do not customize the output when metavar is a tuple of strings. Allow argparse's
1326
+ # formatter to handle that instead.
1327
+ if isinstance(metavar, str) and isinstance(action.nargs, int) and action.nargs > 1:
1328
+ arg_str = '%s' % metavar_formatter(1) # noqa: UP031
1329
+ return f"{arg_str}{{{action.nargs}}}"
1330
+
1331
+ # Fallback to parent for all other cases
1332
+ return super()._format_args(action, default_metavar)
1333
+
1334
+ def _rich_metavar_parts(
1335
+ self,
1336
+ action: argparse.Action,
1337
+ default_metavar: str,
1338
+ ) -> Iterator[tuple[str, bool]]:
1339
+ """Override to handle all cmd2-specific formatting in _format_args()."""
1340
+ metavar = self._determine_metavar(action, default_metavar)
1341
+ metavar_formatter = self._metavar_formatter(action, default_metavar)
1319
1342
 
1320
- return super()._format_args(action, default_metavar) # type: ignore[arg-type]
1343
+ # Handle nargs specified as a range
1344
+ nargs_range = action.get_nargs_range() # type: ignore[attr-defined]
1345
+ if nargs_range is not None:
1346
+ yield "%s" % metavar_formatter(1), True # noqa: UP031
1347
+ yield self._build_nargs_range_str(nargs_range), False
1348
+ return
1349
+
1350
+ # Handle specific integer nargs (e.g., nargs=5 -> arg{5})
1351
+ if isinstance(metavar, str) and isinstance(action.nargs, int) and action.nargs > 1:
1352
+ yield "%s" % metavar_formatter(1), True # noqa: UP031
1353
+ yield f"{{{action.nargs}}}", False
1354
+ return
1355
+
1356
+ # Fallback to parent for all other cases
1357
+ yield from super()._rich_metavar_parts(action, default_metavar)
1321
1358
 
1322
1359
 
1323
1360
  class RawDescriptionCmd2HelpFormatter(