summaryrefslogtreecommitdiff
path: root/cmd2.py
diff options
context:
space:
mode:
Diffstat (limited to 'cmd2.py')
-rwxr-xr-xcmd2.py72
1 files changed, 69 insertions, 3 deletions
diff --git a/cmd2.py b/cmd2.py
index c8bbecb0..9135fa37 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -451,6 +451,10 @@ class ParsedString(str):
return new
def with_args_replaced(self, newargs):
+ """Used for @options commands when USE_ARG_LIST is False.
+
+ It helps figure out what the args are after removing options.
+ """
new = ParsedString(newargs)
new.parsed = self.parsed
new.parser = self.parser
@@ -465,6 +469,10 @@ class StubbornDict(dict):
Create it with the stubbornDict(arg) factory function.
"""
def update(self, arg):
+ """Adds dictionary arg's key-values pairs in to dict
+
+ :param arg: an object convertable to a StubbornDict
+ """
dict.update(self, StubbornDict.to_dict(arg))
append = update
@@ -520,6 +528,11 @@ def stubbornDict(*arg, **kwarg):
def replace_with_file_contents(fname):
+ """Action to perform when successfully matching parse element definition for inputFrom parser.
+
+ :param fname: str - filename
+ :return: str - contents of file "fname" or contents of the clipboard if fname is None or an empty string
+ """
if fname:
try:
result = open(os.path.expanduser(fname[0])).read()
@@ -531,10 +544,12 @@ def replace_with_file_contents(fname):
class EmbeddedConsoleExit(SystemExit):
+ """Custom exception class for use with the py command."""
pass
class EmptyStatement(Exception):
+ """Custom exception class for handling behavior when the user just presses <Enter>."""
pass
@@ -889,6 +904,14 @@ class Cmd(cmd.Cmd):
return stop
def func_named(self, arg):
+ """Gets the method name associated with a given command.
+
+ If self.abbrev is False, it is always just looks for do_arg. However, if self.abbrev is True,
+ it allows abbreivated command names and looks for any commands which start with do_arg.
+
+ :param arg: str - command to look up method name which implements it
+ :return: str - method name which implements the given command
+ """
result = None
target = 'do_' + arg
if target in dir(self):
@@ -901,10 +924,10 @@ class Cmd(cmd.Cmd):
return result
def onecmd_plus_hooks(self, line):
- """
+ """Top-level function called by cmdloop() to handle parsing a line and running the command and all of its hooks.
- :param line:
- :return:
+ :param line: str - line of text read from inp
+ :return: bool - True if cmdloop() should exit, False otherwise
"""
# The outermost level of try/finally nesting can be condensed once
# Python 2.4 support can be dropped.
@@ -954,10 +977,20 @@ class Cmd(cmd.Cmd):
return statement
def redirect_output(self, statement):
+ """Handles output redirection for >, >>, and |.
+
+ :param statement: ParsedString - subclass of str which also contains pyparsing ParseResults instance
+ """
if statement.parsed.pipeTo:
self.kept_state = Statekeeper(self, ('stdout',))
self.kept_sys = Statekeeper(sys, ('stdout',))
sys.stdout = self.stdout
+
+ # NOTE: We couldn't get a real pipe working via subprocess for Python 3.x prior to 3.5.
+ # So to allow compatibility with Python 2.7 and 3.3+ we are redirecting output to a temporary file.
+ # And once command is complete we are using the "cat" shell command to pipe to whatever.
+ # TODO: Once support for Python 3.x prior to 3.5 is no longer necessary, replace with a real subprocess pipe
+
# Redirect stdout to a temporary file
_, self._temp_filename = tempfile.mkstemp()
self.stdout = open(self._temp_filename, 'w')
@@ -977,6 +1010,10 @@ class Cmd(cmd.Cmd):
self.stdout.write(get_paste_buffer())
def restore_output(self, statement):
+ """Handles restoring state after output redirection as well as the actual pipe operation if present.
+
+ :param statement: ParsedString - subclass of str which also contains pyparsing ParseResults instance
+ """
if self.kept_state:
try:
if statement.parsed.output:
@@ -1249,6 +1286,10 @@ class Cmd(cmd.Cmd):
# Support the run command even if called prior to invoking an interactive interpreter
def run(arg):
+ """Run a Python script file in the interactive console.
+
+ :param arg: str - filename of *.py script file to run
+ """
try:
with open(arg) as f:
interp.runcode(f.read())
@@ -1256,6 +1297,11 @@ class Cmd(cmd.Cmd):
self.perror(e)
def onecmd_plus_hooks(arg):
+ """Run a cmd2.Cmd command from a Python script or the interactive Python console.
+
+ :param arg: str - command line including command and arguments to run
+ :return: bool - True if cmdloop() should exit once leaving the interactive Python console, False otherwise.
+ """
return self.onecmd_plus_hooks(arg + '\n')
self.pystate['run'] = run
@@ -1269,6 +1315,7 @@ class Cmd(cmd.Cmd):
interp.runcode(arg)
else:
def quit():
+ """Function callable from the interactive Python console to exit that environment and return to cmd2."""
raise EmbeddedConsoleExit
self.pystate['quit'] = quit
@@ -1330,6 +1377,13 @@ class Cmd(cmd.Cmd):
self.stdout.write(hi.pr())
def last_matching(self, arg):
+ """Return the last item from the history list that matches arg. Or if arg not provided, retern last item.
+
+ If not match is found, return None.
+
+ :param arg: str - text to search for in history
+ :return: str - last match, last item, or None, depending on arg.
+ """
try:
if arg:
return self.history.get(arg)[-1]
@@ -1481,6 +1535,18 @@ Edited files are run on close if the `autorun_on_edit` settable parameter is Tru
self.stdout.write("{}\n".format(help_str))
def read_file_or_url(self, fname):
+ """Open a file or URL for reading by the do_load() method.
+
+ This method methodically proceeds in the following path until it succeeds (or fails in the end):
+ 1) Try to open the file
+ 2) Try to open the URL if it looks like one
+ 3) Try to expand the ~ to create an absolute path for the filename
+ 4) Try to add the default extension to the expanded path
+ 5) Raise an error
+
+ :param fname: str - filename or URL
+ :return: stream or a file-like object pointing to the file or URL (or raise an exception if it couldn't open)
+ """
# TODO: not working on localhost
if os.path.isfile(fname):
result = open(fname, 'r')