cmd2 4.0.0b3__tar.gz → 4.0.0b4__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 (209) hide show
  1. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/PKG-INFO +1 -1
  2. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/completion.py +34 -15
  3. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2.egg-info/PKG-INFO +1 -1
  4. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_completion.py +139 -0
  5. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/.pre-commit-config.yaml +0 -0
  6. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/.prettierignore +0 -0
  7. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/.prettierrc +0 -0
  8. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/.typos.toml +0 -0
  9. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/CHANGELOG.md +0 -0
  10. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/GEMINI.md +0 -0
  11. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/LICENSE +0 -0
  12. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/MANIFEST.in +0 -0
  13. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/Makefile +0 -0
  14. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/README.md +0 -0
  15. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/__init__.py +0 -0
  16. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/argparse_completer.py +0 -0
  17. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/argparse_utils.py +0 -0
  18. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/clipboard.py +0 -0
  19. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/cmd2.py +0 -0
  20. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/colors.py +0 -0
  21. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/command_set.py +0 -0
  22. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/constants.py +0 -0
  23. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/decorators.py +0 -0
  24. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/exceptions.py +0 -0
  25. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/history.py +0 -0
  26. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/parsing.py +0 -0
  27. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/plugin.py +0 -0
  28. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/pt_utils.py +0 -0
  29. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/py.typed +0 -0
  30. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/py_bridge.py +0 -0
  31. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/rich_utils.py +0 -0
  32. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/string_utils.py +0 -0
  33. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/styles.py +0 -0
  34. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/types.py +0 -0
  35. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2/utils.py +0 -0
  36. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2.egg-info/SOURCES.txt +0 -0
  37. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2.egg-info/dependency_links.txt +0 -0
  38. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2.egg-info/requires.txt +0 -0
  39. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2.egg-info/top_level.txt +0 -0
  40. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/cmd2.png +0 -0
  41. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/codecov.yml +0 -0
  42. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/argparse_completer.md +0 -0
  43. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/argparse_utils.md +0 -0
  44. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/clipboard.md +0 -0
  45. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/cmd.md +0 -0
  46. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/colors.md +0 -0
  47. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/command_set.md +0 -0
  48. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/completion.md +0 -0
  49. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/constants.md +0 -0
  50. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/decorators.md +0 -0
  51. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/exceptions.md +0 -0
  52. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/history.md +0 -0
  53. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/index.md +0 -0
  54. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/parsing.md +0 -0
  55. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/plugin.md +0 -0
  56. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/pt_utils.md +0 -0
  57. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/py_bridge.md +0 -0
  58. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/rich_utils.md +0 -0
  59. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/string_utils.md +0 -0
  60. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/styles.md +0 -0
  61. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/api/utils.md +0 -0
  62. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/doc_conventions.md +0 -0
  63. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/examples/alternate_event_loops.md +0 -0
  64. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/examples/examples.md +0 -0
  65. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/examples/getting_started.md +0 -0
  66. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/examples/index.md +0 -0
  67. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/argument_processing.md +0 -0
  68. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/async_commands.md +0 -0
  69. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/builtin_commands.md +0 -0
  70. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/clipboard.md +0 -0
  71. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/commands.md +0 -0
  72. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/completion.md +0 -0
  73. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/disable_commands.md +0 -0
  74. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/embedded_python_shells.md +0 -0
  75. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/generating_output.md +0 -0
  76. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/help.md +0 -0
  77. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/history.md +0 -0
  78. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/hooks.md +0 -0
  79. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/index.md +0 -0
  80. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/initialization.md +0 -0
  81. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/misc.md +0 -0
  82. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/modular_commands.md +0 -0
  83. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/multiline_commands.md +0 -0
  84. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/os.md +0 -0
  85. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/packaging.md +0 -0
  86. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/plugins.md +0 -0
  87. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/prompt.md +0 -0
  88. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/redirection.md +0 -0
  89. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/scripting.md +0 -0
  90. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/settings.md +0 -0
  91. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/shortcuts_aliases_macros.md +0 -0
  92. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/startup_commands.md +0 -0
  93. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/table_creation.md +0 -0
  94. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/features/theme.md +0 -0
  95. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/index.md +0 -0
  96. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/javascripts/readthedocs.js +0 -0
  97. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/migrating/incompatibilities.md +0 -0
  98. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/migrating/index.md +0 -0
  99. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/migrating/minimum.md +0 -0
  100. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/migrating/next_steps.md +0 -0
  101. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/migrating/why.md +0 -0
  102. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/mixins/index.md +0 -0
  103. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/mixins/mixin_template.md +0 -0
  104. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/overrides/main.html +0 -0
  105. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/overview/alternatives.md +0 -0
  106. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/overview/index.md +0 -0
  107. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/overview/installation.md +0 -0
  108. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/overview/integrating.md +0 -0
  109. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/overview/resources.md +0 -0
  110. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/stylesheets/cmd2.css +0 -0
  111. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/testing.md +0 -0
  112. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/docs/upgrades.md +0 -0
  113. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/.cmd2rc +0 -0
  114. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/README.md +0 -0
  115. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/argparse_completion.py +0 -0
  116. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/argparse_example.py +0 -0
  117. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/async_call.py +0 -0
  118. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/async_commands.py +0 -0
  119. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/async_printing.py +0 -0
  120. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/basic_completion.py +0 -0
  121. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/cmd_as_argument.py +0 -0
  122. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/color.py +0 -0
  123. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/command_sets.py +0 -0
  124. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/custom_parser.py +0 -0
  125. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/custom_types.py +0 -0
  126. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/default_categories.py +0 -0
  127. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/dynamic_commands.py +0 -0
  128. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/environment.py +0 -0
  129. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/event_loops.py +0 -0
  130. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/exit_code.py +0 -0
  131. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/getting_started.py +0 -0
  132. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/hello_cmd2.py +0 -0
  133. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/help_categories.py +0 -0
  134. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/hooks.py +0 -0
  135. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/migrating.py +0 -0
  136. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/mixin.py +0 -0
  137. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/modular_commands/__init__.py +0 -0
  138. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/modular_commands/commandset_basic.py +0 -0
  139. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/modular_commands/commandset_complex.py +0 -0
  140. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/modular_commands/commandset_custominit.py +0 -0
  141. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/modular_commandsets.py +0 -0
  142. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/paged_output.py +0 -0
  143. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/persistent_history.py +0 -0
  144. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/pretty_print.py +0 -0
  145. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/python_scripting.py +0 -0
  146. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/read_input.py +0 -0
  147. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/remove_builtin_commands.py +0 -0
  148. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/remove_settable.py +0 -0
  149. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/rich_tables.py +0 -0
  150. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/rich_theme.py +0 -0
  151. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/scripts/arg_printer.py +0 -0
  152. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/scripts/conditional.py +0 -0
  153. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/scripts/nested.txt +0 -0
  154. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/scripts/quit.txt +0 -0
  155. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/scripts/save_help_text.py +0 -0
  156. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/scripts/script.py +0 -0
  157. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/scripts/script.txt +0 -0
  158. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/tmux_launch.sh +0 -0
  159. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/tmux_split.sh +0 -0
  160. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/examples/unicode_commands.py +0 -0
  161. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/mkdocs.yml +0 -0
  162. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/package.json +0 -0
  163. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/pyproject.toml +0 -0
  164. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/ruff.toml +0 -0
  165. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/scripts/validate_tag.py +0 -0
  166. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/setup.cfg +0 -0
  167. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/.cmd2rc +0 -0
  168. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/__init__.py +0 -0
  169. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/conftest.py +0 -0
  170. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/pyscript/echo.py +0 -0
  171. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/pyscript/environment.py +0 -0
  172. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/pyscript/help.py +0 -0
  173. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/pyscript/py_locals.py +0 -0
  174. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/pyscript/pyscript_dir.py +0 -0
  175. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/pyscript/raises_exception.py +0 -0
  176. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/pyscript/recursive.py +0 -0
  177. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/pyscript/self_in_py.py +0 -0
  178. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/pyscript/stdout_capture.py +0 -0
  179. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/pyscript/stop.py +0 -0
  180. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/relative_multiple.txt +0 -0
  181. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/script.py +0 -0
  182. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/script.txt +0 -0
  183. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/scripts/binary.bin +0 -0
  184. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/scripts/empty.txt +0 -0
  185. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/scripts/help.txt +0 -0
  186. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/scripts/nested.txt +0 -0
  187. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/scripts/one_down.txt +0 -0
  188. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/scripts/postcmds.txt +0 -0
  189. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/scripts/precmds.txt +0 -0
  190. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/scripts/utf8.txt +0 -0
  191. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_argparse.py +0 -0
  192. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_argparse_completer.py +0 -0
  193. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_argparse_subcommands.py +0 -0
  194. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_argparse_utils.py +0 -0
  195. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_categories.py +0 -0
  196. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_cmd2.py +0 -0
  197. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_commandset.py +0 -0
  198. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_dynamic_complete_style.py +0 -0
  199. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_future_annotations.py +0 -0
  200. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_history.py +0 -0
  201. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_parsing.py +0 -0
  202. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_plugin.py +0 -0
  203. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_pt_utils.py +0 -0
  204. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_py_completion.py +0 -0
  205. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_rich_utils.py +0 -0
  206. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_run_pyscript.py +0 -0
  207. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_string_utils.py +0 -0
  208. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_utils.py +0 -0
  209. {cmd2-4.0.0b3 → cmd2-4.0.0b4}/tests/test_utils_defining_class.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cmd2
