Automatically construct missing symbols in isympy #643

Merged
merged 1 commit into from Oct 21, 2011

Conversation

Projects
None yet
4 participants
Member

mattpap commented Oct 10, 2011

By default, if a symbol was not defined before code execution, NameError
exception is raised:

$ bin/isympy -q
IPython console for SymPy 0.7.1-git (Python 2.6.6-64-bit) (ground types: gmpy)

In [1]: 'a' in globals()
Out[1]: False

In [2]: integrate(a*x, x)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/home/mateusz/repo/git/sympy/<ipython-input-2-26a8cf347e13> in <module>()
----> 1 integrate(a*x, x)

NameError: name 'a' is not defined

In [3]: 'a' in globals()
Out[3]: False

In [4]:
Do you really want to exit ([y]/n)?
Exiting ...

However, in IPython (>= 0.11) if -a or --auto command line option is
specified, all NameError exceptions that are raised in the interpreter's
stack frame are ignored and appropriate symbols constructed and injected
into the global namespace, and code rerun:

$ bin/isympy -q -a
IPython console for SymPy 0.7.1-git (Python 2.6.6-64-bit) (ground types: gmpy)

In [1]: 'a' in globals()
Out[1]: False

In [2]: integrate(a*x, x)
Out[2]:
   2
a⋅x
────
 2

In [3]: 'a' in globals()
Out[3]: True

Note that any other NameError exceptions are handled by standard
IPython traceback printing procedures:

In [4]: def f(): return b

In [5]: f()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/home/mateusz/repo/git/sympy/<ipython-input-5-0ec059b9bfe1> in <module>()
----> 1 f()

/home/mateusz/repo/git/sympy/<ipython-input-4-ca2b6b0871d2> in f()
----> 1 def f(): return b

NameError: global name 'b' is not defined

@smichr smichr commented on an outdated diff Oct 10, 2011

sympy/interactive/session.py
# don't draw IPython banner during initialization:
app.display_banner = False
app.initialize(argv)
+
+ import re
+ re_nameerror = re.compile("name '(?P<symbol>[A-Za-z_][A-Za-z0-9_]*)' is not defined")
+
+ def handler(self, etype, value, tb, tb_offset=None):
+ """Handle NameError exception and allow to inject missing symbols. """
@smichr

smichr Oct 10, 2011

Member

'allow to inject' -> 'allow injection of'

@smichr smichr commented on the diff Oct 10, 2011

sympy/interactive/session.py
@@ -112,7 +141,7 @@ def _init_python_session():
return SymPyConsole()
def init_session(ipython=None, pretty_print=True, order=None,
- use_unicode=None, quiet=False, argv=[]):
+ use_unicode=None, quiet=False, auto=False, argv=[]):
@smichr

smichr Oct 10, 2011

Member

this changes the order of arguments...should it go after argv?

@mattpap

mattpap Oct 10, 2011

Member

init_session() is only used in isympy and in this case keyword arguments are used, so this doesn't matter.

Member

smichr commented Oct 10, 2011

Should the isympy startup message been changed? Doesn't it print a message abouot symbols that were created "These commands were executed:"

Owner

asmeurer commented Oct 10, 2011

Nice. I've often wondered if this was possible.

Some comments:

  • It would be nice if this were done on top of and in the spirit of (i.e., better documentation for the option) pull request #640.
  • If the IPython version is less than 0.11, or the console is Python, isympy should either emit a warning or fail completely when given this option.
  • Regarding the documentation of the option, I would mention that it only works for the top level namespace, requires IPython 0.11 or higher, that it is only intended for interactive, calculator style, usage, that it won't override names that already exist (like the QCOSINE names), and that assumptions on the variables will be the default. Perhaps also note that you can delete existing names using del and you can check if a name is defined using 'name' in globals() (though these are advanced, so maybe they should go in some other documentation).

But other than that, I like this. I definitely will be using it whenever I use SymPy to do my homework, which tends to have all kinds of variable names which I annoyingly have to define.

Owner

certik commented Oct 10, 2011

Test results html report: http://pastehtml.com/view/ba52umihi.html

