# put this file in .ipython/profile_[xxxxxx]/startup

__all__ = []
from IPython.core.magic import (Magics, magics_class, line_magic,
                                        cell_magic, line_cell_magic)
import re
@magics_class
class IsolateMagics(Magics):
    @cell_magic('isolate')
    def isolate(self, line, cell):
        pre, post = self.parser(line)
        print 'pre', pre
        print 'post', post
        ns = self.shell.user_ns.copy()
        for symbol in pre:
            assert symbol in ns
        exec (cell, ns)
        for symbol in post:
            self.shell.user_ns[symbol] = ns[symbol]

    def parser(self, line):
        clauses = re.findall('(\s*(pre|post)\(([^)]*)\))', line)
        pre = []
        post = []
        for c in clauses:
            if c[1].lower() == 'pre':
                pre = c[2].split(',')
            elif c[1].lower() == 'post':
                post = c[2].split(',')
        return pre, post

        eval(cell, locals)

# In order to actually use these magics, you must register them with a
# running IPython.  This code must be placed in a file that is loaded
# once
# IPython is up and running:
ip = get_ipython()
# You can register the class itself without instantiating it.  IPython
# will
# call the default constructor on it.
ip.register_magics(IsolateMagics)

@@ -1,58 +1,4 @@
-# put this file in .ipython/profile_%5Bxxxxxx%5D/startup%0A%0A
 __al
@@ -151,16 +151,109 @@
 port re%0A
+%0Aclass PreConditionError(NameError):%0A    pass%0Aclass PostConditionError(NameError):%0A    pass%0A%0A
 @magics_
@@ -346,16 +346,32 @@
 ne, cell
+, protected=True
 ):%0A     
@@ -403,24 +403,25 @@
 r(line)%0A
+%0A
         
 print 'p
@@ -416,90 +416,516 @@
     
-print 'pre', pre%0A        print 'post', post%0A        ns = self.shell.user_ns.copy()
+oldnames = set(self.shell.user_ns.keys())%0A        badnames = %5B%5D%0A%0A        for symbol in pre:%0A            if symbol.startswith('@'):%0A                continue%0A            if not symbol in oldnames:%0A                badnames.append(symbol)%0A        if len(badnames) %3E 0:%0A            raise PreConditionError(%22The following variables are undefined: %25s%22,%0A                    str(badnames))%0A%0A        # the juice is here%0A        # ipython processes other magics%0A        self.shell.run_cell(cell)%0A%0A        badnames = %5B%5D%0A
 %0A   
@@ -936,34 +936,35 @@
  for symbol in p
-re
+ost
 :%0A            as
@@ -965,60 +965,449 @@
     
-assert symbol in ns%0A        exec (cell, ns
+if symbol.startswith('@'):%0A                continue%0A            if not symbol in self.shell.user_ns:%0A                badnames.append(symbol)%0A%0A        # alright, due to #7256 we can't tell if run_cell failed or not%0A        # so on failures we get a second error due to post-conditions.%0A        if len(badnames) %3E 0:%0A            raise PostConditionError(%22The following variables are undefined: %25s%22,%0A                    str(badnames)
 )%0A
+%0A
         
 for 
@@ -1402,34 +1402,83 @@
         
-for
+if protected:%0A            # now remove extra
  symbol
+s
  in 
-post
+the user ns
 :%0A      
@@ -1475,32 +1475,46 @@
 ns:%0A            
+for symbol in 
 self.shell.user_
@@ -1519,29 +1519,134 @@
 r_ns
-%5Bsymbol%5D = ns%5B
+.keys():%0A                if symbol not in post and symbol not in oldnames:%0A                    self.shell.user_ns.pop(
 symbol
-%5D
+)%0A
 %0A%0A  
@@ -1856,16 +1856,36 @@
    pre =
+ %5Ba.strip() for a in
  c%5B2%5D.sp
@@ -1882,34 +1882,36 @@
 in c%5B2%5D.split(',
+ 
 ')
+%5D
 %0A            eli
@@ -1958,16 +1958,36 @@
   post =
+ %5Ba.strip() for a in
  c%5B2%5D.sp
@@ -1992,18 +1992,20 @@
 split(',
+ 
 ')
+%5D
 %0A       
@@ -2027,35 +2027,8 @@
 st%0A%0A
-        eval(cell, locals)%0A
 %0A# I

support nested cell magics