3
- Version: 4.0.0b3
3
+ Version: 4.0.0b4
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
@@ -31,6 +31,15 @@ from rich.protocol import is_renderable
31
31
  from . import rich_utils as ru
32
32
 
33
33
 
34
+ class _UnsetStr(str):
35
+ """Internal sentinel to distinguish between an unset and an explicit empty string."""
36
+
37
+ __slots__ = ()
38
+
39
+
40
+ _UNSET_STR = _UnsetStr("")
41
+
42
+
34
43
  @dataclass(frozen=True, slots=True, kw_only=True)
35
44
  class CompletionItem:
36
45
  """A single completion result."""
@@ -39,17 +48,20 @@ class CompletionItem:
39
48
  # control sequences (like ^J or ^I) in the completion menu.
40
49
  _CONTROL_WHITESPACE_RE = re.compile(r"\r\n|[\n\r\t\f\v]")
41
50
 
42
- # The underlying object this completion represents (e.g., str, int, Path).
43
- # This is used to support argparse choices validation.
51
+ # The core object this completion represents (e.g., str, int, Path).
52
+ # This serves as the default source for the completion string and is used
53
+ # to support object-based validation when used in argparse choices.
44
54
  value: Any = field(kw_only=False)
45
55
 
46
- # The actual string that will be inserted into the command line.
47
- # If not provided, it defaults to str(value).
48
- text: str = ""
56
+ # The actual completion string. If not provided, defaults to str(value).
57
+ # This can be used to provide a human-friendly alias for complex objects in
58
+ # an argparse choices list (requires a matching 'type' converter for validation).
59
+ text: str = _UNSET_STR
49
60
 
