Permalink
Browse files

Fixed isympy -a and added a test (#3048)

  • Loading branch information...
1 parent 0f7f4de commit 4903deb8f275a21688db952376658f144b30cdc9 @mattpap mattpap committed Apr 4, 2012
Showing with 67 additions and 29 deletions.
  1. +34 −29 sympy/interactive/session.py
  2. +33 −0 sympy/interactive/tests/test_ipython.py
@@ -68,7 +68,35 @@ def _make_message(ipython=True, quiet=False, source=None):
return message
-def _init_ipython_session(argv=[], auto=False):
+def enable_automatic_symbols(app):
+ """Allow IPython to automatially create symbols (``isympy -a``). """
+ 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 :exc:`NameError` exception and allow injection of missing symbols. """
+ if etype is NameError and tb.tb_next and not tb.tb_next.tb_next:
+ match = re_nameerror.match(str(value))
+
+ if match is not None:
+ # XXX: Make sure Symbol is in scope. Otherwise you'll get infinite recursion.
+ self.run_cell("%(symbol)s = Symbol('%(symbol)s')" %
+ {'symbol': match.group("symbol")}, store_history=False)
+
+ try:
+ code = self.user_ns['In'][-1]
+ except (KeyError, IndexError):
+ pass
+ else:
+ self.run_cell(code, store_history=False)
+ return None
+
+ stb = self.InteractiveTB.structured_traceback(etype, value, tb, tb_offset=tb_offset)
+ self._showtraceback(etype, value, stb)
+
+ app.shell.set_custom_exc((NameError,), _handler)
+
+def init_ipython_session(argv=[], auto=False):
"""Construct new IPython session. """
import IPython
@@ -81,38 +109,15 @@ def _init_ipython_session(argv=[], auto=False):
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 :exc:`NameError` exception and allow injection of missing symbols. """
- if etype is NameError and tb.tb_next and not tb.tb_next.tb_next:
- match = re_nameerror.match(str(value))
-
- if match is not None:
- self.run_cell("%(symbol)s = Symbol('%(symbol)s')" %
- {'symbol': match.group("symbol")}, store_history=False)
-
- try:
- code = self.user_ns_hidden['In'][-1]
- except (KeyError, IndexError):
- pass
- else:
- self.run_cell(code, store_history=False)
- return None
-
- stb = self.InteractiveTB.structured_traceback(etype, value, tb, tb_offset=tb_offset)
- self._showtraceback(etype, value, stb)
-
if auto:
- app.shell.set_custom_exc((NameError,), _handler)
+ enable_automatic_symbols(app)
return app.shell
else:
from IPython.Shell import make_IPython
return make_IPython(argv)
-def _init_python_session():
+def init_python_session():
"""Construct new Python session. """
from code import InteractiveConsole
@@ -222,7 +227,7 @@ def init_session(ipython=None, pretty_print=True, order=None,
in_ipython = False
if ipython is False:
- ip = _init_python_session()
+ ip = init_python_session()
mainloop = ip.interact
else:
try:
@@ -231,7 +236,7 @@ def init_session(ipython=None, pretty_print=True, order=None,
if ipython is not True:
if not quiet:
print no_ipython
- ip = _init_python_session()
+ ip = init_python_session()
mainloop = ip.interact
else:
raise RuntimeError("IPython is not available on this system")
@@ -251,7 +256,7 @@ def init_session(ipython=None, pretty_print=True, order=None,
if ip is not None:
in_ipython = True
else:
- ip = _init_ipython_session(argv=argv, auto=auto)
+ ip = init_ipython_session(argv=argv, auto=auto)
if IPython.__version__ >= '0.11':
# runsource is gone, use run_cell instead, which doesn't
@@ -0,0 +1,33 @@
+"""Tests of tools for setting up interactive IPython sessions. """
+
+from sympy.interactive.session import init_ipython_session, enable_automatic_symbols
+
+from sympy.core import Symbol
+from sympy.external import import_module
+from sympy.utilities.pytest import raises
+
+# TODO: The code below could be made more granular with something like:
+#
+# @requires('IPython', version=">=0.11")
+# def test_automatic_symbols(ipython):
+
+ipython = import_module("IPython", min_module_version="0.11")
+
+if not ipython:
+ #bin/test will not execute any tests now
+ disabled = True
+
+# TODO: Add tests that would verify that enable_automatic_symbols() doesn't
+# break anything. For example typing `factorial` or `all` in an interpreter
+# shouldn't result in a new symbol.
+def test_automatic_symbols():
+ app = init_ipython_session()
+ app.run_cell("from sympy import *")
+
+ enable_automatic_symbols(app)
+
+ symbol = "verylongsymbolname"
+ assert symbol not in app.user_ns
+ app.run_cell(symbol, False)
+ assert symbol in app.user_ns
+ assert isinstance(app.user_ns[symbol], Symbol)

0 comments on commit 4903deb

Please sign in to comment.