Fix

[ 924301 ] A leak case with cmd.py & readline & exception

by ensuring that the readline completion function is always reset
even in the case of an exception being raised.  As a bonus, this
makes the documentation for pre & postloop accurate again.
diff --git a/Lib/cmd.py b/Lib/cmd.py
index 0bb0c03..3ef7c8f 100644
--- a/Lib/cmd.py
+++ b/Lib/cmd.py
@@ -107,32 +107,49 @@
         """
 
         self.preloop()
-        if intro is not None:
-            self.intro = intro
-        if self.intro:
-            self.stdout.write(str(self.intro)+"\n")
-        stop = None
-        while not stop:
-            if self.cmdqueue:
-                line = self.cmdqueue.pop(0)
-            else:
-                if self.use_rawinput:
-                    try:
-                        line = raw_input(self.prompt)
-                    except EOFError:
-                        line = 'EOF'
+        if self.use_rawinput and self.completekey:
+            try:
+                import readline
+                self.old_completer = readline.get_completer()
+                readline.set_completer(self.complete)
+                readline.parse_and_bind(self.completekey+": complete")
+            except ImportError:
+                pass
+        try:
+            if intro is not None:
+                self.intro = intro
+            if self.intro:
+                self.stdout.write(str(self.intro)+"\n")
+            stop = None
+            while not stop:
+                if self.cmdqueue:
+                    line = self.cmdqueue.pop(0)
                 else:
-                    self.stdout.write(self.prompt)
-                    self.stdout.flush()
-                    line = self.stdin.readline()
-                    if not len(line):
-                        line = 'EOF'
+                    if self.use_rawinput:
+                        try:
+                            line = raw_input(self.prompt)
+                        except EOFError:
+                            line = 'EOF'
                     else:
-                        line = line[:-1] # chop \n
-            line = self.precmd(line)
-            stop = self.onecmd(line)
-            stop = self.postcmd(stop, line)
-        self.postloop()
+                        self.stdout.write(self.prompt)
+                        self.stdout.flush()
+                        line = self.stdin.readline()
+                        if not len(line):
+                            line = 'EOF'
+                        else:
+                            line = line[:-1] # chop \n
+                line = self.precmd(line)
+                stop = self.onecmd(line)
+                stop = self.postcmd(stop, line)
+            self.postloop()
+        finally:
+            if self.use_rawinput and self.completekey:
+                try:
+                    import readline
+                    readline.set_completer(self.old_completer)
+                except ImportError:
+                    pass
+            
 
     def precmd(self, line):
         """Hook method executed just before the command line is
@@ -147,27 +164,15 @@
 
     def preloop(self):
         """Hook method executed once when the cmdloop() method is called."""
-        if self.completekey:
-            try:
-                import readline
-                self.old_completer = readline.get_completer()
-                readline.set_completer(self.complete)
-                readline.parse_and_bind(self.completekey+": complete")
-            except ImportError:
-                pass
+        pass
 
     def postloop(self):
         """Hook method executed once when the cmdloop() method is about to
         return.
 
         """
-        if self.completekey:
-            try:
-                import readline
-                readline.set_completer(self.old_completer)
-            except ImportError:
-                pass
-
+        pass
+    
     def parseline(self, line):
         """Parse the line into a command name and a string containing
         the arguments.  Returns a tuple containing (command, args, line).