[IPython-dev] strange namespace issue

Darren Dale dd55 at cornell.edu
Tue Sep 11 13:56:14 EDT 2007


On Tuesday 11 September 2007 01:18:04 pm Fernando Perez wrote:
> On 9/11/07, Darren Dale <dd55 at cornell.edu> wrote:
> > Aha! The problem was introduced in svn 2754, when iplib, FakeModule and
> > Magic were modified. Try doing the following with svn 2753 and then 2754:
> >
> > $ ipython -gthread
> > In [1]: run pygtk-demo.py
> > # interact with the pygtk-demo window
> >
> > I get errors with 2754, but not with 2753.
>
> Lovely.  Those are the changes I made for doctest to work correctly,
> and the more frustrating part is that the new code is in a sense much
> more correct.  Instead of building a fake contraption that tries to
> look like a module, we actually put a true module object in the
> execution namespace of the called script.  This could not be done back
> in the days of python 2.1, but now (post 2.2) I can do that, which
> should be a much better solution.
>
> The new code did pass all the pickle tests I had lying around as well
> as enabling doctest to work correctly.  I'm totally confused as to why
> it may have broken threading support, in particular in that strange
> way you are seeing.
>
> I'm convinced that having a real module in there is the right thing to
> do.  I'd be very grateful if anyone has an idea on how to address the
> GUI problems Darren is seeing without losing the doctest support.
> Very grateful.

No ideas yet, but here is the svn diff -r 2753:2754:

Index: IPython/iplib.py
===================================================================
--- IPython/iplib.py    (revision 2753)
+++ IPython/iplib.py    (revision 2754)
@@ -2391,8 +2391,24 @@
         """A safe version of the builtin execfile().

         This version will never throw an exception, and knows how to handle
-        ipython logs as well."""
+        ipython logs as well.

+        :Parameters:
+          fname : string
+            Name of the file to be executed.
+
+          where : tuple
+            One or two namespaces, passed to execfile() as (globals,locals).
+            If only one is given, it is passed as both.
+
+        :Keywords:
+          islog : boolean (False)
+
+          quiet : boolean (True)
+
+          exit_ignore : boolean (False)
+          """
+
         def syspath_cleanup():
             """Internal cleanup routine for sys.path."""
             if add_dname:
@@ -2424,6 +2440,7 @@
         kw.setdefault('islog',0)
         kw.setdefault('quiet',1)
         kw.setdefault('exit_ignore',0)
+
         first = xfile.readline()
         loghead = str(self.loghead_tpl).split('\n',1)[0].strip()
         xfile.close()
Index: IPython/FakeModule.py
===================================================================
--- IPython/FakeModule.py       (revision 2753)
+++ IPython/FakeModule.py       (revision 2754)
@@ -25,28 +25,19 @@
     sessions.

     Do NOT use this code for anything other than this IPython private 
hack."""
-    def __init__(self,adict):

+    def __init__(self,adict=None):
+
+        # tmp to force __dict__ instance creation, else self.__dict__ fails
+        self.__iptmp = None
+
         # It seems pydoc (and perhaps others) needs any module instance to
         # implement a __nonzero__ method, so we add it if missing:
-        if '__nonzero__' not in adict:
-            def __nonzero__():
-                return 1
-            adict['__nonzero__'] = __nonzero__
+        self.__dict__.setdefault('__nonzero__',lambda : True)
+        self.__dict__.setdefault('__file__',__file__)

-            self._dict_ = adict
+        # cleanup our temp trick
+        del self.__iptmp

-        # modules should have a __file__ attribute
-        adict.setdefault('__file__',__file__)
-
-    def __getattr__(self,key):
-        try:
-            return self._dict_[key]
-        except KeyError, e:
-            raise AttributeError("FakeModule object has no attribute %s" % e)
-
-    def __str__(self):
-        return "<IPython.FakeModule instance>"
-
-    def __repr__(self):
-        return str(self)
+        if adict is not None:
+            self.__dict__.update(adict)
Index: IPython/Magic.py
===================================================================
--- IPython/Magic.py    (revision 2753)
+++ IPython/Magic.py    (revision 2754)
@@ -1522,12 +1522,15 @@
             prog_ns = self.shell.user_ns
             __name__save = self.shell.user_ns['__name__']
             prog_ns['__name__'] = '__main__'
+            main_mod = FakeModule(prog_ns)
         else:
             if opts.has_key('n'):
                 name = os.path.splitext(os.path.basename(filename))[0]
             else:
                 name = '__main__'
-            prog_ns = {'__name__':name}
+            main_mod = FakeModule()
+            prog_ns = main_mod.__dict__
+            prog_ns['__name__'] = name

         # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
         # set the __file__ global in the script's namespace
@@ -1540,7 +1543,7 @@
         else:
             restore_main = False

-        sys.modules[prog_ns['__name__']] = FakeModule(prog_ns)
+        sys.modules[prog_ns['__name__']] = main_mod

         stats = None
         try:



More information about the IPython-dev mailing list