cmd2 2.6.0__tar.gz → 2.6.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.
- {cmd2-2.6.0 → cmd2-2.6.1}/CHANGELOG.md +5 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/PKG-INFO +1 -1
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/cmd2.py +39 -33
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/utils.py +30 -23
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2.egg-info/PKG-INFO +1 -1
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2.egg-info/SOURCES.txt +1 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/pyproject.toml +15 -37
- cmd2-2.6.1/tests/test_future_annotations.py +22 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_utils.py +41 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/.pre-commit-config.yaml +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/.prettierignore +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/.prettierrc +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/.readthedocs.yaml +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/LICENSE +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/MANIFEST.in +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/Makefile +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/Pipfile +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/README.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/__init__.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/ansi.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/argparse_completer.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/argparse_custom.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/clipboard.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/command_definition.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/constants.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/decorators.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/exceptions.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/history.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/parsing.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/plugin.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/py.typed +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/py_bridge.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/rl_utils.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/table_creator.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2/transcript.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2.egg-info/dependency_links.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2.egg-info/requires.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2.egg-info/top_level.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/cmd2.png +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/codecov.yml +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/ansi.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/argparse_completer.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/argparse_custom.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/cmd.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/command_definition.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/constants.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/decorators.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/exceptions.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/history.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/index.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/parsing.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/plugin.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/py_bridge.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/table_creator.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/api/utils.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/doc_conventions.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/examples/alternate_event_loops.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/examples/examples.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/examples/first_app.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/examples/index.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/argument_processing.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/builtin_commands.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/clipboard.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/commands.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/completion.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/disable_commands.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/embedded_python_shells.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/generating_output.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/help.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/history.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/hooks.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/index.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/initialization.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/misc.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/modular_commands.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/multiline_commands.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/os.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/packaging.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/plugins.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/prompt.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/redirection.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/scripting.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/settings.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/shortcuts_aliases_macros.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/startup_commands.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/table_creation.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/features/transcripts.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/index.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/javascripts/readthedocs.js +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/migrating/incompatibilities.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/migrating/index.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/migrating/minimum.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/migrating/next_steps.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/migrating/why.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/overrides/main.html +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/overview/alternatives.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/overview/index.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/overview/installation.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/overview/integrating.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/overview/resources.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/plugins/external_test.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/plugins/index.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/requirements.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/stylesheets/readthedocs.css +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/docs/testing.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.cmd2rc +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/@plugins_snapshot.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/_ast.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/_ast.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/_codecs.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/_codecs.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/_collections_abc.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/_collections_abc.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/_typeshed/__init__.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/_typeshed/__init__.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/_typeshed/importlib.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/_typeshed/importlib.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/abc.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/abc.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/argparse.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/argparse.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/builtins.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/builtins.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/codecs.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/codecs.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/collections/__init__.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/collections/__init__.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/collections/abc.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/collections/abc.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/contextlib.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/contextlib.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/dataclasses.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/dataclasses.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/__init__.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/__init__.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/_policybase.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/_policybase.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/charset.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/charset.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/contentmanager.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/contentmanager.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/errors.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/errors.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/header.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/header.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/message.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/message.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/policy.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/email/policy.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/enum.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/enum.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/genericpath.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/genericpath.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/__init__.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/__init__.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/_abc.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/_abc.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/abc.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/abc.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/machinery.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/machinery.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/metadata/__init__.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/metadata/__init__.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/metadata/_meta.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/metadata/_meta.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/readers.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/readers.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/resources/__init__.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/resources/__init__.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/resources/abc.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/importlib/resources/abc.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/io.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/io.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/os/__init__.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/os/__init__.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/os/path.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/os/path.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/pathlib.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/pathlib.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/posixpath.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/posixpath.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/re.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/re.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/resource.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/resource.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/sre_compile.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/sre_compile.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/sre_constants.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/sre_constants.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/sre_parse.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/sre_parse.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/subprocess.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/subprocess.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/sys/__init__.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/sys/__init__.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/sys/_monitoring.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/sys/_monitoring.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/types.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/types.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/typing.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/typing.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/typing_extensions.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/typing_extensions.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/zipfile/__init__.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/zipfile/__init__.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/zipfile/_path.data.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/3.12/zipfile/_path.meta.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/.mypy_cache/CACHEDIR.TAG +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/README.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/alias_startup.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/arg_decorators.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/arg_print.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/argparse_completion.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/async_printing.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/basic.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/basic_completion.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/cmd2_history.dat +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/cmd_as_argument.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/colors.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/custom_parser.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/decorator_example.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/default_categories.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/dynamic_commands.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/environment.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/event_loops.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/example.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/exit_code.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/first_app.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/hello_cmd2.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/help_categories.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/hooks.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/initialization.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/migrating.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/modular_commands/__init__.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/modular_commands/commandset_basic.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/modular_commands/commandset_complex.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/modular_commands/commandset_custominit.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/modular_commands_basic.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/modular_commands_dynamic.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/modular_commands_main.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/modular_subcommands.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/override_parser.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/paged_output.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/persistent_history.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/pirate.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/pretty_print.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/python_scripting.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/read_input.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/remove_builtin_commands.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/remove_settable.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/scripts/arg_printer.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/scripts/conditional.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/scripts/nested.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/scripts/quit.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/scripts/save_help_text.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/scripts/script.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/scripts/script.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/subcommands.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/table_creation.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/tmux_launch.sh +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/tmux_split.sh +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/transcripts/exampleSession.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/transcripts/pirate.transcript +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/transcripts/quit.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/transcripts/transcript_regex.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/examples/unicode_commands.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/mkdocs.yml +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/package.json +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/README.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/CHANGELOG.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/README.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/build-pyenvs.sh +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/cmd2_ext_test/__init__.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/cmd2_ext_test/cmd2_ext_test.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/cmd2_ext_test/py.typed +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/cmd2_ext_test/pylintrc +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/examples/example.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/noxfile.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/pyproject.toml +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/setup.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/tasks.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/tests/__init__.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/tests/pylintrc +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/ext_test/tests/test_ext_test.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/tasks.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/CHANGELOG.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/LICENSE +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/README.md +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/build-pyenvs.sh +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/cmd2_myplugin/__init__.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/cmd2_myplugin/myplugin.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/cmd2_myplugin/pylintrc +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/examples/example.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/noxfile.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/setup.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/tasks.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/tests/__init__.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/tests/pylintrc +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/plugins/template/tests/test_myplugin.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/readme_files/shout_out.csv +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/readme_files/shoutout.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/setup.cfg +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tasks.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/.cmd2rc +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/__init__.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/conftest.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/pyscript/echo.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/pyscript/environment.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/pyscript/help.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/pyscript/py_locals.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/pyscript/pyscript_dir.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/pyscript/raises_exception.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/pyscript/recursive.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/pyscript/self_in_py.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/pyscript/stdout_capture.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/pyscript/stop.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/relative_multiple.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/script.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/script.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/scripts/binary.bin +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/scripts/empty.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/scripts/help.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/scripts/nested.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/scripts/one_down.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/scripts/postcmds.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/scripts/precmds.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/scripts/utf8.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_ansi.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_argparse.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_argparse_completer.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_argparse_custom.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_cmd2.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_completion.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_history.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_parsing.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_plugin.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_run_pyscript.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_table_creator.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_transcript.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/test_utils_defining_class.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/bol_eol.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/characterclass.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/dotstar.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/extension_notation.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/failure.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/from_cmdloop.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/multiline_no_regex.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/multiline_regex.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/no_output.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/no_output_last.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/regex_set.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/singleslash.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/slashes_escaped.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/slashslash.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/spaces.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests/transcripts/word_boundaries.txt +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests_isolated/__init__.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests_isolated/test_commandset/__init__.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests_isolated/test_commandset/conftest.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests_isolated/test_commandset/test_argparse_subcommands.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests_isolated/test_commandset/test_categories.py +0 -0
- {cmd2-2.6.0 → cmd2-2.6.1}/tests_isolated/test_commandset/test_commandset.py +0 -0
@@ -144,6 +144,7 @@ from .table_creator import (
|
|
144
144
|
from .utils import (
|
145
145
|
Settable,
|
146
146
|
get_defining_class,
|
147
|
+
get_types,
|
147
148
|
strip_doc_annotations,
|
148
149
|
suggest_similar,
|
149
150
|
)
|
@@ -3597,8 +3598,8 @@ class Cmd(cmd.Cmd):
|
|
3597
3598
|
max_arg_num = 0
|
3598
3599
|
arg_nums = set()
|
3599
3600
|
|
3600
|
-
|
3601
|
-
|
3601
|
+
try:
|
3602
|
+
while True:
|
3602
3603
|
cur_match = normal_matches.__next__()
|
3603
3604
|
|
3604
3605
|
# Get the number string between the braces
|
@@ -3612,9 +3613,8 @@ class Cmd(cmd.Cmd):
|
|
3612
3613
|
max_arg_num = max(max_arg_num, cur_num)
|
3613
3614
|
|
3614
3615
|
arg_list.append(MacroArg(start_index=cur_match.start(), number_str=cur_num_str, is_escaped=False))
|
3615
|
-
|
3616
|
-
|
3617
|
-
break
|
3616
|
+
except StopIteration:
|
3617
|
+
pass
|
3618
3618
|
|
3619
3619
|
# Make sure the argument numbers are continuous
|
3620
3620
|
if len(arg_nums) != max_arg_num:
|
@@ -3624,16 +3624,16 @@ class Cmd(cmd.Cmd):
|
|
3624
3624
|
# Find all escaped arguments
|
3625
3625
|
escaped_matches = re.finditer(MacroArg.macro_escaped_arg_pattern, value)
|
3626
3626
|
|
3627
|
-
|
3628
|
-
|
3627
|
+
try:
|
3628
|
+
while True:
|
3629
3629
|
cur_match = escaped_matches.__next__()
|
3630
3630
|
|
3631
3631
|
# Get the number string between the braces
|
3632
3632
|
cur_num_str = re.findall(MacroArg.digit_pattern, cur_match.group())[0]
|
3633
3633
|
|
3634
3634
|
arg_list.append(MacroArg(start_index=cur_match.start(), number_str=cur_num_str, is_escaped=True))
|
3635
|
-
|
3636
|
-
|
3635
|
+
except StopIteration:
|
3636
|
+
pass
|
3637
3637
|
|
3638
3638
|
# Set the macro
|
3639
3639
|
result = "overwritten" if args.name in self.macros else "created"
|
@@ -5545,10 +5545,10 @@ class Cmd(cmd.Cmd):
|
|
5545
5545
|
def _validate_prepostloop_callable(cls, func: Callable[[], None]) -> None:
|
5546
5546
|
"""Check parameter and return types for preloop and postloop hooks."""
|
5547
5547
|
cls._validate_callable_param_count(func, 0)
|
5548
|
-
# make sure there is no return
|
5549
|
-
|
5550
|
-
if
|
5551
|
-
raise TypeError(f"{func.__name__} must
|
5548
|
+
# make sure there is no return annotation or the return is specified as None
|
5549
|
+
_, ret_ann = get_types(func)
|
5550
|
+
if ret_ann is not None:
|
5551
|
+
raise TypeError(f"{func.__name__} must have a return type of 'None', got: {ret_ann}")
|
5552
5552
|
|
5553
5553
|
def register_preloop_hook(self, func: Callable[[], None]) -> None:
|
5554
5554
|
"""Register a function to be called at the beginning of the command loop."""
|
@@ -5564,11 +5564,13 @@ class Cmd(cmd.Cmd):
|
|
5564
5564
|
def _validate_postparsing_callable(cls, func: Callable[[plugin.PostparsingData], plugin.PostparsingData]) -> None:
|
5565
5565
|
"""Check parameter and return types for postparsing hooks."""
|
5566
5566
|
cls._validate_callable_param_count(cast(Callable[..., Any], func), 1)
|
5567
|
-
|
5568
|
-
|
5569
|
-
|
5567
|
+
type_hints, ret_ann = get_types(func)
|
5568
|
+
if not type_hints:
|
5569
|
+
raise TypeError(f"{func.__name__} parameter is missing a type hint, expected: 'cmd2.plugin.PostparsingData'")
|
5570
|
+
par_ann = next(iter(type_hints.values()))
|
5571
|
+
if par_ann != plugin.PostparsingData:
|
5570
5572
|
raise TypeError(f"{func.__name__} must have one parameter declared with type 'cmd2.plugin.PostparsingData'")
|
5571
|
-
if
|
5573
|
+
if ret_ann != plugin.PostparsingData:
|
5572
5574
|
raise TypeError(f"{func.__name__} must declare return a return type of 'cmd2.plugin.PostparsingData'")
|
5573
5575
|
|
5574
5576
|
def register_postparsing_hook(self, func: Callable[[plugin.PostparsingData], plugin.PostparsingData]) -> None:
|
@@ -5583,21 +5585,21 @@ class Cmd(cmd.Cmd):
|
|
5583
5585
|
cls, func: Callable[[CommandDataType], CommandDataType], data_type: type[CommandDataType]
|
5584
5586
|
) -> None:
|
5585
5587
|
"""Check parameter and return types for pre and post command hooks."""
|
5586
|
-
signature = inspect.signature(func)
|
5587
5588
|
# validate that the callable has the right number of parameters
|
5588
5589
|
cls._validate_callable_param_count(cast(Callable[..., Any], func), 1)
|
5590
|
+
|
5591
|
+
type_hints, ret_ann = get_types(func)
|
5592
|
+
if not type_hints:
|
5593
|
+
raise TypeError(f"{func.__name__} parameter is missing a type hint, expected: {data_type}")
|
5594
|
+
param_name, par_ann = next(iter(type_hints.items()))
|
5589
5595
|
# validate the parameter has the right annotation
|
5590
|
-
|
5591
|
-
|
5592
|
-
if param.annotation != data_type:
|
5593
|
-
raise TypeError(f'argument 1 of {func.__name__} has incompatible type {param.annotation}, expected {data_type}')
|
5596
|
+
if par_ann != data_type:
|
5597
|
+
raise TypeError(f'argument 1 of {func.__name__} has incompatible type {par_ann}, expected {data_type}')
|
5594
5598
|
# validate the return value has the right annotation
|
5595
|
-
if
|
5599
|
+
if ret_ann is None:
|
5596
5600
|
raise TypeError(f'{func.__name__} does not have a declared return type, expected {data_type}')
|
5597
|
-
if
|
5598
|
-
raise TypeError(
|
5599
|
-
f'{func.__name__} has incompatible return type {signature.return_annotation}, expected {data_type}'
|
5600
|
-
)
|
5601
|
+
if ret_ann != data_type:
|
5602
|
+
raise TypeError(f'{func.__name__} has incompatible return type {ret_ann}, expected {data_type}')
|
5601
5603
|
|
5602
5604
|
def register_precmd_hook(self, func: Callable[[plugin.PrecommandData], plugin.PrecommandData]) -> None:
|
5603
5605
|
"""Register a hook to be called before the command function."""
|
@@ -5615,12 +5617,16 @@ class Cmd(cmd.Cmd):
|
|
5615
5617
|
) -> None:
|
5616
5618
|
"""Check parameter and return types for command finalization hooks."""
|
5617
5619
|
cls._validate_callable_param_count(func, 1)
|
5618
|
-
|
5619
|
-
|
5620
|
-
|
5621
|
-
|
5622
|
-
if
|
5623
|
-
raise TypeError(
|
5620
|
+
type_hints, ret_ann = get_types(func)
|
5621
|
+
if not type_hints:
|
5622
|
+
raise TypeError(f"{func.__name__} parameter is missing a type hint, expected: {plugin.CommandFinalizationData}")
|
5623
|
+
_, par_ann = next(iter(type_hints.items()))
|
5624
|
+
if par_ann != plugin.CommandFinalizationData:
|
5625
|
+
raise TypeError(
|
5626
|
+
f"{func.__name__} must have one parameter declared with type {plugin.CommandFinalizationData}, got: {par_ann}"
|
5627
|
+
)
|
5628
|
+
if ret_ann != plugin.CommandFinalizationData:
|
5629
|
+
raise TypeError(f"{func.__name__} must declare return a return type of {plugin.CommandFinalizationData}")
|
5624
5630
|
|
5625
5631
|
def register_cmdfinalization_hook(
|
5626
5632
|
self, func: Callable[[plugin.CommandFinalizationData], plugin.CommandFinalizationData]
|
@@ -14,29 +14,12 @@ import sys
|
|
14
14
|
import threading
|
15
15
|
import unicodedata
|
16
16
|
from collections.abc import Callable, Iterable
|
17
|
-
from difflib import
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
from typing import (
|
24
|
-
TYPE_CHECKING,
|
25
|
-
Any,
|
26
|
-
Optional,
|
27
|
-
TextIO,
|
28
|
-
TypeVar,
|
29
|
-
Union,
|
30
|
-
cast,
|
31
|
-
)
|
32
|
-
|
33
|
-
from . import (
|
34
|
-
constants,
|
35
|
-
)
|
36
|
-
from .argparse_custom import (
|
37
|
-
ChoicesProviderFunc,
|
38
|
-
CompleterFunc,
|
39
|
-
)
|
17
|
+
from difflib import SequenceMatcher
|
18
|
+
from enum import Enum
|
19
|
+
from typing import TYPE_CHECKING, Any, Optional, TextIO, TypeVar, Union, cast, get_type_hints
|
20
|
+
|
21
|
+
from . import constants
|
22
|
+
from .argparse_custom import ChoicesProviderFunc, CompleterFunc
|
40
23
|
|
41
24
|
if TYPE_CHECKING: # pragma: no cover
|
42
25
|
import cmd2 # noqa: F401
|
@@ -1261,3 +1244,27 @@ def suggest_similar(
|
|
1261
1244
|
best_simil = simil
|
1262
1245
|
proposed_command = each
|
1263
1246
|
return proposed_command
|
1247
|
+
|
1248
|
+
|
1249
|
+
def get_types(func_or_method: Callable[..., Any]) -> tuple[dict[str, Any], Any]:
|
1250
|
+
"""Use typing.get_type_hints() to extract type hints for parameters and return value.
|
1251
|
+
|
1252
|
+
This exists because the inspect module doesn't have a safe way of doing this that works
|
1253
|
+
both with and without importing annotations from __future__ until Python 3.10.
|
1254
|
+
|
1255
|
+
TODO: Once cmd2 only supports Python 3.10+, change to use inspect.get_annotations(eval_str=True)
|
1256
|
+
|
1257
|
+
:param func_or_method: Function or method to return the type hints for
|
1258
|
+
:return tuple with first element being dictionary mapping param names to type hints
|
1259
|
+
and second element being return type hint, unspecified, returns None
|
1260
|
+
"""
|
1261
|
+
try:
|
1262
|
+
type_hints = get_type_hints(func_or_method) # Get dictionary of type hints
|
1263
|
+
except TypeError as exc:
|
1264
|
+
raise ValueError("Argument passed to get_types should be a function or method") from exc
|
1265
|
+
ret_ann = type_hints.pop('return', None) # Pop off the return annotation if it exists
|
1266
|
+
if inspect.ismethod(func_or_method):
|
1267
|
+
type_hints.pop('self', None) # Pop off `self` hint for methods
|
1268
|
+
if ret_ann is type(None):
|
1269
|
+
ret_ann = None # Simplify logic to just return None instead of NoneType
|
1270
|
+
return type_hints, ret_ann
|
@@ -147,9 +147,7 @@ exclude = [
|
|
147
147
|
# Same as Black.
|
148
148
|
line-length = 127
|
149
149
|
indent-width = 4
|
150
|
-
|
151
|
-
# Assume Python 3.13
|
152
|
-
target-version = "py313"
|
150
|
+
target-version = "py39" # Minimum supported version of Python
|
153
151
|
output-format = "full"
|
154
152
|
|
155
153
|
[tool.ruff.lint]
|
@@ -235,6 +233,7 @@ ignore = [
|
|
235
233
|
"E111", # Conflicts with ruff format
|
236
234
|
"E114", # Conflicts with ruff format
|
237
235
|
"E117", # Conflicts with ruff format
|
236
|
+
"FA100", # Adding from __future__ import annotations screws up cmd2 because of how use inspect to validate type annotations at runtime
|
238
237
|
"ISC002", # Conflicts with ruff format
|
239
238
|
"Q000", # Conflicts with ruff format
|
240
239
|
"Q001", # Conflicts with ruff format
|
@@ -258,36 +257,26 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
|
258
257
|
|
259
258
|
mccabe.max-complexity = 49
|
260
259
|
|
261
|
-
per-file-ignores
|
262
|
-
|
263
|
-
|
264
|
-
]
|
260
|
+
[tool.ruff.lint.per-file-ignores]
|
261
|
+
# Module level import not at top of file and unused import
|
262
|
+
"cmd2/__init__.py" = ["E402", "F401"]
|
265
263
|
|
266
|
-
|
267
|
-
|
268
|
-
]
|
264
|
+
# Do not call setattr with constant attribute value
|
265
|
+
"cmd2/argparse_custom.py" = ["B010"]
|
269
266
|
|
270
|
-
|
267
|
+
# Ignore various varnings in examples/ directory
|
268
|
+
"examples/*.py" = [
|
271
269
|
"ANN", # Ignore all type annotation rules in examples folder
|
272
270
|
"D", # Ignore all pydocstyle rules in examples folder
|
273
271
|
"INP001", # Module is part of an implicit namespace
|
274
272
|
"PLW2901", # loop variable overwritten inside loop
|
275
273
|
"S", # Ignore all Security rules in examples folder
|
276
274
|
]
|
275
|
+
"examples/scripts/*.py" = ["F821"] # Undefined name `app`
|
276
|
+
"plugins/*.py" = ["INP001"] # Module is part of an implicit namespace
|
277
277
|
|
278
|
-
|
279
|
-
|
280
|
-
]
|
281
|
-
|
282
|
-
per-file-ignores."plugins/*.py" = [
|
283
|
-
"ANN", # Ignore all type annotation rules in test folders
|
284
|
-
"D", # Ignore all pydocstyle rules in test folders
|
285
|
-
"INP001", # Module is part of an implicit namespace
|
286
|
-
"S", # Ignore all Security rules in test folders
|
287
|
-
"SLF", # Ignore all warnings about private or protected member access in test folders
|
288
|
-
]
|
289
|
-
|
290
|
-
per-file-ignores."tests/*.py" = [
|
278
|
+
# Ingore various rulesets in test and plugins directories
|
279
|
+
"{plugins,tests,tests_isolated}/*.py" = [
|
291
280
|
"ANN", # Ignore all type annotation rules in test folders
|
292
281
|
"ARG", # Ignore all unused argument warnings in test folders
|
293
282
|
"D", # Ignore all pydocstyle rules in test folders
|
@@ -295,19 +284,8 @@ per-file-ignores."tests/*.py" = [
|
|
295
284
|
"S", # Ignore all Security rules in test folders
|
296
285
|
"SLF", # Ignore all warnings about private or protected member access in test folders
|
297
286
|
]
|
298
|
-
|
299
|
-
|
300
|
-
"F821", # Undefined name `app`
|
301
|
-
"INP001", # Module is part of an implicit namespace
|
302
|
-
]
|
303
|
-
|
304
|
-
per-file-ignores."tests_isolated/*.py" = [
|
305
|
-
"ANN", # Ignore all type annotation rules in test folders
|
306
|
-
"ARG", # Ignore all unused argument warnings in test folders
|
307
|
-
"D", # Ignore all pydocstyle rules in test folders
|
308
|
-
"S", # Ignore all Security rules in test folders
|
309
|
-
"SLF", # Ignore all warnings about private or protected member access in test folders
|
310
|
-
]
|
287
|
+
# Undefined name `app` and module is part of an implicit namespace
|
288
|
+
"tests/pyscript/*.py" = ["F821", "INP001"]
|
311
289
|
|
312
290
|
[tool.ruff.format]
|
313
291
|
# Like Black, use double quotes for strings.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import cmd2
|
4
|
+
|
5
|
+
from .conftest import normalize, run_cmd
|
6
|
+
|
7
|
+
|
8
|
+
def test_hooks_work_with_future_annotations() -> None:
|
9
|
+
class HookApp(cmd2.Cmd):
|
10
|
+
def __init__(self, *args, **kwargs) -> None:
|
11
|
+
super().__init__(*args, **kwargs)
|
12
|
+
self.register_cmdfinalization_hook(self.hook)
|
13
|
+
|
14
|
+
def hook(self: cmd2.Cmd, data: cmd2.plugin.CommandFinalizationData) -> cmd2.plugin.CommandFinalizationData:
|
15
|
+
if self.in_script():
|
16
|
+
self.poutput("WE ARE IN SCRIPT")
|
17
|
+
return data
|
18
|
+
|
19
|
+
hook_app = HookApp()
|
20
|
+
out, err = run_cmd(hook_app, '')
|
21
|
+
expected = normalize('')
|
22
|
+
assert out == expected
|
@@ -892,3 +892,44 @@ def test_similarity_overwrite_function() -> None:
|
|
892
892
|
|
893
893
|
suggested_command = cu.suggest_similar("test", ["test"], similarity_function_to_use=custom_similarity_function)
|
894
894
|
assert suggested_command is None
|
895
|
+
|
896
|
+
|
897
|
+
def test_get_types_invalid_input() -> None:
|
898
|
+
x = 1
|
899
|
+
with pytest.raises(ValueError, match="Argument passed to get_types should be a function or method"):
|
900
|
+
cu.get_types(x)
|
901
|
+
|
902
|
+
|
903
|
+
def test_get_types_empty() -> None:
|
904
|
+
def a(b):
|
905
|
+
print(b)
|
906
|
+
|
907
|
+
param_ann, ret_ann = cu.get_types(a)
|
908
|
+
assert ret_ann is None
|
909
|
+
assert param_ann == {}
|
910
|
+
|
911
|
+
|
912
|
+
def test_get_types_non_empty() -> None:
|
913
|
+
def foo(x: int) -> str:
|
914
|
+
return f"{x * x}"
|
915
|
+
|
916
|
+
param_ann, ret_ann = cu.get_types(foo)
|
917
|
+
assert ret_ann is str
|
918
|
+
param_name, param_value = next(iter(param_ann.items()))
|
919
|
+
assert param_name == 'x'
|
920
|
+
assert param_value is int
|
921
|
+
|
922
|
+
|
923
|
+
def test_get_types_method() -> None:
|
924
|
+
class Foo:
|
925
|
+
def bar(self, x: bool) -> None:
|
926
|
+
print(x)
|
927
|
+
|
928
|
+
f = Foo()
|
929
|
+
|
930
|
+
param_ann, ret_ann = cu.get_types(f.bar)
|
931
|
+
assert ret_ann is None
|
932
|
+
assert len(param_ann) == 1
|
933
|
+
param_name, param_value = next(iter(param_ann.items()))
|
934
|
+
assert param_name == 'x'
|
935
|
+
assert param_value is bool
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|