123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- """Tests of tools for setting up interactive IPython sessions. """
- from sympy.interactive.session import (init_ipython_session,
- enable_automatic_symbols, enable_automatic_int_sympification)
- from sympy.core import Symbol, Rational, Integer
- from sympy.external import import_module
- from sympy.testing.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
- # WARNING: These tests will modify the existing IPython environment. IPython
- # uses a single instance for its interpreter, so there is no way to isolate
- # the test from another IPython session. It also means that if this test is
- # run twice in the same Python session it will fail. This isn't usually a
- # problem because the test suite is run in a subprocess by default, but if the
- # tests are run with subprocess=False it can pollute the current IPython
- # session. See the discussion in issue #15149.
- def test_automatic_symbols():
- # NOTE: Because of the way the hook works, you have to use run_cell(code,
- # True). This means that the code must have no Out, or it will be printed
- # during the tests.
- 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("a = %s" % symbol, True)
- assert symbol not in app.user_ns
- app.run_cell("a = type(%s)" % symbol, True)
- assert app.user_ns['a'] == Symbol
- app.run_cell("%s = Symbol('%s')" % (symbol, symbol), True)
- assert symbol in app.user_ns
- # Check that built-in names aren't overridden
- app.run_cell("a = all == __builtin__.all", True)
- assert "all" not in app.user_ns
- assert app.user_ns['a'] is True
- # Check that SymPy names aren't overridden
- app.run_cell("import sympy")
- app.run_cell("a = factorial == sympy.factorial", True)
- assert app.user_ns['a'] is True
- def test_int_to_Integer():
- # XXX: Warning, don't test with == here. 0.5 == Rational(1, 2) is True!
- app = init_ipython_session()
- app.run_cell("from sympy import Integer")
- app.run_cell("a = 1")
- assert isinstance(app.user_ns['a'], int)
- enable_automatic_int_sympification(app)
- app.run_cell("a = 1/2")
- assert isinstance(app.user_ns['a'], Rational)
- app.run_cell("a = 1")
- assert isinstance(app.user_ns['a'], Integer)
- app.run_cell("a = int(1)")
- assert isinstance(app.user_ns['a'], int)
- app.run_cell("a = (1/\n2)")
- assert app.user_ns['a'] == Rational(1, 2)
- # TODO: How can we test that the output of a SyntaxError is the original
- # input, not the transformed input?
- def test_ipythonprinting():
- # Initialize and setup IPython session
- app = init_ipython_session()
- app.run_cell("ip = get_ipython()")
- app.run_cell("inst = ip.instance()")
- app.run_cell("format = inst.display_formatter.format")
- app.run_cell("from sympy import Symbol")
- # Printing without printing extension
- app.run_cell("a = format(Symbol('pi'))")
- app.run_cell("a2 = format(Symbol('pi')**2)")
- # Deal with API change starting at IPython 1.0
- if int(ipython.__version__.split(".")[0]) < 1:
- assert app.user_ns['a']['text/plain'] == "pi"
- assert app.user_ns['a2']['text/plain'] == "pi**2"
- else:
- assert app.user_ns['a'][0]['text/plain'] == "pi"
- assert app.user_ns['a2'][0]['text/plain'] == "pi**2"
- # Load printing extension
- app.run_cell("from sympy import init_printing")
- app.run_cell("init_printing()")
- # Printing with printing extension
- app.run_cell("a = format(Symbol('pi'))")
- app.run_cell("a2 = format(Symbol('pi')**2)")
- # Deal with API change starting at IPython 1.0
- if int(ipython.__version__.split(".")[0]) < 1:
- assert app.user_ns['a']['text/plain'] in ('\N{GREEK SMALL LETTER PI}', 'pi')
- assert app.user_ns['a2']['text/plain'] in (' 2\n\N{GREEK SMALL LETTER PI} ', ' 2\npi ')
- else:
- assert app.user_ns['a'][0]['text/plain'] in ('\N{GREEK SMALL LETTER PI}', 'pi')
- assert app.user_ns['a2'][0]['text/plain'] in (' 2\n\N{GREEK SMALL LETTER PI} ', ' 2\npi ')
- def test_print_builtin_option():
- # Initialize and setup IPython session
- app = init_ipython_session()
- app.run_cell("ip = get_ipython()")
- app.run_cell("inst = ip.instance()")
- app.run_cell("format = inst.display_formatter.format")
- app.run_cell("from sympy import Symbol")
- app.run_cell("from sympy import init_printing")
- app.run_cell("a = format({Symbol('pi'): 3.14, Symbol('n_i'): 3})")
- # Deal with API change starting at IPython 1.0
- if int(ipython.__version__.split(".")[0]) < 1:
- text = app.user_ns['a']['text/plain']
- raises(KeyError, lambda: app.user_ns['a']['text/latex'])
- else:
- text = app.user_ns['a'][0]['text/plain']
- raises(KeyError, lambda: app.user_ns['a'][0]['text/latex'])
- # XXX: How can we make this ignore the terminal width? This test fails if
- # the terminal is too narrow.
- assert text in ("{pi: 3.14, n_i: 3}",
- '{n\N{LATIN SUBSCRIPT SMALL LETTER I}: 3, \N{GREEK SMALL LETTER PI}: 3.14}',
- "{n_i: 3, pi: 3.14}",
- '{\N{GREEK SMALL LETTER PI}: 3.14, n\N{LATIN SUBSCRIPT SMALL LETTER I}: 3}')
- # If we enable the default printing, then the dictionary's should render
- # as a LaTeX version of the whole dict: ${\pi: 3.14, n_i: 3}$
- app.run_cell("inst.display_formatter.formatters['text/latex'].enabled = True")
- app.run_cell("init_printing(use_latex=True)")
- app.run_cell("a = format({Symbol('pi'): 3.14, Symbol('n_i'): 3})")
- # Deal with API change starting at IPython 1.0
- if int(ipython.__version__.split(".")[0]) < 1:
- text = app.user_ns['a']['text/plain']
- latex = app.user_ns['a']['text/latex']
- else:
- text = app.user_ns['a'][0]['text/plain']
- latex = app.user_ns['a'][0]['text/latex']
- assert text in ("{pi: 3.14, n_i: 3}",
- '{n\N{LATIN SUBSCRIPT SMALL LETTER I}: 3, \N{GREEK SMALL LETTER PI}: 3.14}',
- "{n_i: 3, pi: 3.14}",
- '{\N{GREEK SMALL LETTER PI}: 3.14, n\N{LATIN SUBSCRIPT SMALL LETTER I}: 3}')
- assert latex == r'$\displaystyle \left\{ n_{i} : 3, \ \pi : 3.14\right\}$'
- # Objects with an _latex overload should also be handled by our tuple
- # printer.
- app.run_cell("""\
- class WithOverload:
- def _latex(self, printer):
- return r"\\LaTeX"
- """)
- app.run_cell("a = format((WithOverload(),))")
- # Deal with API change starting at IPython 1.0
- if int(ipython.__version__.split(".")[0]) < 1:
- latex = app.user_ns['a']['text/latex']
- else:
- latex = app.user_ns['a'][0]['text/latex']
- assert latex == r'$\displaystyle \left( \LaTeX,\right)$'
- app.run_cell("inst.display_formatter.formatters['text/latex'].enabled = True")
- app.run_cell("init_printing(use_latex=True, print_builtin=False)")
- app.run_cell("a = format({Symbol('pi'): 3.14, Symbol('n_i'): 3})")
- # Deal with API change starting at IPython 1.0
- if int(ipython.__version__.split(".")[0]) < 1:
- text = app.user_ns['a']['text/plain']
- raises(KeyError, lambda: app.user_ns['a']['text/latex'])
- else:
- text = app.user_ns['a'][0]['text/plain']
- raises(KeyError, lambda: app.user_ns['a'][0]['text/latex'])
- # Note : In Python 3 we have one text type: str which holds Unicode data
- # and two byte types bytes and bytearray.
- # Python 3.3.3 + IPython 0.13.2 gives: '{n_i: 3, pi: 3.14}'
- # Python 3.3.3 + IPython 1.1.0 gives: '{n_i: 3, pi: 3.14}'
- assert text in ("{pi: 3.14, n_i: 3}", "{n_i: 3, pi: 3.14}")
- def test_builtin_containers():
- # Initialize and setup IPython session
- app = init_ipython_session()
- app.run_cell("ip = get_ipython()")
- app.run_cell("inst = ip.instance()")
- app.run_cell("format = inst.display_formatter.format")
- app.run_cell("inst.display_formatter.formatters['text/latex'].enabled = True")
- app.run_cell("from sympy import init_printing, Matrix")
- app.run_cell('init_printing(use_latex=True, use_unicode=False)')
- # Make sure containers that shouldn't pretty print don't.
- app.run_cell('a = format((True, False))')
- app.run_cell('import sys')
- app.run_cell('b = format(sys.flags)')
- app.run_cell('c = format((Matrix([1, 2]),))')
- # Deal with API change starting at IPython 1.0
- if int(ipython.__version__.split(".")[0]) < 1:
- assert app.user_ns['a']['text/plain'] == '(True, False)'
- assert 'text/latex' not in app.user_ns['a']
- assert app.user_ns['b']['text/plain'][:10] == 'sys.flags('
- assert 'text/latex' not in app.user_ns['b']
- assert app.user_ns['c']['text/plain'] == \
- """\
- [1] \n\
- ([ ],)
- [2] \
- """
- assert app.user_ns['c']['text/latex'] == '$\\displaystyle \\left( \\left[\\begin{matrix}1\\\\2\\end{matrix}\\right],\\right)$'
- else:
- assert app.user_ns['a'][0]['text/plain'] == '(True, False)'
- assert 'text/latex' not in app.user_ns['a'][0]
- assert app.user_ns['b'][0]['text/plain'][:10] == 'sys.flags('
- assert 'text/latex' not in app.user_ns['b'][0]
- assert app.user_ns['c'][0]['text/plain'] == \
- """\
- [1] \n\
- ([ ],)
- [2] \
- """
- assert app.user_ns['c'][0]['text/latex'] == '$\\displaystyle \\left( \\left[\\begin{matrix}1\\\\2\\end{matrix}\\right],\\right)$'
- def test_matplotlib_bad_latex():
- # Initialize and setup IPython session
- app = init_ipython_session()
- app.run_cell("import IPython")
- app.run_cell("ip = get_ipython()")
- app.run_cell("inst = ip.instance()")
- app.run_cell("format = inst.display_formatter.format")
- app.run_cell("from sympy import init_printing, Matrix")
- app.run_cell("init_printing(use_latex='matplotlib')")
- # The png formatter is not enabled by default in this context
- app.run_cell("inst.display_formatter.formatters['image/png'].enabled = True")
- # Make sure no warnings are raised by IPython
- app.run_cell("import warnings")
- # IPython.core.formatters.FormatterWarning was introduced in IPython 2.0
- if int(ipython.__version__.split(".")[0]) < 2:
- app.run_cell("warnings.simplefilter('error')")
- else:
- app.run_cell("warnings.simplefilter('error', IPython.core.formatters.FormatterWarning)")
- # This should not raise an exception
- app.run_cell("a = format(Matrix([1, 2, 3]))")
- # issue 9799
- app.run_cell("from sympy import Piecewise, Symbol, Eq")
- app.run_cell("x = Symbol('x'); pw = format(Piecewise((1, Eq(x, 0)), (0, True)))")
- def test_override_repr_latex():
- # Initialize and setup IPython session
- app = init_ipython_session()
- app.run_cell("import IPython")
- app.run_cell("ip = get_ipython()")
- app.run_cell("inst = ip.instance()")
- app.run_cell("format = inst.display_formatter.format")
- app.run_cell("inst.display_formatter.formatters['text/latex'].enabled = True")
- app.run_cell("from sympy import init_printing")
- app.run_cell("from sympy import Symbol")
- app.run_cell("init_printing(use_latex=True)")
- app.run_cell("""\
- class SymbolWithOverload(Symbol):
- def _repr_latex_(self):
- return r"Hello " + super()._repr_latex_() + " world"
- """)
- app.run_cell("a = format(SymbolWithOverload('s'))")
- if int(ipython.__version__.split(".")[0]) < 1:
- latex = app.user_ns['a']['text/latex']
- else:
- latex = app.user_ns['a'][0]['text/latex']
- assert latex == r'Hello $\displaystyle s$ world'
|