From 2b49e4d4e1fda3db1125678f13083c8c6beeaa20 2011-04-11 00:28:46
From: Thomas Kluyver <takowl@gmail.com>
Date: 2011-04-11 00:28:46
Subject: [PATCH] Replace magic exit function with exit subclassing IPyAutocall. Credit to David Warde-Farley (@dwf) for tackling this issue.

---

diff --git a/IPython/core/autocall.py b/IPython/core/autocall.py
index ff2d3a6..d02e7ae 100644
--- a/IPython/core/autocall.py
+++ b/IPython/core/autocall.py
@@ -7,6 +7,7 @@ Authors:
 
 * Brian Granger
 * Fernando Perez
+* Thomas Kluyver
 
 Notes
 -----
@@ -34,8 +35,11 @@ class IPyAutocall(object):
     This happens regardless of 'autocall' variable state. Use this to
     develop macro-like mechanisms.
     """
+    _ip = None
+    def __init__(self, ip=None):
+        self._ip = ip
     
-    def set_ip(self,ip):
+    def set_ip(self, ip):
         """ Will be used to set _ip point to current ipython instance b/f call
         
         Override this method if you don't want this to happen.
@@ -43,3 +47,10 @@ class IPyAutocall(object):
         """
         self._ip = ip
 
+
+class ExitAutocall(IPyAutocall):
+    """An autocallable object which will be added to the user namespace so that
+    exit, exit(), quit or quit() are all valid ways to close the shell."""
+    
+    def __call__(self):
+        self._ip.ask_exit()
diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py
index ccbda3c..17998fa 100644
--- a/IPython/core/interactiveshell.py
+++ b/IPython/core/interactiveshell.py
@@ -39,6 +39,7 @@ from IPython.core import prefilter
 from IPython.core import shadowns
 from IPython.core import ultratb
 from IPython.core.alias import AliasManager
+from IPython.core.autocall import ExitAutocall
 from IPython.core.builtin_trap import BuiltinTrap
 from IPython.core.compilerop import CachingCompiler
 from IPython.core.display_trap import DisplayTrap
@@ -1023,6 +1024,10 @@ class InteractiveShell(Configurable, Magic):
 
         # Store myself as the public api!!!
         ns['get_ipython'] = self.get_ipython
+        
+        exiter = ExitAutocall(self)
+        for n in ['exit', 'Exit', 'quit', 'Quit']:
+            ns[n] = exiter
 
         # Sync what we've added so far to user_ns_hidden so these aren't seen
         # by %who
diff --git a/IPython/core/magic.py b/IPython/core/magic.py
index 042618b..f6febd4 100644
--- a/IPython/core/magic.py
+++ b/IPython/core/magic.py
@@ -2503,14 +2503,6 @@ Defaulting color scheme to 'NoColor'"""
         ptformatter.pprint = bool(1 - ptformatter.pprint)
         print 'Pretty printing has been turned', \
               ['OFF','ON'][ptformatter.pprint]
-                
-    def magic_Exit(self, parameter_s=''):
-        """Exit IPython."""
-
-        self.shell.ask_exit()
-
-    # Add aliases as magics so all common forms work: exit, quit, Exit, Quit.
-    magic_exit = magic_quit = magic_Quit = magic_Exit
 
     #......................................................................
     # Functions to implement unix shell-type things