Repository: python-cmd2/cmd2

Issue:
onecmd should accept a raw string
I have commands that I want to run without the hooks as strings, but trying to run `onecmd` directly fails because `command` and `args` to be in the namespace.

This is inconsistent with the `cmd` standard library module.

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0e22ee79..764d0061 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,7 @@
-## 0.9.3 (TBD, 2018)
+## 0.9.3 (July TBD, 2018)
+* Bug Fixes
+    * Fixed bug when StatementParser ``__init__()`` was called with ``terminators`` equal to ``None``
+    * Fixed bug when ``Cmd.onecmd()`` was called with a raw ``str``
 
 ## 0.9.2 (June 28, 2018)
 * Bug Fixes
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 42e00c39..44f3a068 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -1901,14 +1901,19 @@ class Cmd(cmd.Cmd):
             result = target
         return result
 
-    def onecmd(self, statement: Statement) -> Optional[bool]:
+    def onecmd(self, statement: Union[Statement, str]) -> Optional[bool]:
         """ This executes the actual do_* method for a command.
 
         If the command provided doesn't exist, then it executes _default() instead.
 
-        :param statement: Command - a parsed command from the input stream
+        :param statement: Command - intended to be a Statement instance parsed command from the input stream,
+                                    alternative acceptance of a str is present only for backward compatibility with cmd
         :return: a flag indicating whether the interpretation of commands should stop
         """
+        # For backwards compatibility with cmd, allow a str to be passed in
+        if not isinstance(statement, Statement):
+            statement = self._complete_statement(statement)
+
         funcname = self._func_named(statement.command)
         if not funcname:
             self.default(statement)


Test patch:
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py
index 77dcc875..b973fdf5 100644
--- a/tests/test_cmd2.py
+++ b/tests/test_cmd2.py
@@ -1787,3 +1787,18 @@ def test_readline_remove_history_item(base_app):
     assert readline.get_current_history_length() == 1
     readline.remove_history_item(0)
     assert readline.get_current_history_length() == 0
+
+def test_onecmd_raw_str_continue(base_app):
+    line = "help"
+    stop = base_app.onecmd(line)
+    out = base_app.stdout.buffer
+    assert not stop
+    assert out.strip() == BASE_HELP.strip()
+
+def test_onecmd_raw_str_quit(base_app):
+    line = "quit"
+    stop = base_app.onecmd(line)
+    out = base_app.stdout.buffer
+    assert stop
+    assert out == ''
+