]> granicus.if.org Git - python/commitdiff
Updated version of [ 558544 ] cmd.py: add instance-specific stdin/out
authorAnthony Baxter <anthonybaxter@gmail.com>
Thu, 6 Feb 2003 01:45:11 +0000 (01:45 +0000)
committerAnthony Baxter <anthonybaxter@gmail.com>
Thu, 6 Feb 2003 01:45:11 +0000 (01:45 +0000)
This patch adds stdin, stdout as optional arguments to the cmd.Cmd
constructor (defaulting to sys.stdin, sys.stdout), and changes the Cmd
methods throughout to use self.stdout.write() and self.stdin.foo for
output and input. This allows much greater flexibility for using cmd -
for instance, hooking it into a telnet server.

Patch for library module and for documentation.

Doc/lib/libcmd.tex
Lib/cmd.py

index 59d573fba9a413d366654a04614cbf3acabede1b..4b2af91dff32dc78a178934a1b966ac932193c94 100644 (file)
@@ -11,17 +11,23 @@ line-oriented command interpreters.  These are often useful for
 test harnesses, administrative tools, and prototypes that will
 later be wrapped in a more sophisticated interface.
 
-\begin{classdesc}{Cmd}{\optional{completekey}}
+\begin{classdesc}{Cmd}{\optional{completekey},\optional{stdin},\optional{stdout}}
 A \class{Cmd} instance or subclass instance is a line-oriented
 interpreter framework.  There is no good reason to instantiate
 \class{Cmd} itself; rather, it's useful as a superclass of an
 interpreter class you define yourself in order to inherit
 \class{Cmd}'s methods and encapsulate action methods.
 
-The optional argument is the \refmodule{readline} name of a completion
-key; it defaults to \kbd{Tab}. If \var{completekey} is not \code{None}
-and \module{readline} is available, command completion is done
-automatically.
+The optional argument \var{completekey} is the \refmodule{readline} name
+of a completion key; it defaults to \kbd{Tab}. If \var{completekey} is
+not \code{None} and \module{readline} is available, command completion
+is done automatically.
+
+The optional arguments \var{stdin} and \var{stdout} specify the 
+input and output file objects that the Cmd instance or subclass 
+instance will use for input and output. If not specified, they
+will default to \var{sys.stdin} and \var{sys.stdout}.
+
 \end{classdesc}
 
 \subsection{Cmd Objects}
index 592990310ba4d9baa137b4803562c75e24c0e86e..bc91c0081e93a38936bd6fe75810e415b7194e44 100644 (file)
@@ -45,7 +45,7 @@ These interpreters use raw_input; thus, if the readline module is loaded,
 they automatically support Emacs-like command history and editing features.
 """
 
-import string, sys
+import string
 
 __all__ = ["Cmd"]
 
@@ -76,15 +76,26 @@ class Cmd:
     nohelp = "*** No help on %s"
     use_rawinput = 1
 
-    def __init__(self, completekey='tab'):
+    def __init__(self, completekey='tab', stdin=None, stdout=None):
         """Instantiate a line-oriented interpreter framework.
 
-        The optional argument is the readline name of a completion key;
-        it defaults to the Tab key. If completekey is not None and the
-        readline module is available, command completion is done
-        automatically.
+        The optional argument 'completekey' is the readline name of a 
+        completion key; it defaults to the Tab key. If completekey is 
+        not None and the readline module is available, command completion 
+        is done automatically. The optional arguments stdin and stdout
+        specify alternate input and output file objects; if not specified,
+        sys.stdin and sys.stdout are used.
 
         """
+        import sys
+        if stdin is not None:
+            self.stdin = stdin
+        else:
+            self.stdin = sys.stdin
+        if stdout is not None:
+            self.stdout = stdout
+        else:
+            self.stdout = sys.stdout
         self.cmdqueue = []
         self.completekey = completekey
 
@@ -99,7 +110,7 @@ class Cmd:
         if intro is not None:
             self.intro = intro
         if self.intro:
-            print self.intro
+            self.stdout.write(str(self.intro)+"\n")
         stop = None
         while not stop:
             if self.cmdqueue:
@@ -111,9 +122,9 @@ class Cmd:
                     except EOFError:
                         line = 'EOF'
                 else:
-                    sys.stdout.write(self.prompt)
-                    sys.stdout.flush()
-                    line = sys.stdin.readline()
+                    self.stdout.write(self.prompt)
+                    self.stdout.flush()
+                    line = self.stdin.readline()
                     if not len(line):
                         line = 'EOF'
                     else:
@@ -215,7 +226,7 @@ class Cmd:
         returns.
 
         """
-        print '*** Unknown syntax:', line
+        self.stdout.write('*** Unknown syntax: %s\n'%line)
 
     def completedefault(self, *ignored):
         """Method called to complete an input line when no command-specific
@@ -284,11 +295,11 @@ class Cmd:
                 try:
                     doc=getattr(self, 'do_' + arg).__doc__
                     if doc:
-                        print doc
+                        self.stdout.write("%s\n"%str(doc))
                         return
                 except AttributeError:
                     pass
-                print self.nohelp % (arg,)
+                self.stdout.write("%s\n"%str(self.nohelp % (arg,)))
                 return
             func()
         else:
@@ -315,18 +326,18 @@ class Cmd:
                         cmds_doc.append(cmd)
                     else:
                         cmds_undoc.append(cmd)
-            print self.doc_leader
+            self.stdout.write("%s\n"%str(self.doc_leader))
             self.print_topics(self.doc_header,   cmds_doc,   15,80)
             self.print_topics(self.misc_header,  help.keys(),15,80)
             self.print_topics(self.undoc_header, cmds_undoc, 15,80)
 
     def print_topics(self, header, cmds, cmdlen, maxcol):
         if cmds:
-            print header
+            self.stdout.write("%s\n"%str(header))
             if self.ruler:
-                print self.ruler * len(header)
+                self.stdout.write("%s\n"%str(self.ruler * len(header)))
             self.columnize(cmds, maxcol-1)
-            print
+            self.stdout.write("\n")
 
     def columnize(self, list, displaywidth=80):
         """Display a list of strings as a compact set of columns.
@@ -335,7 +346,7 @@ class Cmd:
         Columns are separated by two spaces (one was not legible enough).
         """
         if not list:
-            print "<empty>"
+            self.stdout.write("<empty>\n")
             return
         nonstrings = [i for i in range(len(list))
                         if not isinstance(list[i], str)]
@@ -344,7 +355,7 @@ class Cmd:
                               ", ".join(map(str, nonstrings)))
         size = len(list)
         if size == 1:
-            print list[0]
+            self.stdout.write('%s\n'%str(list[0]))
             return
         # Try every row count from 1 upwards
         for nrows in range(1, len(list)):
@@ -382,4 +393,4 @@ class Cmd:
                 del texts[-1]
             for col in range(len(texts)):
                 texts[col] = texts[col].ljust(colwidths[col])
-            print "  ".join(texts)
+            self.stdout.write("%s\n"%str("  ".join(texts)))