50
61
  # Optional string for displaying the completion differently in the completion menu.
51
62
  # This can contain ANSI style sequences. A plain version is stored in display_plain.
52
- display: str = ""
63
+ # If not provided, defaults to the (possibly computed) value of 'text'.
64
+ display: str = _UNSET_STR
53
65
 
54
66
  # Optional meta information about completion which displays in the completion menu.
55
67
  # This can contain ANSI style sequences. A plain version is stored in display_meta_plain.
@@ -60,9 +72,8 @@ class CompletionItem:
60
72
  table_data: Sequence[Any] = field(default_factory=tuple)
61
73
 
62
74
  # Plain text versions of display fields (stripped of ANSI) for sorting/filtering.
63
- # These are set in __post_init__().
64
- display_plain: str = field(init=False)
65
- display_meta_plain: str = field(init=False)
75
+ display_plain: str = field(default="", init=False)
76
+ display_meta_plain: str = field(default="", init=False)
66
77
 
67
78
  @classmethod
68
79
  def _clean_display(cls, val: str) -> str:
@@ -77,13 +88,21 @@ class CompletionItem:
77
88
  return cls._CONTROL_WHITESPACE_RE.sub(" ", val)
78
89
 
79
90
  def __post_init__(self) -> None:
80
- """Finalize the object after initialization."""
81
- # Derive text from value if it wasn't explicitly provided
82
- if not self.text:
91
+ """Finalize the object after initialization.
92
+
93
+ By using the sentinel pattern to distinguish between a field that was never
94
+ set and one explicitly blanked out, this handles the two-stage lifecycle:
95
+
96
+ 1. Initial creation (usually by a developer-provided choices_provider or completer).
97
+ 2. Post-processing by cmd2 via dataclasses.replace(), which may modify fields or
98
+ explicitly set them to empty strings.
99
+ """
100
+ # If the completion string was not provided, derive it from value.
101
+ if isinstance(self.text, _UnsetStr):
83
102
  object.__setattr__(self, "text", str(self.value))
