diff --git a/CHANGELOG.md b/CHANGELOG.md
index c378f893..70b84bf8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.1 (TBD, 2020)
+* Bug Fixes
+    * Fixed issue where postcmd hooks were running after an `argparse` exception in a command.
+
 ## 1.0.0 (March 1, 2020)
 * Enhancements
     * The documentation at [cmd2.rftd.io](https://cmd2.readthedocs.io) received a major overhaul
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 4ab3df3f..44e02005 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -50,7 +50,7 @@ from . import utils
 from .argparse_custom import CompletionItem, DEFAULT_ARGUMENT_PARSER
 from .clipboard import can_clip, get_paste_buffer, write_to_paste_buffer
 from .decorators import with_argparser
-from .exceptions import EmbeddedConsoleExit, EmptyStatement
+from .exceptions import Cmd2ArgparseError, Cmd2ShlexError, EmbeddedConsoleExit, EmptyStatement
 from .history import History, HistoryItem
 from .parsing import StatementParser, Statement, Macro, MacroArg, shlex_split
 from .rl_utils import rl_type, RlType, rl_get_point, rl_set_prompt, vt100_support, rl_make_safe_prompt, rl_warning
@@ -1599,12 +1599,10 @@ class Cmd(cmd.Cmd):
         stop = False
         try:
             statement = self._input_line_to_statement(line)
-        except EmptyStatement:
+        except (EmptyStatement, Cmd2ShlexError) as ex:
+            if isinstance(ex, Cmd2ShlexError):
+                self.perror("Invalid syntax: {}".format(ex))
             return self._run_cmdfinalization_hooks(stop, None)
-        except ValueError as ex:
-            # If shlex.split failed on syntax, let user know what's going on
-            self.pexcept("Invalid syntax: {}".format(ex))
-            return stop
 
         # now that we have a statement, run it with all the hooks
         try:
@@ -1684,8 +1682,8 @@ class Cmd(cmd.Cmd):
                         # Stop saving command's stdout before command finalization hooks run
                         self.stdout.pause_storage = True
 
-        except EmptyStatement:
-            # don't do anything, but do allow command finalization hooks to run
+        except (Cmd2ArgparseError, EmptyStatement):
+            # Don't do anything, but do allow command finalization hooks to run
             pass
         except Exception as ex:
             self.pexcept(ex)
@@ -1744,6 +1742,8 @@ class Cmd(cmd.Cmd):
 
         :param line: the line being parsed
         :return: the completed Statement
+        :raises: Cmd2ShlexError if a shlex error occurs (e.g. No closing quotation)
+                 EmptyStatement when the resulting Statement is blank
         """
         while True:
             try:
@@ -1755,7 +1755,7 @@ class Cmd(cmd.Cmd):
                     # it's not a multiline command, but we parsed it ok
                     # so we are done
                     break
-            except ValueError:
+            except Cmd2ShlexError:
                 # we have unclosed quotation marks, lets parse only the command
                 # and see if it's a multiline
                 statement = self.statement_parser.parse_command_only(line)
@@ -1792,7 +1792,7 @@ class Cmd(cmd.Cmd):
                 self._at_continuation_prompt = False
 
         if not statement.command:
-            raise EmptyStatement()
+            raise EmptyStatement
         return statement
 
     def _input_line_to_statement(self, line: str) -> Statement:
@@ -1801,6 +1801,8 @@ class Cmd(cmd.Cmd):
 
         :param line: the line being parsed
         :return: parsed command line as a Statement
+        :raises: Cmd2ShlexError if a shlex error occurs (e.g. No closing quotation)
+                 EmptyStatement when the resulting Statement is blank
         """
         used_macros = []
         orig_line = None
@@ -1819,7 +1821,7 @@ class Cmd(cmd.Cmd):
                 used_macros.append(statement.command)
                 line = self._resolve_macro(statement)
                 if line is None:
-                    raise EmptyStatement()
+                    raise EmptyStatement
             else:
                 break
 
diff --git a/cmd2/decorators.py b/cmd2/decorators.py
index 2c78134c..deac4701 100644
--- a/cmd2/decorators.py
+++ b/cmd2/decorators.py
@@ -4,6 +4,7 @@ import argparse
 from typing import Callable, List, Optional, Union
 
 from . import constants
+from .exceptions import Cmd2ArgparseError
 from .parsing import Statement
 
 
@@ -144,7 +145,7 @@ def with_argparser_and_unknown_args(parser: argparse.ArgumentParser, *,
             try:
                 args, unknown = parser.parse_known_args(parsed_arglist, namespace)
             except SystemExit:
-                return
+                raise Cmd2ArgparseError
             else:
                 setattr(args, '__statement__', statement)
                 return func(cmd2_app, args, unknown)
@@ -216,7 +217,7 @@ def with_argparser(parser: argparse.ArgumentParser, *,
             try:
                 args = parser.parse_args(parsed_arglist, namespace)
             except SystemExit:
-                return
+                raise Cmd2ArgparseError
             else:
                 setattr(args, '__statement__', statement)
                 return func(cmd2_app, args)
diff --git a/cmd2/exceptions.py b/cmd2/exceptions.py
index 747e2368..15787177 100644
--- a/cmd2/exceptions.py
+++ b/cmd2/exceptions.py
@@ -2,6 +2,20 @@
 """Custom exceptions for cmd2.  These are NOT part of the public API and are intended for internal use only."""
 
 
+class Cmd2ArgparseError(Exception):
+    """
+    Custom exception class for when a command has an error parsing its arguments.
+    This can be raised by argparse decorators or the command functions themselves.
+    The main use of this exception is to tell cmd2 not to run Postcommand hooks.
+    """
+    pass
+
+
+class Cmd2ShlexError(Exception):
+    """Raised when shlex fails to parse a command line string in StatementParser"""
+    pass
+
+
 class EmbeddedConsoleExit(SystemExit):
     """Custom exception class for use with the py command."""
     pass
diff --git a/cmd2/parsing.py b/cmd2/parsing.py
index 078b1860..71582f1a 100755
--- a/cmd2/parsing.py
+++ b/cmd2/parsing.py
@@ -10,6 +10,7 @@ import attr
 
 from . import constants
 from . import utils
+from .exceptions import Cmd2ShlexError
 
 
 def shlex_split(str_to_split: str) -> List[str]:
@@ -330,7 +331,7 @@ class StatementParser:
 
         :param line: the command line being lexed
         :return: A list of tokens
-        :raises ValueError: if there are unclosed quotation marks
+        :raises: Cmd2ShlexError if a shlex error occurs (e.g. No closing quotation)
         """
 
         # expand shortcuts and aliases
@@ -341,7 +342,10 @@ class StatementParser:
             return []
 
         # split on whitespace
-        tokens = shlex_split(line)
+        try:
+            tokens = shlex_split(line)
+        except ValueError as ex:
+            raise Cmd2ShlexError(ex)
 
         # custom lexing
         tokens = self.split_on_punctuation(tokens)
@@ -355,7 +359,7 @@ class StatementParser:
 
         :param line: the command line being parsed
         :return: a new :class:`~cmd2.Statement` object
-        :raises ValueError: if there are unclosed quotation marks
+        :raises: Cmd2ShlexError if a shlex error occurs (e.g. No closing quotation)
         """
 
         # handle the special case/hardcoded terminator of a blank line
@@ -518,8 +522,6 @@ class StatementParser:
         :param rawinput: the command line as entered by the user
         :return: a new :class:`~cmd2.Statement` object
         """
-        line = rawinput
-
         # expand shortcuts and aliases
         line = self._expand(rawinput)
 

Postcommand Hooks and argparse
Hi

I am using argparse for autocompletion and with sub-commands. 
I always annotate my command methods with `@with_argparser(parser)` which i think is the right way to use the argparser with cmd2. 
I did experiment with postcommand hooks using the `register_postcmd_hook` method. 
The documentation states, that the registered postcommand is only executed when the command method was called (in case of a raised exception the postcommand it is not executed). 

Now, if argparse can't parse the submitted args (for example when there are too few), the command method is not executed, but the postcommand hooks will be executed anyway. 

I understand, that in this context, the `@with_argparser(parser)` belongs to the method and thus one could argument, the method was called and didn't raise an exception, but on the other side, in most cases (i think), it makes not a lot of sense to execute postcommands if argparse can't parse the arguments of the command method. 
Is this behaviour intended? And if yes, is there a possibility to change it? I know i could ditch the annotations, use the argparser inside the command method and raise an exception if argparse fails, but this seems to be a lot of overhead (and i would lose the autocomplete stuff).

Could i possibly "monkey patch" the `with_argparser` method so a exception will be raised? (Also not a very elegant solution i think)

Thanks for any help.


diff --git a/tests/test_parsing.py b/tests/test_parsing.py
index 435f22eb..5f363320 100755
--- a/tests/test_parsing.py
+++ b/tests/test_parsing.py
@@ -96,7 +96,7 @@ def test_tokenize(parser, line, tokens):
     assert tokens_to_test == tokens
 
 def test_tokenize_unclosed_quotes(parser):
-    with pytest.raises(ValueError):
+    with pytest.raises(exceptions.Cmd2ShlexError):
         _ = parser.tokenize('command with "unclosed quotes')
 
 @pytest.mark.parametrize('tokens,command,args', [
@@ -583,7 +583,7 @@ def test_parse_redirect_to_unicode_filename(parser):
     assert statement.output_to == 'café'
 
 def test_parse_unclosed_quotes(parser):
-    with pytest.raises(ValueError):
+    with pytest.raises(exceptions.Cmd2ShlexError):
         _ = parser.tokenize("command with 'unclosed quotes")
 
 def test_empty_statement_raises_exception():
diff --git a/tests/test_plugin.py b/tests/test_plugin.py
index c118b60d..bb7753f0 100644
--- a/tests/test_plugin.py
+++ b/tests/test_plugin.py
@@ -3,6 +3,7 @@
 """
 Test plugin infrastructure and hooks.
 """
+import argparse
 import sys
 
 import pytest
@@ -14,7 +15,7 @@ except ImportError:
     from unittest import mock
 
 import cmd2
-from cmd2 import exceptions, plugin
+from cmd2 import exceptions, plugin, Cmd2ArgumentParser, with_argparser
 
 
 class Plugin:
@@ -254,6 +255,14 @@ class PluggedApp(Plugin, cmd2.Cmd):
         """Repeat back the arguments"""
         self.poutput(statement)
 
+    parser = Cmd2ArgumentParser(description="Test parser")
+    parser.add_argument("my_arg", help="some help text")
+
+    @with_argparser(parser)
+    def do_argparse_cmd(self, namespace: argparse.Namespace):
+        """Repeat back the arguments"""
+        self.poutput(namespace.__statement__)
+
 ###
 #
 # test pre and postloop hooks
@@ -836,3 +845,31 @@ def test_cmdfinalization_hook_exception(capsys):
     assert out == 'hello\n'
     assert err
     assert app.called_cmdfinalization == 1
+
+
+def test_cmd2_argparse_exception(capsys):
+    """
+    Verify Cmd2ArgparseErrors raised after calling a command prevent postcmd events from
+    running but do not affect cmdfinalization events
+    """
+    app = PluggedApp()
+    app.register_postcmd_hook(app.postcmd_hook)
+    app.register_cmdfinalization_hook(app.cmdfinalization_hook)
+
+    # First generate no exception and make sure postcmd_hook, postcmd, and cmdfinalization_hook run
+    app.onecmd_plus_hooks('argparse_cmd arg_val')
+    out, err = capsys.readouterr()
+    assert out == 'arg_val\n'
+    assert not err
+    assert app.called_postcmd == 2
+    assert app.called_cmdfinalization == 1
+
+    app.reset_counters()
+
+    # Next cause an argparse exception and verify no postcmd stuff runs but cmdfinalization_hook still does
+    app.onecmd_plus_hooks('argparse_cmd')
+    out, err = capsys.readouterr()
+    assert not out
+    assert "Error: the following arguments are required: my_arg" in err
+    assert app.called_postcmd == 0
+    assert app.called_cmdfinalization == 1

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-mock
3.9
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.16
anyio==4.9.0
attrs==25.3.0
babel==2.17.0
backports.tarfile==1.2.0
cachetools==5.5.2
certifi==2025.1.31
cffi==1.17.1
chardet==5.2.0
charset-normalizer==3.4.1
click==8.1.8
-e git+https://github.com/python-cmd2/cmd2.git@59739aa5b6f253814fb019a9e777056a6efb61ca#egg=cmd2
codecov==2.1.13
colorama==0.4.6
coverage==7.8.0
cryptography==44.0.2
distlib==0.3.9
doc8==1.1.2
docutils==0.21.2
exceptiongroup==1.2.2
filelock==3.18.0
flake8==7.2.0
h11==0.14.0
id==1.5.0
idna==3.10
imagesize==1.4.1
importlib_metadata==8.6.1
iniconfig==2.1.0
invoke==2.2.0
jaraco.classes==3.4.0
jaraco.context==6.0.1
jaraco.functools==4.1.0
jeepney==0.9.0
Jinja2==3.1.6
keyring==25.6.0
markdown-it-py==3.0.0
MarkupSafe==3.0.2
mccabe==0.7.0
mdurl==0.1.2
more-itertools==10.6.0
nh3==0.2.21
packaging==24.2
pbr==6.1.1
platformdirs==4.3.7
pluggy==1.5.0
pycodestyle==2.13.0
pycparser==2.22
pyflakes==3.3.1
Pygments==2.19.1
pyperclip==1.9.0
pyproject-api==1.9.0
pytest==8.3.5
pytest-cov==6.0.0
pytest-mock==3.14.0
readme_renderer==44.0
requests==2.32.3
requests-toolbelt==1.0.0
restructuredtext_lint==1.4.0
rfc3986==2.0.0
rich==14.0.0
SecretStorage==3.3.3
sniffio==1.3.1
snowballstemmer==2.2.0
Sphinx==7.4.7
sphinx-autobuild==2024.10.3
sphinx-rtd-theme==3.0.2
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
starlette==0.46.1
stevedore==5.4.1
tomli==2.2.1
tox==4.25.0
twine==6.1.0
typing_extensions==4.13.0
urllib3==2.3.0
uvicorn==0.34.0
virtualenv==20.29.3
watchfiles==1.0.4
wcwidth==0.2.13
websockets==15.0.1
zipp==3.21.0

name: cmd2
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.16
      - anyio==4.9.0
      - attrs==25.3.0
      - babel==2.17.0
      - backports-tarfile==1.2.0
      - cachetools==5.5.2
      - certifi==2025.1.31
      - cffi==1.17.1
      - chardet==5.2.0
      - charset-normalizer==3.4.1
      - click==8.1.8
      - codecov==2.1.13
      - colorama==0.4.6
      - coverage==7.8.0
      - cryptography==44.0.2
      - distlib==0.3.9
      - doc8==1.1.2
      - docutils==0.21.2
      - exceptiongroup==1.2.2
      - filelock==3.18.0
      - flake8==7.2.0
      - h11==0.14.0
      - id==1.5.0
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - invoke==2.2.0
      - jaraco-classes==3.4.0
      - jaraco-context==6.0.1
      - jaraco-functools==4.1.0
      - jeepney==0.9.0
      - jinja2==3.1.6
      - keyring==25.6.0
      - markdown-it-py==3.0.0
      - markupsafe==3.0.2
      - mccabe==0.7.0
      - mdurl==0.1.2
      - more-itertools==10.6.0
      - nh3==0.2.21
      - packaging==24.2
      - pbr==6.1.1
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pycparser==2.22
      - pyflakes==3.3.1
      - pygments==2.19.1
      - pyperclip==1.9.0
      - pyproject-api==1.9.0
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - pytest-mock==3.14.0
      - readme-renderer==44.0
      - requests==2.32.3
      - requests-toolbelt==1.0.0
      - restructuredtext-lint==1.4.0
      - rfc3986==2.0.0
      - rich==14.0.0
      - secretstorage==3.3.3
      - sniffio==1.3.1
      - snowballstemmer==2.2.0
      - sphinx==7.4.7
      - sphinx-autobuild==2024.10.3
      - sphinx-rtd-theme==3.0.2
      - sphinxcontrib-applehelp==2.0.0
      - sphinxcontrib-devhelp==2.0.0
      - sphinxcontrib-htmlhelp==2.1.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==2.0.0
      - sphinxcontrib-serializinghtml==2.0.0
      - starlette==0.46.1
      - stevedore==5.4.1
      - tomli==2.2.1
      - tox==4.25.0
      - twine==6.1.0
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - uvicorn==0.34.0
      - virtualenv==20.29.3
      - watchfiles==1.0.4
      - wcwidth==0.2.13
      - websockets==15.0.1
      - zipp==3.21.0
prefix: /opt/conda/envs/cmd2

tests/test_parsing.py::test_tokenize_unclosed_quotes tests/test_parsing.py::test_parse_unclosed_quotes tests/test_plugin.py::test_cmd2_argparse_exception
tests/test_parsing.py::test_parse_empty_string tests/test_parsing.py::test_parse_empty_string_default tests/test_parsing.py::test_tokenize_default[command-tokens0] tests/test_parsing.py::test_tokenize_default[#comment-tokens1] tests/test_parsing.py::test_tokenize_default[not tests/test_parsing.py::test_tokenize_default[termbare tests/test_parsing.py::test_tokenize_default[termbare; tests/test_parsing.py::test_tokenize_default[termbare& tests/test_parsing.py::test_tokenize_default[help|less-tokens7] tests/test_parsing.py::test_tokenize[command-tokens0] tests/test_parsing.py::test_tokenize[# tests/test_parsing.py::test_tokenize[not tests/test_parsing.py::test_tokenize[42 tests/test_parsing.py::test_tokenize[l-tokens4] tests/test_parsing.py::test_tokenize[termbare tests/test_parsing.py::test_tokenize[termbare; tests/test_parsing.py::test_tokenize[termbare& tests/test_parsing.py::test_tokenize[help|less-tokens9] tests/test_parsing.py::test_tokenize[l|less-tokens10] tests/test_parsing.py::test_command_and_args[tokens0--] tests/test_parsing.py::test_command_and_args[tokens1-command-] tests/test_parsing.py::test_command_and_args[tokens2-command-arg1 tests/test_parsing.py::test_parse_single_word[plainword] tests/test_parsing.py::test_parse_single_word["one tests/test_parsing.py::test_parse_single_word['one tests/test_parsing.py::test_parse_word_plus_terminator[termbare;-;] tests/test_parsing.py::test_parse_word_plus_terminator[termbare tests/test_parsing.py::test_parse_word_plus_terminator[termbare&-&] tests/test_parsing.py::test_parse_suffix_after_terminator[termbare; tests/test_parsing.py::test_parse_suffix_after_terminator[termbare tests/test_parsing.py::test_parse_suffix_after_terminator[termbare& tests/test_parsing.py::test_parse_command_with_args tests/test_parsing.py::test_parse_command_with_quoted_args tests/test_parsing.py::test_parse_command_with_args_terminator_and_suffix tests/test_parsing.py::test_parse_comment tests/test_parsing.py::test_parse_embedded_comment_char tests/test_parsing.py::test_parse_simple_pipe[simple tests/test_parsing.py::test_parse_simple_pipe[simple|piped] tests/test_parsing.py::test_parse_double_pipe_is_not_a_pipe tests/test_parsing.py::test_parse_complex_pipe tests/test_parsing.py::test_parse_redirect[help tests/test_parsing.py::test_parse_redirect[help>out.txt->] tests/test_parsing.py::test_parse_redirect[help>>out.txt->>] tests/test_parsing.py::test_parse_redirect_with_args tests/test_parsing.py::test_parse_redirect_with_dash_in_path tests/test_parsing.py::test_parse_redirect_append tests/test_parsing.py::test_parse_pipe_then_redirect tests/test_parsing.py::test_parse_multiple_pipes tests/test_parsing.py::test_redirect_then_pipe tests/test_parsing.py::test_append_then_pipe tests/test_parsing.py::test_append_then_redirect tests/test_parsing.py::test_redirect_then_append tests/test_parsing.py::test_redirect_to_quoted_string tests/test_parsing.py::test_redirect_to_single_quoted_string tests/test_parsing.py::test_redirect_to_empty_quoted_string tests/test_parsing.py::test_redirect_to_empty_single_quoted_string tests/test_parsing.py::test_parse_output_to_paste_buffer tests/test_parsing.py::test_parse_redirect_inside_terminator tests/test_parsing.py::test_parse_multiple_terminators[multiline tests/test_parsing.py::test_parse_unfinished_multiliine_command tests/test_parsing.py::test_parse_basic_multiline_command tests/test_parsing.py::test_parse_multiline_command_ignores_redirectors_within_it[multiline tests/test_parsing.py::test_parse_multiline_terminated_by_empty_line tests/test_parsing.py::test_parse_multiline_with_embedded_newline[multiline tests/test_parsing.py::test_parse_multiline_ignores_terminators_in_quotes tests/test_parsing.py::test_parse_command_with_unicode_args tests/test_parsing.py::test_parse_unicode_command tests/test_parsing.py::test_parse_redirect_to_unicode_filename tests/test_parsing.py::test_empty_statement_raises_exception tests/test_parsing.py::test_parse_alias_and_shortcut_expansion[helpalias-help-] tests/test_parsing.py::test_parse_alias_and_shortcut_expansion[helpalias tests/test_parsing.py::test_parse_alias_and_shortcut_expansion[42-theanswer-] tests/test_parsing.py::test_parse_alias_and_shortcut_expansion[42 tests/test_parsing.py::test_parse_alias_and_shortcut_expansion[!ls-shell-ls] tests/test_parsing.py::test_parse_alias_and_shortcut_expansion[!ls tests/test_parsing.py::test_parse_alias_and_shortcut_expansion[l-shell-ls tests/test_parsing.py::test_parse_alias_on_multiline_command tests/test_parsing.py::test_parse_alias_redirection[helpalias tests/test_parsing.py::test_parse_alias_redirection[helpalias>out.txt->] tests/test_parsing.py::test_parse_alias_redirection[helpalias>>out.txt->>] tests/test_parsing.py::test_parse_alias_pipe[helpalias tests/test_parsing.py::test_parse_alias_pipe[helpalias|less] tests/test_parsing.py::test_parse_alias_terminator_no_whitespace[helpalias;] tests/test_parsing.py::test_parse_alias_terminator_no_whitespace[helpalias;;] tests/test_parsing.py::test_parse_alias_terminator_no_whitespace[helpalias;; tests/test_parsing.py::test_parse_alias_terminator_no_whitespace[helpalias tests/test_parsing.py::test_parse_command_only_command_and_args tests/test_parsing.py::test_parse_command_only_strips_line tests/test_parsing.py::test_parse_command_only_expands_alias tests/test_parsing.py::test_parse_command_only_expands_shortcuts tests/test_parsing.py::test_parse_command_only_quoted_args tests/test_parsing.py::test_parse_command_only_specialchars[helpalias tests/test_parsing.py::test_parse_command_only_specialchars[helpalias>out.txt->out.txt] tests/test_parsing.py::test_parse_command_only_specialchars[helpalias>>out.txt->>out.txt] tests/test_parsing.py::test_parse_command_only_specialchars[help|less-|less] tests/test_parsing.py::test_parse_command_only_specialchars[helpalias;-;] tests/test_parsing.py::test_parse_command_only_specialchars[help tests/test_parsing.py::test_parse_command_only_specialchars[help; tests/test_parsing.py::test_parse_command_only_empty[] tests/test_parsing.py::test_parse_command_only_empty[;] tests/test_parsing.py::test_parse_command_only_empty[;;] tests/test_parsing.py::test_parse_command_only_empty[;; tests/test_parsing.py::test_parse_command_only_empty[&] tests/test_parsing.py::test_parse_command_only_empty[& tests/test_parsing.py::test_parse_command_only_empty[ tests/test_parsing.py::test_parse_command_only_empty[>] tests/test_parsing.py::test_parse_command_only_empty['] tests/test_parsing.py::test_parse_command_only_empty["] tests/test_parsing.py::test_parse_command_only_empty[|] tests/test_parsing.py::test_parse_command_only_multiline tests/test_parsing.py::test_statement_initialization tests/test_parsing.py::test_statement_is_immutable tests/test_parsing.py::test_is_valid_command_invalid tests/test_parsing.py::test_is_valid_command_valid tests/test_parsing.py::test_macro_normal_arg_pattern tests/test_parsing.py::test_macro_escaped_arg_pattern tests/test_plugin.py::test_register_preloop_hook_too_many_parameters tests/test_plugin.py::test_register_preloop_hook_with_return_annotation tests/test_plugin.py::test_preloop_hook tests/test_plugin.py::test_preloop_hooks tests/test_plugin.py::test_register_postloop_hook_too_many_parameters tests/test_plugin.py::test_register_postloop_hook_with_wrong_return_annotation tests/test_plugin.py::test_postloop_hook tests/test_plugin.py::test_postloop_hooks tests/test_plugin.py::test_preparse tests/test_plugin.py::test_postparsing_hook_too_many_parameters tests/test_plugin.py::test_postparsing_hook_undeclared_parameter_annotation tests/test_plugin.py::test_postparsing_hook_wrong_parameter_annotation tests/test_plugin.py::test_postparsing_hook_undeclared_return_annotation tests/test_plugin.py::test_postparsing_hook_wrong_return_annotation tests/test_plugin.py::test_postparsing_hook tests/test_plugin.py::test_postparsing_hook_stop_first tests/test_plugin.py::test_postparsing_hook_stop_second tests/test_plugin.py::test_postparsing_hook_emptystatement_first tests/test_plugin.py::test_postparsing_hook_emptystatement_second tests/test_plugin.py::test_postparsing_hook_exception tests/test_plugin.py::test_register_precmd_hook_parameter_count tests/test_plugin.py::test_register_precmd_hook_no_parameter_annotation tests/test_plugin.py::test_register_precmd_hook_wrong_parameter_annotation tests/test_plugin.py::test_register_precmd_hook_no_return_annotation tests/test_plugin.py::test_register_precmd_hook_wrong_return_annotation tests/test_plugin.py::test_precmd_hook tests/test_plugin.py::test_precmd_hook_emptystatement_first tests/test_plugin.py::test_precmd_hook_emptystatement_second tests/test_plugin.py::test_register_postcmd_hook_parameter_count tests/test_plugin.py::test_register_postcmd_hook_no_parameter_annotation tests/test_plugin.py::test_register_postcmd_hook_wrong_parameter_annotation tests/test_plugin.py::test_register_postcmd_hook_no_return_annotation tests/test_plugin.py::test_register_postcmd_hook_wrong_return_annotation tests/test_plugin.py::test_postcmd tests/test_plugin.py::test_postcmd_exception_first tests/test_plugin.py::test_postcmd_exception_second tests/test_plugin.py::test_register_cmdfinalization_hook_parameter_count tests/test_plugin.py::test_register_cmdfinalization_hook_no_parameter_annotation tests/test_plugin.py::test_register_cmdfinalization_hook_wrong_parameter_annotation tests/test_plugin.py::test_register_cmdfinalization_hook_no_return_annotation tests/test_plugin.py::test_register_cmdfinalization_hook_wrong_return_annotation tests/test_plugin.py::test_cmdfinalization tests/test_plugin.py::test_cmdfinalization_stop_first tests/test_plugin.py::test_cmdfinalization_stop_second tests/test_plugin.py::test_cmdfinalization_hook_exception
cmd2/cmd2.py cmd2/parsing.py cmd2/decorators.py CHANGELOG.md cmd2/exceptions.py
cmd2/cmd2.py cmd2/parsing.py cmd2/decorators.py CHANGELOG.md cmd2/exceptions.py