Summary: All tests have passed. You can merge with master.

Automatic review by sympy-bot.

Owner

certik commented Oct 10, 2011

Test results html report: http://pastehtml.com/view/ba53suxrq.html

Note A custom interpreter was used: python3

Summary: All tests have passed. You can merge with master.

Automatic review by sympy-bot.

Owner

certik commented Oct 10, 2011

I like this too. +1 from me.

Member

mattpap commented Oct 10, 2011

I fixed the docstring.

Member

smichr commented Oct 11, 2011

I don't think changing the startup message is necessary. Those commands are run, but you just get more with the -a option. So I defer to @asmeurer for final ok since has pending suggestions.

Owner

asmeurer commented Oct 12, 2011

If you don't want to do the documentation, I will update my branch at #640 for it after this gets in.

But I do think it should warn or fail without IPython 0.11.

Member

mattpap commented Oct 12, 2011

But I do think it should warn or fail without IPython 0.11.

I know it would be better this way, but then we will have to add IPython handling code into isympy. I was thinking about moving isympy's code into sympy (keep all logic in one place) and then just run sympy.interative.isympy(sys.argv) from bin/isympy (similarly as we do with lib2to3). But to do that we have to figure out how to handle configuration of caching and ground types which are configured as soon as sympy is imported for the first time.

Owner

asmeurer commented Oct 12, 2011

So just put it in init_session for now. It won't be the cleanest, but at least it will be more or less the right thing from the user's end.

I agree that it would be better to have everything in the interactive module. I think the solution would be to move away from using environment variables to define caching, ground types, and debugging (they can still be used to set them, but they won't be what is used internally).

Owner

asmeurer commented Oct 12, 2011

I think what we can do is create functions like _should_enable_cache() in sympy/interactive/session.py (or somewhere similar), that will not require sympy to be imported to access, and then import those at the top of sympy/__init__.py, run them, set the variable, and then delete the helper function.

Hopefully there aren't any flaws in that idea that I'm missing.

@mattpap mattpap Automatically construct missing symbols in isympy
By default, if a symbol was not defined before code execution, NameError
exception is raised:

$ bin/isympy -q
IPython console for SymPy 0.7.1-git (Python 2.6.6-64-bit) (ground types: gmpy)

In [1]: 'a' in globals()
Out[1]: False

In [2]: integrate(a*x, x)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/home/mateusz/repo/git/sympy/<ipython-input-2-26a8cf347e13> in <module>()
----> 1 integrate(a*x, x)

NameError: name 'a' is not defined

In [3]: 'a' in globals()
Out[3]: False

In [4]:
Do you really want to exit ([y]/n)?
Exiting ...

However, in IPython (>= 0.11) if -a or --auto command line option is
specified, all NameError exceptions that are raised in the interpreter's
stack frame are ignored and appropriate symbols constructed and injected
into the global namespace, and code rerun:

$ bin/isympy -q -a
IPython console for SymPy 0.7.1-git (Python 2.6.6-64-bit) (ground types: gmpy)

In [1]: 'a' in globals()
Out[1]: False

In [2]: integrate(a*x, x)
Out[2]:
   2
a⋅x
────
 2

In [3]: 'a' in globals()
Out[3]: True

Note that any other NameError exceptions are handled by standard
IPython traceback printing procedures:

In [4]: def f(): return b

In [5]: f()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/home/mateusz/repo/git/sympy/<ipython-input-5-0ec059b9bfe1> in <module>()
----> 1 f()

/home/mateusz/repo/git/sympy/<ipython-input-4-ca2b6b0871d2> in f()
----> 1 def f(): return b

NameError: global name 'b' is not defined
cd62a54
Owner

certik commented Oct 21, 2011

This looks good to me. Thanks. I am merging it, let's improve upon it.

@certik certik added a commit that referenced this pull request Oct 21, 2011

@certik certik Merge pull request #643 from mattpap/auto_symbols
Automatically construct missing symbols in isympy
9028973

@certik certik merged commit 9028973 into sympy:master Oct 21, 2011

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment