Crash when doing "import math; math.sin?" #10229

Closed
jdemeyer opened this Issue Feb 1, 2017 · 4 comments

Comments

Projects
None yet
4 participants
@jdemeyer
Contributor

jdemeyer commented Feb 1, 2017

In the IPython session below, I executed

%config Application.verbose_crash=True

and

import math; math.sin?

When doing this, IPython crashes.

Below, you will see In [3]: import math; math.sin? but I have no idea where that came from. That was just displayed automatically.

Python 2.7.13 (default, Jan 25 2017, 11:01:10) 
Type "copyright", "credits" or "license" for more information.

IPython 5.2.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: %config Application.verbose_crash=True

In [2]: import math; math.sin?
Object `math.sin` not found.

In [3]: import math; math.sin?
---------------------------------------------------------------------------
---------------------------------------------------------------------------
AssertionError   Python 2.7.13: /usr/local/src/sage-config/local/bin/python
                                                   Wed Feb  1 10:17:47 2017
A problem occurred executing Python code.  Here is the sequence of function
calls leading up to the error, with the most recent (innermost) call last.
/usr/local/src/sage-config/local/bin/ipython in <module>()
      1 #!/usr/local/src/sage-config/local/bin/python
      2 
      3 # -*- coding: utf-8 -*-
      4 import re
      5 import sys
      6 
      7 from IPython import start_ipython
      8 
      9 if __name__ == '__main__':
     10     sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
---> 11     sys.exit(start_ipython())
        global sys.exit = <built-in function exit>
        global start_ipython = <function start_ipython at 0x7fcd69088e60>

/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/__init__.pyc in start_ipython(argv=None, **kwargs={})
    104     This is a public API method, and will survive implementation changes.
    105     
    106     Parameters
    107     ----------
    108     
    109     argv : list or None, optional
    110         If unspecified or None, IPython will parse command-line options from sys.argv.
    111         To prevent any command-line parsing, pass an empty list: `argv=[]`.
    112     user_ns : dict, optional
    113         specify this dictionary to initialize the IPython user namespace with particular values.
    114     kwargs : various, optional
    115         Any other kwargs will be passed to the Application constructor,
    116         such as `config`.
    117     """
    118     from IPython.terminal.ipapp import launch_new_instance
--> 119     return launch_new_instance(argv=argv, **kwargs)
        launch_new_instance = <bound method MetaHasTraits.launch_instance of <class 'IPython.terminal.ipapp.TerminalIPythonApp'>>
        argv = None
        kwargs = {}
    120 
    121 def start_kernel(argv=None, **kwargs):
    122     """Launch a normal IPython kernel instance (as opposed to embedded)
    123     
    124     `IPython.embed_kernel()` puts a shell in a particular calling scope,
    125     such as a function or method for debugging purposes,
    126     which is often not desirable.
    127     
    128     `start_kernel()` does full, regular IPython initialization,
    129     including loading startup files, configuration, etc.
    130     much of which is skipped by `embed()`.
    131     
    132     Parameters
    133     ----------
    134     

/usr/local/src/sage-config/local/lib/python2.7/site-packages/traitlets/config/application.pyc in launch_instance(cls=<class 'IPython.terminal.ipapp.TerminalIPythonApp'>, argv=None, **kwargs={})
    643             lines.append(cls.class_config_section())
    644         return '\n'.join(lines)
    645 
    646     def exit(self, exit_status=0):
    647         self.log.debug("Exiting application: %s" % self.name)
    648         sys.exit(exit_status)
    649 
    650     @classmethod
    651     def launch_instance(cls, argv=None, **kwargs):
    652         """Launch a global instance of this Application
    653 
    654         If a global instance already exists, this reinitializes and starts it
    655         """
    656         app = cls.instance(**kwargs)
    657         app.initialize(argv)
--> 658         app.start()
        app.start = <bound method TerminalIPythonApp.start of <IPython.terminal.ipapp.TerminalIPythonApp object at 0x7fcd702dc750>>
    659 
    660 #-----------------------------------------------------------------------------
    661 # utility functions, for convenience
    662 #-----------------------------------------------------------------------------
    663 
    664 def boolean_flag(name, configurable, set_help='', unset_help=''):
    665     """Helper for building basic --trait, --no-trait flags.
    666 
    667     Parameters
    668     ----------
    669 
    670     name : str
    671         The name of the flag.
    672     configurable : str
    673         The 'Class.trait' string of the trait to be set/unset with the flag

/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/terminal/ipapp.pyc in start(self=<IPython.terminal.ipapp.TerminalIPythonApp object>)
    333         if self.log_level <= logging.INFO: print()
    334 
    335     def _pylab_changed(self, name, old, new):
    336         """Replace --pylab='inline' with --pylab='auto'"""
    337         if new == 'inline':
    338             warnings.warn("'inline' not available as pylab backend, "
    339                       "using 'auto' instead.")
    340             self.pylab = 'auto'
    341 
    342     def start(self):
    343         if self.subapp is not None:
    344             return self.subapp.start()
    345         # perform any prexec steps:
    346         if self.interact:
    347             self.log.debug("Starting IPython's mainloop...")
--> 348             self.shell.mainloop()
        self.shell.mainloop = <bound method TerminalInteractiveShell.mainloop of <IPython.terminal.interactiveshell.TerminalInteractiveShell object at 0x7fcd6934c510>>
    349         else:
    350             self.log.debug("IPython not interactive...")
    351 
    352 def load_default_config(ipython_dir=None):
    353     """Load the default config file from the default ipython_dir.
    354 
    355     This is useful for embedded shells.
    356     """
    357     if ipython_dir is None:
    358         ipython_dir = get_ipython_dir()
    359 
    360     profile_dir = os.path.join(ipython_dir, 'profile_default')
    361 
    362     config = Config()
    363     for cf in Application._load_config_files("ipython_config", path=profile_dir):

/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/terminal/interactiveshell.pyc in mainloop(self=<IPython.terminal.interactiveshell.TerminalInteractiveShell object>, display_banner=<object object>)
    440                 if (not self.confirm_exit) \
    441                         or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
    442                     self.ask_exit()
    443 
    444             else:
    445                 if code:
    446                     self.run_cell(code, store_history=True)
    447 
    448     def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
    449         # An extra layer of protection in case someone mashing Ctrl-C breaks
    450         # out of our internal code.
    451         if display_banner is not DISPLAY_BANNER_DEPRECATED:
    452             warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
    453         while True:
    454             try:
--> 455                 self.interact()
        self.interact = <bound method TerminalInteractiveShell.interact of <IPython.terminal.interactiveshell.TerminalInteractiveShell object at 0x7fcd6934c510>>
    456                 break
    457             except KeyboardInterrupt as e:
    458                 print("\n%s escaped interact()\n" % type(e).__name__)
    459             finally:
    460                 # An interrupt during the eventloop will mess up the
    461                 # internal state of the prompt_toolkit library.
    462                 # Stopping the eventloop fixes this, see
    463                 # https://github.com/ipython/ipython/pull/9867
    464                 if hasattr(self, '_eventloop'):
    465                     self._eventloop.stop()
    466 
    467     _inputhook = None
    468     def inputhook(self, context):
    469         if self._inputhook is not None:
    470             self._inputhook(context)

/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/terminal/interactiveshell.pyc in interact(self=<IPython.terminal.interactiveshell.TerminalInteractiveShell object>, display_banner=<object object>)
    423     def pre_prompt(self):
    424         if self.rl_next_input:
    425             self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
    426             self.rl_next_input = None
    427 
    428     def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
    429 
    430         if display_banner is not DISPLAY_BANNER_DEPRECATED:
    431             warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
    432 
    433         self.keep_running = True
    434         while self.keep_running:
    435             print(self.separate_in, end='')
    436 
    437             try:
--> 438                 code = self.prompt_for_code()
        code = u'import math; math.sin?'
        self.prompt_for_code = <bound method TerminalInteractiveShell.prompt_for_code of <IPython.terminal.interactiveshell.TerminalInteractiveShell object at 0x7fcd6934c510>>
    439             except EOFError:
    440                 if (not self.confirm_exit) \
    441                         or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
    442                     self.ask_exit()
    443 
    444             else:
    445                 if code:
    446                     self.run_cell(code, store_history=True)
    447 
    448     def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
    449         # An extra layer of protection in case someone mashing Ctrl-C breaks
    450         # out of our internal code.
    451         if display_banner is not DISPLAY_BANNER_DEPRECATED:
    452             warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
    453         while True:

/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/terminal/interactiveshell.pyc in prompt_for_code(self=<IPython.terminal.interactiveshell.TerminalInteractiveShell object>)
    328                         processor=HighlightMatchingBracketProcessor(chars='[](){}'),
    329                         filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
    330                             Condition(lambda cli: self.highlight_matching_brackets))],
    331                 }
    332 
    333     def _update_layout(self):
    334         """
    335         Ask for a re computation of the application layout, if for example ,
    336         some configuration options have changed.
    337         """
    338         if self._pt_app:
    339             self._pt_app.layout = create_prompt_layout(**self._layout_options())
    340 
    341     def prompt_for_code(self):
    342         document = self.pt_cli.run(
--> 343             pre_run=self.pre_prompt, reset_current_buffer=True)
        global pre_run = undefined
        self.pre_prompt = <bound method TerminalInteractiveShell.pre_prompt of <IPython.terminal.interactiveshell.TerminalInteractiveShell object at 0x7fcd6934c510>>
        global reset_current_buffer = undefined
        global True = undefined
    344         return document.text
    345 
    346     def enable_win_unicode_console(self):
    347         if sys.version_info >= (3, 6):
    348             # Since PEP 528, Python uses the unicode APIs for the Windows
    349             # console by default, so WUC shouldn't be needed.
    350             return
    351 
    352         import win_unicode_console
    353 
    354         if PY3:
    355             win_unicode_console.enable()
    356         else:
    357             # https://github.com/ipython/ipython/issues/9768
    358             from win_unicode_console.streams import (TextStreamWrapper,

/usr/local/src/sage-config/local/lib/python2.7/site-packages/prompt_toolkit/interface.pyc in run(self=<prompt_toolkit.interface.CommandLineInterface object>, reset_current_buffer=True, pre_run=<bound method TerminalInteractiveShell.pre_promp...nteractiveshell.TerminalInteractiveShell object>>)
    393         This runs the eventloop until a return value has been set.
    394 
    395         :param reset_current_buffer: XXX: Not used anymore.
    396         :param pre_run: Callable that is called right after the reset has taken
    397             place. This allows custom initialisation.
    398         """
    399         assert pre_run is None or callable(pre_run)
    400 
    401         try:
    402             self._is_running = True
    403 
    404             self.on_start.fire()
    405             self.reset()
    406 
    407             # Call pre_run.
--> 408             self._pre_run(pre_run)
        self._pre_run = <bound method CommandLineInterface._pre_run of <prompt_toolkit.interface.CommandLineInterface object at 0x7fcd6859a910>>
        pre_run = <bound method TerminalInteractiveShell.pre_prompt of <IPython.terminal.interactiveshell.TerminalInteractiveShell object at 0x7fcd6934c510>>
    409 
    410             # Run eventloop in raw mode.
    411             with self.input.raw_mode():
    412                 self.renderer.request_absolute_cursor_position()
    413                 self._redraw()
    414 
    415                 self.eventloop.run(self.input, self.create_eventloop_callbacks())
    416         finally:
    417             # Clean up renderer. (This will leave the alternate screen, if we use
    418             # that.)
    419 
    420             # If exit/abort haven't been called set, but another exception was
    421             # thrown instead for some reason, make sure that we redraw in exit
    422             # mode.
    423             if not self.is_done:

/usr/local/src/sage-config/local/lib/python2.7/site-packages/prompt_toolkit/interface.pyc in _pre_run(self=<prompt_toolkit.interface.CommandLineInterface object>, pre_run=<bound method TerminalInteractiveShell.pre_promp...nteractiveshell.TerminalInteractiveShell object>>)
    368         """
    369         # Erase, request position (when cursor is at the start position)
    370         # and redraw again. -- The order is important.
    371         self.renderer.erase(leave_alternate_screen=False, erase_title=False)
    372         self.renderer.request_absolute_cursor_position()
    373         self._redraw()
    374 
    375     def _load_next_buffer_indexes(self):
    376         for buff, index in self._next_buffer_indexes.items():
    377             if buff in self.buffers:
    378                 self.buffers[buff].working_index = index
    379 
    380     def _pre_run(self, pre_run=None):
    381         " Called during `run`. "
    382         if pre_run:
--> 383             pre_run()
        pre_run = <bound method TerminalInteractiveShell.pre_prompt of <IPython.terminal.interactiveshell.TerminalInteractiveShell object at 0x7fcd6934c510>>
    384 
    385         # Process registered "pre_run_callables" and clear list.
    386         for c in self.pre_run_callables:
    387             c()
    388         del self.pre_run_callables[:]
    389 
    390     def run(self, reset_current_buffer=False, pre_run=None):
    391         """
    392         Read input from the command line.
    393         This runs the eventloop until a return value has been set.
    394 
    395         :param reset_current_buffer: XXX: Not used anymore.
    396         :param pre_run: Callable that is called right after the reset has taken
    397             place. This allows custom initialisation.
    398         """

/usr/local/src/sage-config/local/lib/python2.7/site-packages/IPython/terminal/interactiveshell.pyc in pre_prompt(self=<IPython.terminal.interactiveshell.TerminalInteractiveShell object>)
    410     def __init__(self, *args, **kwargs):
    411         super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
    412         self.init_prompt_toolkit_cli()
    413         self.init_term_title()
    414         self.keep_running = True
    415 
    416         self.debugger_history = InMemoryHistory()
    417 
    418     def ask_exit(self):
    419         self.keep_running = False
    420 
    421     rl_next_input = None
    422 
    423     def pre_prompt(self):
    424         if self.rl_next_input:
--> 425             self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
        self.pt_cli.application.buffer.text = u'import math; math.sin?'
        global cast_unicode_py2 = <function cast_unicode at 0x7fcd6c2f6cf8>
        self.rl_next_input = 'import math; math.sin'
    426             self.rl_next_input = None
    427 
    428     def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
    429 
    430         if display_banner is not DISPLAY_BANNER_DEPRECATED:
    431             warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
    432 
    433         self.keep_running = True
    434         while self.keep_running:
    435             print(self.separate_in, end='')
    436 
    437             try:
    438                 code = self.prompt_for_code()
    439             except EOFError:
    440                 if (not self.confirm_exit) \

/usr/local/src/sage-config/local/lib/python2.7/site-packages/prompt_toolkit/buffer.pyc in text(self=<prompt_toolkit.buffer.Buffer object>, value=u'import math; math.sin')
    356 
    357         return value != original_position
    358 
    359     @property
    360     def text(self):
    361         return self._working_lines[self.working_index]
    362 
    363     @text.setter
    364     def text(self, value):
    365         """
    366         Setting text. (When doing this, make sure that the cursor_position is
    367         valid for this text. text/cursor_position should be consistent at any time,
    368         otherwise set a Document instead.)
    369         """
    370         assert isinstance(value, six.text_type), 'Got %r' % value
--> 371         assert self.cursor_position <= len(value)
        self.cursor_position = 22
        global len = undefined
        value = u'import math; math.sin'
    372 
    373         # Don't allow editing of read-only buffers.
    374         if self.read_only():
    375             raise EditReadOnlyBuffer()
    376 
    377         changed = self._set_text(value)
    378 
    379         if changed:
    380             self._text_changed()
    381 
    382             # Reset history search text.
    383             self.history_search_text = None
    384 
    385     @property
    386     def cursor_position(self):

AssertionError: 

**********************************************************************

Oops, ipython crashed. We do our best to make it stable, but...

A crash report was automatically generated with the following information:
  - A verbatim copy of the crash traceback.
  - A copy of your input history during this session.
  - Data on your current ipython configuration.

It was left in the file named:
        '/home/jdemeyer/.sage/ipython-5.0.0/Crash_report_ipython.txt'
If you can email this file to the developers, the information in it will help
them in understanding and correcting the problem.

You can mail it to: The IPython Development Team at ipython-dev@scipy.org
with the subject 'ipython Crash Report'.

If you want to do it now, the following command will work (under Unix):
mail -s 'ipython Crash Report' ipython-dev@scipy.org < /home/jdemeyer/.sage/ipython-5.0.0/Crash_report_ipython.txt

To ensure accurate tracking of this issue, please file a report about it at:
https://github.com/ipython/ipython/issues

Hit <Enter> to quit (your terminal may close):
@takluyver

This comment has been minimized.

Show comment
Hide comment
@takluyver

takluyver Feb 1, 2017

Member

Ping @jonathanslenders - I was only able to reproduce this after upgrading prompt_toolkit, so I think a recent change must have broken what we do. It looks like we should be setting a Document instead of a string?

Member

takluyver commented Feb 1, 2017

Ping @jonathanslenders - I was only able to reproduce this after upgrading prompt_toolkit, so I think a recent change must have broken what we do. It looks like we should be setting a Document instead of a string?

@takluyver

This comment has been minimized.

Show comment
Hide comment
@takluyver

takluyver Feb 1, 2017

Member

#10231 fixes it at least on sufficiently recent prompt_toolkit; I haven't checked how recent it needs to be.

Member

takluyver commented Feb 1, 2017

#10231 fixes it at least on sufficiently recent prompt_toolkit; I haven't checked how recent it needs to be.

@Carreau Carreau added this to the 5.3 milestone Feb 1, 2017

@solstag

This comment has been minimized.

Show comment
Hide comment
@solstag

solstag Feb 17, 2017

I can reproduce this (exact same error message) with a simpler command:

str().find?

It's likely the same problem but, just in case, you might want to check if the fix works for both.

Thanks!

solstag commented Feb 17, 2017

I can reproduce this (exact same error message) with a simpler command:

str().find?

It's likely the same problem but, just in case, you might want to check if the fix works for both.

Thanks!

@takluyver

This comment has been minimized.

Show comment
Hide comment
@takluyver

takluyver Feb 17, 2017

Member

Thanks, I believe that the problem & the fix don't depend on the details of what you enter - anything that calls shell.set_next_input() is affected.

Member

takluyver commented Feb 17, 2017

Thanks, I believe that the problem & the fix don't depend on the details of what you enter - anything that calls shell.set_next_input() is affected.

@minrk minrk closed this in #10231 Feb 21, 2017

meeseeksdev bot pushed a commit that referenced this issue Feb 21, 2017

Backport PR #10231: Fix set_next_input with prompt_toolkit 1.0.10
Closes gh-10229

Please don't merge this just yet.

 jonathanslenders I discovered after updating that we can no longer set text in the buffer with a `pre_run` function, because `pre_run_callables` reset the buffer immediately after that. I've worked around this by adding another callable to `pre_run_callables` which sets the text that I want, but I don't know if this is the right way to do it, or whether it works with previous releases of prompt_toolkit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment