On Tue, Nov 17, 2009 at 7:51 PM, William Stein <wst...@gmail.com> wrote:
> Can somebody referee this?     It's mainly code in the *notebook* --
> it doesn't seem possible to do something like the above on the command
> line without some deep internal change to Ipython.
>

Actually no, not that hard: ipython executes all  user  code inside a
dict created at initialization time.  One could replace this (today a
plain python dict) with another dict that would implement the
requested behavior.  This would spring variables into existence when a
KeyError was about to occur.

The command-line doesn't have the notion of a cell (yet, that will
hopefully change soon) but it could be toggled with a function call.

It's basically a matter of instantiating the initial ipython with a
custom user_ns dict that does the above, that should be all.  And
providing a magic (or even plain) function in the global namespace to
toggle this behavior on/off at runtime.

The attached file (run it as 'ipauto.py') shows how it could work, I
didn't implement the toggling and it's a quick hack, but the basic
idea is  there.  Here it is in action:

In [1]: %autocall 0
Automatic calling is: OFF

In [2]: x+y
Injecting x
Injecting y
Out[2]: x + y

In [3]: type(x)
Out[3]: <class 'sympy.core.symbol.Symbol'>

In [4]: x+3
Out[4]: 3 + x

In [5]: x**2+x*x
Out[5]: 2*x**2

In [6]: x+z**3
Injecting z
Out[6]: x + z**3


A couple of notes:

- It's key to disable autocalling for this to work, otherwise too many
false positives are triggered.  If this idea proves to have  wings, it
will be one more argument in favor of disabling autocalling (it just
has too many uncontrollable side effects).

- Unfortunately IPython as shipped needs a tiny patch for this to
work, due to a really silly omission.  The patch is a trivial 2-liner,
in case anyone wants to take this further for Sage:

(ipython-0.10)maqroll[0.10]> bzr diff
=== modified file 'IPython/Shell.py'
--- IPython/Shell.py    2009-04-14 20:12:02 +0000
+++ IPython/Shell.py    2009-11-18 09:03:01 +0000
@@ -1230,7 +1230,7 @@


 # This is the one which should be called by external code.
-def start(user_ns = None):
+def start(user_ns = None, user_global_ns = None):
     """Return a running shell instance, dealing with threading options.

     This is a factory function which will instantiate the proper IPython shell
@@ -1238,7 +1238,7 @@
     different GUI toolkits require different thread handling details."""

     shell = _select_shell(sys.argv)
-    return shell(user_ns = user_ns)
+    return shell(user_ns = user_ns, user_global_ns = user_global_ns)

 # Some aliases for backwards compatibility
 IPythonShell = IPShell



Cheers,

f

-- 
To post to this group, send an email to sage-devel@googlegroups.com
To unsubscribe from this group, send an email to 
sage-devel-unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/sage-devel
URL: http://www.sagemath.org
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import __builtin__

from sympy import var

class AutoNS(dict):
    def __getitem__(self, key):
        if key not in self and key not in self['__IP'].user_global_ns \
           and key not in __builtin__.__dict__:
            # inject
            print 'Injecting',key
            self[key] = var(key)
            
        return dict.__getitem__(self, key)

# main

import IPython.Shell

IPython.Shell.start(AutoNS(),{}).mainloop()

Reply via email to