84
103
 
85
- # Ensure display is never blank.
86
- if not self.display:
104
+ # If the display string was not provided, use text.
105
+ if isinstance(self.display, _UnsetStr):
87
106
  object.__setattr__(self, "display", self.text)
88
107
 
89
108
  # Clean display and display_meta
@@ -163,7 +182,7 @@ class CompletionResultsBase:
163
182
 
164
183
  # True if every item in this collection has a numeric display string.
165
184
  # Used for sorting and alignment.
166
- numeric_display: bool = field(init=False)
185
+ numeric_display: bool = field(default=False, init=False)
167
186
 
168
187
  def __post_init__(self) -> None:
169
188
  """Finalize the object after initialization."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cmd2
3
- Version: 4.0.0b3
3
+ Version: 4.0.0b4
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
@@ -4,6 +4,7 @@ These are primarily tests related to prompt-toolkit completer functions which ha
4
4
  file system paths, and shell commands.
5
5
  """
6
6
 
7
+ import argparse
7
8
  import dataclasses
8
9
  import enum
9
10
  import os
@@ -15,6 +16,7 @@ import pytest
15
16
 
16
17
  import cmd2
17
18
  from cmd2 import (
19
+ Choices,
18
20
  CompletionItem,
19
21
  Completions,
20
22
  utils,
@@ -1300,3 +1302,140 @@ def test_subcommand_tab_completion_with_no_completer_scu(scu_app) -> None:
1300
1302
 
1301
1303
  completions = scu_app.complete(text, line, begidx, endidx)
1302
1304
  assert not completions
1305
+
1306
+
1307
+ def test_set_completion_item_text() -> None:
1308
+ """Test setting CompletionItem.text and how it affects CompletionItem.display."""
1309
+ value = 5
1310
+
1311
+ # Don't provide text
1312
+ item = CompletionItem(value=value)
1313
+ assert item.text == str(value)
1314
+
1315
+ # Provide text
1316
+ item = CompletionItem(value=value, text="my_text")
1317
+ assert item.text == "my_text"
1318
+
1319
+ # Provide blank text
1320
+ item = CompletionItem(value=value, text="")
1321
+ assert item.text == ""
1322
+
1323
+
1324
+ def test_replace_completion_item_text() -> None:
1325
+ """Test replacing the value of CompletionItem.text"""
1326
+ value = 5
1327
+
1328
+ # Replace text value
1329
+ item = CompletionItem(value=value, text="my_text")
1330
+ updated_item = dataclasses.replace(item, text="new_text")
1331
+ assert item.text == "my_text"
1332
+ assert item.display == "my_text"
1333
+
1334
+ # Text should be updated and display should be the same
1335
+ assert updated_item.text == "new_text"
1336
+ assert updated_item.display == "my_text"
1337
+
1338
+ # Replace text value with blank
1339
+ item = CompletionItem(value=value, text="my_text")
1340
+ updated_item = dataclasses.replace(item, text="")
1341
+ assert item.text == "my_text"
1342
+ assert item.display == "my_text"
1343
+
1344
+ # Text should be updated and display should be the same
1345
+ assert updated_item.text == ""
1346
+ assert updated_item.display == "my_text"
1347
+
1348
+
1349
+ def test_set_completion_item_display() -> None:
1350
+ """Test setting CompletionItem.display and how it is affected by CompletionItem.text."""
1351
+ value = 5
1352
+
1353
+ # Don't provide text or display
1354
+ value = 5
1355
+ item = CompletionItem(value=value)
1356
+ assert item.text == str(value)
1357
+ assert item.display == item.text
1358
+
1359
+ # Don't provide display but provide text
1360
+ item = CompletionItem(value=value, text="my_text")
1361
+ assert item.text == "my_text"
1362
+ assert item.display == item.text
1363
+
1364
+ # Provide display
1365
+ item = CompletionItem(value=value, text="my_text", display="my_display")
1366
+ assert item.text == "my_text"
1367
+ assert item.display == "my_display"
1368
+
1369
+ # Provide blank display
1370
+ item = CompletionItem(value=value, text="my_text", display="")
1371
+ assert item.text == "my_text"
1372
+ assert item.display == ""
1373
+
1374
+
1375
+ def test_replace_completion_item_display() -> None:
1376
+ """Test replacing the value of CompletionItem.display"""
1377
+ value = 5
1378
+
1379
+ # Replace display value
1380
+ item = CompletionItem(value=value, display="my_display")
1381
+ updated_item = dataclasses.replace(item, display="new_display")
1382
+
1383
+ assert item.display == "my_display"
1384
+ assert updated_item.display == "new_display"
1385
+
1386
+ # Replace display value with blank
1387
+ item = CompletionItem(value=value, display="my_display")
1388
+ updated_item = dataclasses.replace(item, display="")
1389
+
1390
+ assert item.display == "my_display"
1391
+ assert updated_item.display == ""
1392
+
1393
+
1394
+ def test_full_prefix_removal() -> None:
1395
+ """Verify that Cmd._perform_completion() can clear item.text when
1396
+ text_to_remove matches item.text exactly. This occurs when completing
1397
+ a nested quoted string where the command line already contains the
1398
+ full unquoted content of the completion match.
1399
+ """
1400
+
1401
+ class TestApp(cmd2.Cmd):
1402
+ def get_choices(self) -> Choices:
1403
+ """Return choices."""
1404
+ choices = [
1405
+ "'This is a single-quoted item'",
1406
+ '"This is a double-quoted item"',
1407
+ ]
1408
+ return cmd2.Choices.from_values(choices)
1409
+
1410
+ parser = cmd2.Cmd2ArgumentParser()
1411
+ parser.add_argument("arg", choices_provider=get_choices)
1412
+
1413
+ @cmd2.with_argparser(parser)
1414
+ def do_command(self, args: argparse.Namespace) -> None:
1415
+ """Test stuff."""
1416
+
1417
+ # Test single-quoted item
1418
+ text = ""
1419
+ line = "command \"'This is a single-quoted item'"
1420
+ endidx = len(line)
1421
+ begidx = endidx
1422
+
1423
+ app = TestApp()
1424
+ completions = app.complete(text, line, begidx, endidx)
1425
+ assert len(completions) == 1
1426
+
1427
+ item = completions[0]
1428
+ assert item.text == ""
1429
+
1430
+ # Test double-quoted item
1431
+ text = ""
1432
+ line = 'command \'"This is a double-quoted item"'
1433
+ endidx = len(line)
1434
+ begidx = endidx
1435
+
1436
+ app = TestApp()
1437
+ completions = app.complete(text, line, begidx, endidx)
1438
+ assert len(completions) == 1
1439
+
1440
+ item = completions[0]
1441
+ assert item.text == ""
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes