diff options
-rw-r--r-- | CHANGELOG.md | 8 | ||||
-rwxr-xr-x | README.md | 7 | ||||
-rw-r--r-- | cmd2/cmd2.py | 22 | ||||
-rw-r--r-- | docs/features/builtin_commands.rst | 3 | ||||
-rw-r--r-- | docs/features/embedded_python_shells.rst | 6 | ||||
-rw-r--r-- | docs/features/initialization.rst | 8 | ||||
-rw-r--r-- | docs/features/multiline_commands.rst | 10 | ||||
-rw-r--r-- | docs/features/prompt.rst | 7 | ||||
-rw-r--r-- | docs/features/settings.rst | 35 | ||||
-rw-r--r-- | docs/features/transcripts.rst | 4 | ||||
-rwxr-xr-x | examples/basic.py | 2 | ||||
-rwxr-xr-x | examples/cmd_as_argument.py | 2 | ||||
-rwxr-xr-x | examples/hello_cmd2.py | 2 | ||||
-rwxr-xr-x | examples/initialization.py | 2 | ||||
-rwxr-xr-x | examples/override_parser.py | 2 | ||||
-rwxr-xr-x | examples/python_scripting.py | 2 | ||||
-rw-r--r-- | examples/scripts/conditional.py | 2 | ||||
-rw-r--r-- | examples/scripts/save_help_text.py | 2 | ||||
-rw-r--r-- | examples/transcripts/exampleSession.txt | 4 | ||||
-rw-r--r-- | examples/transcripts/transcript_regex.txt | 4 | ||||
-rw-r--r-- | tests/conftest.py | 6 | ||||
-rwxr-xr-x | tests/test_cmd2.py | 12 | ||||
-rw-r--r-- | tests/transcripts/from_cmdloop.txt | 6 | ||||
-rw-r--r-- | tests/transcripts/regex_set.txt | 3 |
24 files changed, 67 insertions, 94 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index bc5fa5d4..7065983d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.9.26 (TBD, 2020) +* Breaking changes + * Renamed `locals_in_py` attribute of `cmd2.Cmd` to `self_in_py` + * The following public attributes of `cmd2.Cmd` are no longer settable at runtime by end users: + * `continuation_prompt` + * `self_in_py` + * `prompt` + ## 0.9.25 (January 26, 2020) * Enhancements * Reduced what gets put in package downloadable from PyPI (removed irrelevant CI config files and such) @@ -318,14 +318,11 @@ example/transcript_regex.txt: # regexes on prompts just make the trailing space obvious (Cmd) set allow_style: Terminal -continuation_prompt: >/ / debug: False echo: False editor: /.*?/ feedback_to_output: False -locals_in_py: True maxrepeats: 3 -prompt: (Cmd)/ / quiet: False timing: False ``` @@ -350,14 +347,14 @@ Open source projects using cmd2 Here are a few examples of open-source projects which use `cmd2`: +* [Jok3r](http://www.jok3r-framework.com) + * Network & Web Pentest Automation Framework * [CephFS Shell](http://docs.ceph.com/docs/master/cephfs/cephfs-shell/) * [Ceph](https://ceph.com/) is a distributed object, block, and file storage platform * [JSShell](https://github.com/Den1al/JSShell) * An interactive multi-user web JavaScript shell * [psiTurk](https://psiturk.org) * An open platform for science on Amazon Mechanical Turk -* [Jok3r](http://www.jok3r-framework.com) - * Network & Web Pentest Automation Framework * [Poseidon](https://github.com/CyberReboot/poseidon) * Leverages software-defined networks (SDNs) to acquire and then feed network traffic to a number of machine learning techniques * [Unipacker](https://github.com/unipacker/unipacker) diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index 648aadb1..f3b7c4a4 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -181,28 +181,23 @@ class Cmd(cmd.Cmd): super().__init__(completekey=completekey, stdin=stdin, stdout=stdout) # Attributes which should NOT be dynamically settable via the set command at runtime - # To prevent a user from altering these with the py/ipy commands, remove locals_in_py from the - # settable dictionary during your applications's __init__ method. self.default_to_shell = False # Attempt to run unrecognized commands as shell commands self.quit_on_sigint = False # Quit the loop on interrupt instead of just resetting prompt self.allow_redirection = allow_redirection # Security setting to prevent redirection of stdout # Attributes which ARE dynamically settable via the set command at runtime - self.continuation_prompt = '> ' self.debug = False self.echo = False self.editor = Cmd.DEFAULT_EDITOR self.feedback_to_output = False # Do not include nonessentials in >, | output by default (things like timing) - self.locals_in_py = False + self.quiet = False # Do not suppress nonessential output + self.timing = False # Prints elapsed time for each command # The maximum number of CompletionItems to display during tab completion. If the number of completion # suggestions exceeds this number, they will be displayed in the typical columnized format and will # not include the description value of the CompletionItems. self.max_completion_items = 50 - self.quiet = False # Do not suppress nonessential output - self.timing = False # Prints elapsed time for each command - # To make an attribute settable with the "do_set" command, add it to this ... self.settable = \ { @@ -211,18 +206,21 @@ class Cmd(cmd.Cmd): '(valid values: {}, {}, {})'.format(ansi.STYLE_TERMINAL, ansi.STYLE_ALWAYS, ansi.STYLE_NEVER)), - 'continuation_prompt': 'On 2nd+ line of input', 'debug': 'Show full error stack on error', 'echo': 'Echo command issued into output', 'editor': 'Program used by ``edit``', 'feedback_to_output': 'Include nonessentials in `|`, `>` results', - 'locals_in_py': 'Allow access to your application in py via self', 'max_completion_items': 'Maximum number of CompletionItems to display during tab completion', - 'prompt': 'The prompt issued to solicit input', 'quiet': "Don't print nonessential feedback", 'timing': 'Report execution times' } + # Use as prompt for multiline commands on the 2nd+ line of input + self.continuation_prompt = '> ' + + # Allow access to your application in embedded Python shells and scripts py via self + self.self_in_py = False + # Commands to exclude from the help menu and tab completion self.hidden_commands = ['eof', '_relative_load', '_relative_run_script'] @@ -3118,7 +3116,7 @@ class Cmd(cmd.Cmd): self.py_locals['quit'] = py_quit self.py_locals['exit'] = py_quit - if self.locals_in_py: + if self.self_in_py: self.py_locals['self'] = self elif 'self' in self.py_locals: del self.py_locals['self'] @@ -3238,7 +3236,7 @@ class Cmd(cmd.Cmd): exec("{} = py_bridge".format(cmd2_app.py_bridge_name)) # Add self variable pointing to cmd2_app, if allowed - if cmd2_app.locals_in_py: + if cmd2_app.self_in_py: exec("self = cmd2_app") # Delete these names from the environment so IPython can't use them diff --git a/docs/features/builtin_commands.rst b/docs/features/builtin_commands.rst index 540cfbb1..025149b3 100644 --- a/docs/features/builtin_commands.rst +++ b/docs/features/builtin_commands.rst @@ -93,14 +93,11 @@ within a running application: (Cmd) set --long allow_style: Terminal # Allow ANSI text style sequences in output (valid values: Terminal, Always, Never) - continuation_prompt: > # On 2nd+ line of input debug: False # Show full error stack on error echo: False # Echo command issued into output editor: vim # Program used by ``edit`` feedback_to_output: False # include nonessentials in `|`, `>` results - locals_in_py: False # Allow access to your application in py via self max_completion_items: 50 # Maximum number of CompletionItems to display during tab completion - prompt: (Cmd) # The prompt issued to solicit input quiet: False # Don't print nonessential feedback timing: False # Report execution times diff --git a/docs/features/embedded_python_shells.rst b/docs/features/embedded_python_shells.rst index 9d721c2c..0af2f737 100644 --- a/docs/features/embedded_python_shells.rst +++ b/docs/features/embedded_python_shells.rst @@ -8,11 +8,9 @@ arguments, it enters an interactive Python session. The session can call your cmd2 application while maintaining isolation. You may optionally enable full access to to your application by setting -``locals_in_py`` to ``True``. Enabling this flag adds ``self`` to the python +``self_in_py`` to ``True``. Enabling this flag adds ``self`` to the python session, which is a reference to your Cmd2 application. This can be useful for -debugging your application. To prevent users from enabling this ability -manually you'll need to remove ``locals_in_py`` from the ``settable`` -dictionary. +debugging your application. The ``app`` object (or your custom name) provides access to application commands through raw commands. For example, any application command call be diff --git a/docs/features/initialization.rst b/docs/features/initialization.rst index 39e36428..c5df5af8 100644 --- a/docs/features/initialization.rst +++ b/docs/features/initialization.rst @@ -39,7 +39,7 @@ capabilities which you may wish to utilize while initializing the app:: self.continuation_prompt = '... ' # Allow access to your application in py and ipy via self - self.locals_in_py = True + self.self_in_py = True # Set the default category name self.default_category = 'cmd2 Built-in Commands' @@ -110,7 +110,7 @@ override: DisabledCommand objects. - **echo**: if ``True``, each command the user issues will be repeated to the screen before it is executed. This is particularly useful when running - scripts. This behavior does not occur when a running command at the prompt. + scripts. This behavior does not occur when running a command at the prompt. (Default: ``False``) - **editor**: text editor program to use with *edit* command (e.g. ``vim``) - **exclude_from_history**: commands to exclude from the *history* command @@ -125,7 +125,7 @@ override: of results in a Python script or interactive console. Built-in commands don't make use of this. It is purely there for user-defined commands and convenience. -- **locals_in_py**: if ``True`` allow access to your application in *py* +- **self_in_py**: if ``True`` allow access to your application in *py* command via ``self`` (Default: ``False``) - **macros**: dictionary of macro names and their values - **max_completion_items**: max number of CompletionItems to display during @@ -139,7 +139,7 @@ override: ``app``) - **py_locals**: dictionary that defines specific variables/functions available in Python shells and scripts (provides more fine-grained control than making - everything available with **locals_in_py**) + everything available with **self_in_py**) - **quiet**: if ``True`` then completely suppress nonessential output (Default: ``False``) - **quit_on_sigint**: if ``True`` quit the main loop on interrupt instead of diff --git a/docs/features/multiline_commands.rst b/docs/features/multiline_commands.rst index d6502058..769e0a64 100644 --- a/docs/features/multiline_commands.rst +++ b/docs/features/multiline_commands.rst @@ -10,3 +10,13 @@ blank line is *always* considered a command terminator (cannot be overridden). In multiline commands, output redirection characters like ``>`` and ``|`` are part of the command arguments unless they appear after the terminator. + +Continuation prompt +------------------- + +When a user types a :ref:`Multiline Command +<features/multiline_commands:Multiline Commands>` it may span more than one +line of input. The prompt for the first line of input is specified by the +``cmd2.Cmd.prompt`` instance attribute - see +:ref:`features/prompt:Customizing the Prompt`. The prompt for subsequent lines +of input is defined by the ``cmd2.Cmd.continuation_prompt`` attribute. diff --git a/docs/features/prompt.rst b/docs/features/prompt.rst index 40c50d2b..244ffb31 100644 --- a/docs/features/prompt.rst +++ b/docs/features/prompt.rst @@ -3,6 +3,13 @@ Prompt ``cmd2`` can issue a prompt before soliciting user input. +Customizing the Prompt +---------------------- + +This prompt can be configured by setting the `cmd2.Cmd.prompt` instance +attribute. This contains the string which should be printed as a prompt +for user input. + Asynchronous Feedback --------------------- diff --git a/docs/features/settings.rst b/docs/features/settings.rst index b8f75934..55b6a10d 100644 --- a/docs/features/settings.rst +++ b/docs/features/settings.rst @@ -47,16 +47,6 @@ This setting can be one of three values: - ``Always`` - ANSI escape sequences are always passed through to the output -continuation_prompt -~~~~~~~~~~~~~~~~~~~ - -When a user types a :ref:`Multiline Command -<features/multiline_commands:Multiline Commands>` it may span more than one -line of input. The prompt for the first line of input is specified by the -:ref:`features/settings:prompt` setting. The prompt for subsequent lines of -input is defined by this setting. - - debug ~~~~~ @@ -71,7 +61,7 @@ echo If ``True``, each command the user issues will be repeated to the screen before it is executed. This is particularly useful when running scripts. -This behavior does not occur when a running command at the prompt. +This behavior does not occur when running a command at the prompt. editor @@ -95,13 +85,6 @@ feedback output will be mixed in with and indistinguishable from output generated with :meth:`~cmd2.cmd2.Cmd.poutput`. -locals_in_py -~~~~~~~~~~~~ - -Allow access to your application in one of the -:ref:`features/embedded_python_shells:Embedded Python Shells` via ``self``. - - max_completion_items ~~~~~~~~~~~~~~~~~~~~ @@ -115,13 +98,6 @@ they will be displayed in the typical columnized format and will not include the description text of the CompletionItem. -prompt -~~~~~~ - -This setting contains the string which should be printed as a prompt for user -input. - - quiet ~~~~~ @@ -180,14 +156,13 @@ You may want to prevent a user from modifying a builtin setting. A setting must appear in the :attr:`cmd2.cmd2.Cmd.settable` dictionary in order for it to be available to the :ref:`features/builtin_commands:set` command. -Let's say your program does not have any -:ref:`features/multiline_commands:Multiline Commands`. You might want to hide -the :ref:`features/settings:continuation_prompt` setting from your users since -it is only applicable to multiline commands. To do so, remove it from the +Let's say that you never want end users of your program to be able to enable +full debug tracebacks to print out if an error occurs. You might want to hide +the :ref:`features/settings:debug` setting. To do so, remove it from the :attr:`cmd2.cmd2.Cmd.settable` dictionary after you initialize your object:: class MyApp(cmd2.Cmd): def __init__(self): super().__init__() - self.settable.pop('continuation_prompt') + self.settable.pop('debug') diff --git a/docs/features/transcripts.rst b/docs/features/transcripts.rst index 9f524e0a..1af2a74f 100644 --- a/docs/features/transcripts.rst +++ b/docs/features/transcripts.rst @@ -146,8 +146,8 @@ the path instead of specifying it verbatim, or we can escape the slashes:: invisible, you can add a regular expression to match them, so that you can see where they are when you look at the transcript:: - (Cmd) set prompt - prompt: (Cmd)/ / + (Cmd) set editor + editor: vim/ / Some terminal emulators strip trailing space when you copy text from them. This could make the actual data generated by your app different than the diff --git a/examples/basic.py b/examples/basic.py index 75672a6b..37db6501 100755 --- a/examples/basic.py +++ b/examples/basic.py @@ -22,7 +22,7 @@ class BasicApp(cmd2.Cmd): self.intro = style('Welcome to PyOhio 2019 and cmd2!', fg='red', bg='white', bold=True) + ' 😀' # Allow access to your application in py and ipy via self - self.locals_in_py = True + self.self_in_py = True # Set the default category name self.default_category = 'cmd2 Built-in Commands' diff --git a/examples/cmd_as_argument.py b/examples/cmd_as_argument.py index 49a50670..08643a50 100755 --- a/examples/cmd_as_argument.py +++ b/examples/cmd_as_argument.py @@ -33,7 +33,7 @@ class CmdLineApp(cmd2.Cmd): # Set use_ipython to True to enable the "ipy" command which embeds and interactive IPython shell super().__init__(allow_cli_args=False, use_ipython=True, multiline_commands=['orate'], shortcuts=shortcuts) - self.locals_in_py = True + self.self_in_py = True self.maxrepeats = 3 # Make maxrepeats settable at runtime self.settable['maxrepeats'] = 'max repetitions for speak command' diff --git a/examples/hello_cmd2.py b/examples/hello_cmd2.py index 84754623..94ec334f 100755 --- a/examples/hello_cmd2.py +++ b/examples/hello_cmd2.py @@ -12,6 +12,6 @@ if __name__ == '__main__': # Set "use_ipython" to True to include the ipy command if IPython is installed, which supports advanced interactive # debugging of your application via introspection on self. app = cmd2.Cmd(use_ipython=True, persistent_history_file='cmd2_history.dat') - app.locals_in_py = True # Enable access to "self" within the py command + app.self_in_py = True # Enable access to "self" within the py command app.debug = True # Show traceback if/when an exception occurs sys.exit(app.cmdloop()) diff --git a/examples/initialization.py b/examples/initialization.py index e26aac9f..32aa852f 100755 --- a/examples/initialization.py +++ b/examples/initialization.py @@ -33,7 +33,7 @@ class BasicApp(cmd2.Cmd): self.continuation_prompt = '... ' # Allow access to your application in py and ipy via self - self.locals_in_py = True + self.self_in_py = True # Set the default category name self.default_category = 'cmd2 Built-in Commands' diff --git a/examples/override_parser.py b/examples/override_parser.py index ddfa8323..eecb0e88 100755 --- a/examples/override_parser.py +++ b/examples/override_parser.py @@ -19,6 +19,6 @@ from cmd2 import cmd2 if __name__ == '__main__': import sys app = cmd2.Cmd(use_ipython=True, persistent_history_file='cmd2_history.dat') - app.locals_in_py = True # Enable access to "self" within the py command + app.self_in_py = True # Enable access to "self" within the py command app.debug = True # Show traceback if/when an exception occurs sys.exit(app.cmdloop()) diff --git a/examples/python_scripting.py b/examples/python_scripting.py index 8c680d33..fc23c562 100755 --- a/examples/python_scripting.py +++ b/examples/python_scripting.py @@ -29,7 +29,7 @@ class CmdLineApp(cmd2.Cmd): super().__init__(use_ipython=True) self._set_prompt() self.intro = 'Happy 𝛑 Day. Note the full Unicode support: 😇 💩' - self.locals_in_py = True + self.self_in_py = True def _set_prompt(self): """Set prompt so it displays the current working directory.""" diff --git a/examples/scripts/conditional.py b/examples/scripts/conditional.py index 2e307cb4..eb4c203e 100644 --- a/examples/scripts/conditional.py +++ b/examples/scripts/conditional.py @@ -8,7 +8,7 @@ To run it you should do the following: run_pyscript scripts/conditional.py directory_path Note: The "app" function is defined within the cmd2 embedded Python environment and in there "self" is your cmd2 -application instance. Note: self only exists in this environment if locals_in_py is True. +application instance. Note: self only exists in this environment if self_in_py is True. """ import os import sys diff --git a/examples/scripts/save_help_text.py b/examples/scripts/save_help_text.py index 12d66d6d..cc4cfcc7 100644 --- a/examples/scripts/save_help_text.py +++ b/examples/scripts/save_help_text.py @@ -60,7 +60,7 @@ def main() -> None: # Make sure we have access to self if 'self' not in globals(): - print("Run 'set locals_in_py true' and then rerun this script") + print("Re-run this script from a cmd2 application where self_in_py is True") return # Make sure the user passed in an output file diff --git a/examples/transcripts/exampleSession.txt b/examples/transcripts/exampleSession.txt index 5a75235b..54419f91 100644 --- a/examples/transcripts/exampleSession.txt +++ b/examples/transcripts/exampleSession.txt @@ -4,13 +4,11 @@ # regexes on prompts just make the trailing space obvious (Cmd) set allow_style: /(Terminal|Always|Never)/ -continuation_prompt: >/ / debug: False echo: False editor: /.*?/ feedback_to_output: False -locals_in_py: False +max_completion_items: 50 maxrepeats: 3 -prompt: (Cmd)/ / quiet: False timing: False diff --git a/examples/transcripts/transcript_regex.txt b/examples/transcripts/transcript_regex.txt index 276f7d22..35fc5817 100644 --- a/examples/transcripts/transcript_regex.txt +++ b/examples/transcripts/transcript_regex.txt @@ -4,13 +4,11 @@ # regexes on prompts just make the trailing space obvious (Cmd) set allow_style: /(Terminal|Always|Never)/ -continuation_prompt: >/ / debug: False echo: False editor: /.*?/ feedback_to_output: False -locals_in_py: False +max_completion_items: 50 maxrepeats: 3 -prompt: (Cmd)/ / quiet: False timing: False diff --git a/tests/conftest.py b/tests/conftest.py index fe74ffe2..b8abc4a5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -89,28 +89,22 @@ SHORTCUTS_TXT = """Shortcuts for other commands: # Output from the show command with default settings SHOW_TXT = """allow_style: Terminal -continuation_prompt: > debug: False echo: False editor: vim feedback_to_output: False -locals_in_py: False max_completion_items: 50 -prompt: (Cmd) quiet: False timing: False """ SHOW_LONG = """ allow_style: Terminal # Allow ANSI text style sequences in output (valid values: Terminal, Always, Never) -continuation_prompt: > # On 2nd+ line of input debug: False # Show full error stack on error echo: False # Echo command issued into output editor: vim # Program used by ``edit`` feedback_to_output: False # Include nonessentials in `|`, `>` results -locals_in_py: False # Allow access to your application in py via self max_completion_items: 50 # Maximum number of CompletionItems to display during tab completion -prompt: (Cmd) # The prompt issued to solicit input quiet: False # Don't print nonessential feedback timing: False # Report execution times """ diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py index b5473609..a3dbe1be 100755 --- a/tests/test_cmd2.py +++ b/tests/test_cmd2.py @@ -254,17 +254,13 @@ def test_base_py(base_app): out, err = run_cmd(base_app, 'py print("spaces" + " in this " + "command")') assert out[0].rstrip() == 'spaces in this command' - # Set locals_in_py to True and make sure we see self - out, err = run_cmd(base_app, 'set locals_in_py True') - assert 'now: True' in out - + # Set self_in_py to True and make sure we see self + base_app.self_in_py = True out, err = run_cmd(base_app, 'py print(self)') assert 'cmd2.cmd2.Cmd object' in out[0] - # Set locals_in_py to False and make sure we can't see self - out, err = run_cmd(base_app, 'set locals_in_py False') - assert 'now: False' in out - + # Set self_in_py to False and make sure we can't see self + base_app.self_in_py = False out, err = run_cmd(base_app, 'py print(self)') assert "NameError: name 'self' is not defined" in err diff --git a/tests/transcripts/from_cmdloop.txt b/tests/transcripts/from_cmdloop.txt index aede6659..95537665 100644 --- a/tests/transcripts/from_cmdloop.txt +++ b/tests/transcripts/from_cmdloop.txt @@ -39,6 +39,6 @@ OODNIGHT, GRACIEGAY OODNIGHT, GRACIEGAY OODNIGHT, GRACIEGAY OODNIGHT, GRACIEGAY -(Cmd) set prompt "---> " -prompt - was: (Cmd)/ */ -now: --->/ */ +(Cmd) set debug True +debug - was: False/ */ +now: True/ */ diff --git a/tests/transcripts/regex_set.txt b/tests/transcripts/regex_set.txt index 17f43ede..5bf9add3 100644 --- a/tests/transcripts/regex_set.txt +++ b/tests/transcripts/regex_set.txt @@ -5,14 +5,11 @@ (Cmd) set allow_style: /(Terminal|Always|Never)/ -continuation_prompt: >/ / debug: False echo: False editor: /.*/ feedback_to_output: False -locals_in_py: False max_completion_items: 50 maxrepeats: 3 -prompt: (Cmd)/ / quiet: False timing: False |