ipython 9.0.2__tar.gz → 9.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/completer.py +155 -3
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/display_trap.py +4 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/displayhook.py +17 -7
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/displaypub.py +14 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/history.py +18 -1
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/historyapp.py +3 -3
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/interactiveshell.py +130 -12
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/basic.py +42 -9
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/execution.py +18 -10
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/release.py +2 -2
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/tips.py +13 -13
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/embed.py +2 -1
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/interactiveshell.py +2 -3
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/shortcuts/auto_suggest.py +16 -15
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/PyColorize.py +2 -2
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/_sysinfo.py +1 -1
- {ipython-9.0.2/ipython.egg-info → ipython-9.1.0}/PKG-INFO +7 -3
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version9.rst +63 -1
- {ipython-9.0.2 → ipython-9.1.0}/examples/auto_suggest_llm.py +2 -4
- {ipython-9.0.2 → ipython-9.1.0/ipython.egg-info}/PKG-INFO +7 -3
- {ipython-9.0.2 → ipython-9.1.0}/ipython.egg-info/SOURCES.txt +1 -0
- {ipython-9.0.2 → ipython-9.1.0}/ipython.egg-info/requires.txt +3 -0
- {ipython-9.0.2 → ipython-9.1.0}/pyproject.toml +4 -1
- ipython-9.1.0/tests/fake_llm.py +89 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_completer.py +119 -1
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_magic.py +74 -3
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_shortcuts.py +24 -0
- {ipython-9.0.2 → ipython-9.1.0}/.flake8 +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/.mailmap +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/.pre-commit-config.yaml +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/COPYING.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/__main__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/alias.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/application.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/async_helpers.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/autocall.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/builtin_trap.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/compilerop.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/completerlib.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/crashhandler.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/debugger.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/display.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/display_functions.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/doctb.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/error.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/events.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/extensions.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/formatters.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/getipython.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/guarded_eval.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/hooks.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/inputtransformer2.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/latex_symbols.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/logger.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/macro.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magic.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magic_arguments.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/ast_mod.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/auto.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/code.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/config.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/display.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/extension.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/history.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/logging.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/namespace.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/osm.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/packaging.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/pylab.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/magics/script.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/oinspect.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/page.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/payload.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/payloadpage.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/prefilter.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/profile/README_STARTUP +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/profileapp.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/profiledir.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/pylabtools.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/shellapp.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/splitinput.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/tbtools.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/ultratb.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/core/usage.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/display.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/extensions/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/extensions/autoreload.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/extensions/deduperreload/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/extensions/deduperreload/deduperreload.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/extensions/deduperreload/deduperreload_patching.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/extensions/storemagic.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/extensions/tests/test_deduperreload.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/external/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/external/pickleshare.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/external/qt_for_kernel.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/external/qt_loaders.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/backgroundjobs.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/clipboard.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/deepreload.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/demo.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/display.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/editorhooks.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/guisupport.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/latextools.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/lexers.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/lib/pretty.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/paths.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/py.typed +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/sphinxext/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/sphinxext/custom_doctests.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/sphinxext/ipython_console_highlighting.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/sphinxext/ipython_directive.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/debugger.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/ipapp.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/magics.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/prompts.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/asyncio.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/glut.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/gtk.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/gtk3.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/gtk4.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/osx.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/pyglet.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/qt.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/tk.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/pt_inputhooks/wx.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/ptutils.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/shortcuts/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/shortcuts/auto_match.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/terminal/shortcuts/filters.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/decorators.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/globalipapp.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/ipunittest.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/Makefile +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/dtexample.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/ipdoctest.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/pytest_ipdoctest.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/setup.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/simple.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/simplevars.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/test_combo.txt +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/test_example.txt +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/test_exampleip.txt +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/test_ipdoctest.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/plugin/test_refs.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/skipdoctest.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/testing/tools.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/_process_cli.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/_process_common.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/_process_emscripten.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/_process_posix.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/_process_win32.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/_process_win32_controller.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/capture.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/coloransi.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/contexts.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/data.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/decorators.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/dir2.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/docs.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/encoding.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/eventful.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/frame.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/generics.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/importstring.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/io.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/ipstruct.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/jsonutil.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/log.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/module_paths.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/openpy.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/path.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/process.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/py3compat.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/sentinel.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/strdispatch.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/sysinfo.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/syspathcontext.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/tempdir.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/terminal.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/text.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/timing.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/tokenutil.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/IPython/utils/wildcard.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/LICENSE +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/MANIFEST.in +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/README.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/_build_meta.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/Makefile +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/README.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/autogen_api.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/autogen_config.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/autogen_magics.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/autogen_shortcuts.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/make.cmd +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/man/ipython.1 +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/requirements.txt +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/2.0/running-crop.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/2.0/running.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/2.0/treeview.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/2.0/user-interface.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/2.0/widgets.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/auto_suggest_1_prompt_no_text.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/auto_suggest_2_print_hello_suggest.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/auto_suggest_3_print_hello_suggest.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/auto_suggest_4_print_hello.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/auto_suggest_d_completions.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/auto_suggest_d_phantom.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/auto_suggest_def_completions.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/auto_suggest_def_phantom.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/auto_suggest_match_parens.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/auto_suggest_second_prompt.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/8.0/pathlib_pathlib_everywhere.jpg +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/autosuggest.gif +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_dashboard.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_dashboard_cluster.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_notebook_cythonmagic.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_notebook_long_out.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_notebook_octavemagic.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_notebook_rmagic.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_notebook_script_cells.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_notebook_spectrogram.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_notebook_tooltip.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_par_tb.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_qtconsole_baboon.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipy_013_qtconsole_completer.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ipython-6-screenshot.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/jedi_type_inference_60.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/kernel_selector_screenshot.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ms_visual_studio.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/notebook_specgram.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/ptshell_features.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/qtconsole.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/qtconsole_tabbed.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_images/unicode_completion.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_static/favicon.ico +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_static/logo.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_static/theme_overrides.css +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_templates/breadcrumbs.html +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/_templates/notebook_redirect.html +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/about/history.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/about/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/about/license_and_copyright.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/api/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/conf.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/callbacks.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/custommagics.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/details.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/eventloops.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/extensions/autoreload.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/extensions/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/extensions/storemagic.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/inputtransforms.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/integrating.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/intro.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/options/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/shell_mimerenderer.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/config/shortcuts/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/coredev/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/config.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/execution.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/figs/ipy_kernel_and_terminal.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/figs/ipy_kernel_and_terminal.svg +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/figs/other_kernels.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/figs/other_kernels.svg +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/how_ipython_works.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/inputhook_app.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/kernels.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/messaging.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/pycompat.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/development/wrapperkernels.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/install/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/install/install.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/install/kernel_install.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/interactive/autoawait.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/interactive/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/interactive/magics.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/interactive/plotting.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/interactive/python-ipython-diff.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/interactive/reference.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/interactive/shell.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/interactive/tips.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/interactive/tutorial.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/links.txt +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/overview.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/parallel/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/sphinx.toml +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/sphinxext.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/development.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-0.11.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-0.12.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-0.13.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-1.0.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-2.0.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-3.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-4.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-5.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-6.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-7.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/github-stats-8.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/index.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/pr/README.md +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/pr/antigravity-feature.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/pr/incompat-switching-to-perl.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version0.10.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version0.11.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version0.12.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version0.13.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version0.8.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version0.9.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version1.0.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version2.0.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version3.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version3_widget_migration.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version4.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version5.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version6.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version7.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/source/whatsnew/version8.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/sphinxext/apigen.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/sphinxext/configtraits.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/sphinxext/github.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/docs/sphinxext/magics.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/Embedding/embed_class_long.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/Embedding/embed_class_short.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/Embedding/embed_function.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/Embedding/start_ipython_config.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/IPython Kernel/example-demo.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/IPython Kernel/gui/gui-glut.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/IPython Kernel/gui/gui-gtk4.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/IPython Kernel/gui/gui-qt.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/IPython Kernel/ipython-completion.bash +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/IPython Kernel/ipython-get-history.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/IPython Kernel/ipython.desktop +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/utils/cwd_prompt.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/utils/list_pyfiles.ipy +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/examples/utils/list_subdirs.ipy +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/ipython.egg-info/dependency_links.txt +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/ipython.egg-info/entry_points.txt +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/ipython.egg-info/not-zip-safe +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/ipython.egg-info/top_level.txt +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/long_description.rst +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/scripts/ipython.ico +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/scripts/ipython_nb.ico +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/setup.cfg +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/setup.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/setupbase.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/2x2.jpg +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/2x2.png +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/__init__.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/bad_all.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/conftest.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/cve.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/fake_ext_dir/daft_extension.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/nonascii.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/nonascii2.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/print_argv.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/refbug.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/simpleerr.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/tclass.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test.wav +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_alias.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_application.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_async_helpers.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_autocall.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_backgroundjobs.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_capture.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_clipboard.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_compilerop.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_completerlib.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_debug_magic.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_debugger.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_decorators.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_decorators_2.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_deepreload.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_dir2.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_display.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_display_2.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_displayhook.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_editorhooks.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_embed.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_events.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_exceptiongroup_tb.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_extension.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_formatters.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_guarded_eval.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_handlers.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_help.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_history.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_hooks.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_imports.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_importstring.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_inputtransformer2.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_inputtransformer2_line.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_interactiveshell.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_interactivshell.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_io.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_iplib.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_ipunittest.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_latextools.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_logger.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_magic_arguments.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_magic_terminal.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_module_paths.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_oinspect.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_openpy.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_page.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_path.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_paths.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_prefilter.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_pretty.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_process.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_profile.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_pt_inputhooks.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_pycolorize.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_pylabtools.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_qt_loaders.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_run.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_shellapp.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_splitinput.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_storemagic.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_sysinfo.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_tempdir.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_text.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_tips.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_tokenutil.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_tools.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_ultratb.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_wildcard.py +0 -0
- {ipython-9.0.2 → ipython-9.1.0}/tests/test_zzz_autoreload.py +0 -0
|
@@ -1137,7 +1137,7 @@ class Completer(Configurable):
|
|
|
1137
1137
|
def _attr_matches(
|
|
1138
1138
|
self, text: str, include_prefix: bool = True
|
|
1139
1139
|
) -> tuple[Sequence[str], str]:
|
|
1140
|
-
m2 = self._ATTR_MATCH_RE.match(
|
|
1140
|
+
m2 = self._ATTR_MATCH_RE.match(text)
|
|
1141
1141
|
if not m2:
|
|
1142
1142
|
return [], ""
|
|
1143
1143
|
expr, attr = m2.group(1, 2)
|
|
@@ -2360,11 +2360,163 @@ class IPCompleter(Completer):
|
|
|
2360
2360
|
else:
|
|
2361
2361
|
return iter([])
|
|
2362
2362
|
|
|
2363
|
+
class _CompletionContextType(enum.Enum):
|
|
2364
|
+
ATTRIBUTE = "attribute" # For attribute completion
|
|
2365
|
+
GLOBAL = "global" # For global completion
|
|
2366
|
+
|
|
2367
|
+
def _determine_completion_context(self, line):
|
|
2368
|
+
"""
|
|
2369
|
+
Determine whether the cursor is in an attribute or global completion context.
|
|
2370
|
+
"""
|
|
2371
|
+
# Cursor in string/comment → GLOBAL.
|
|
2372
|
+
is_string, is_in_expression = self._is_in_string_or_comment(line)
|
|
2373
|
+
if is_string and not is_in_expression:
|
|
2374
|
+
return self._CompletionContextType.GLOBAL
|
|
2375
|
+
|
|
2376
|
+
# If we're in a template string expression, handle specially
|
|
2377
|
+
if is_string and is_in_expression:
|
|
2378
|
+
# Extract the expression part - look for the last { that isn't closed
|
|
2379
|
+
expr_start = line.rfind("{")
|
|
2380
|
+
if expr_start >= 0:
|
|
2381
|
+
# We're looking at the expression inside a template string
|
|
2382
|
+
expr = line[expr_start + 1 :]
|
|
2383
|
+
# Recursively determine the context of the expression
|
|
2384
|
+
return self._determine_completion_context(expr)
|
|
2385
|
+
|
|
2386
|
+
# Handle plain number literals - should be global context
|
|
2387
|
+
# Ex: 3. -42.14 but not 3.1.
|
|
2388
|
+
if re.search(r"(?<!\w)(?<!\d\.)([-+]?\d+\.(\d+)?)(?!\w)$", line):
|
|
2389
|
+
return self._CompletionContextType.GLOBAL
|
|
2390
|
+
|
|
2391
|
+
# Handle all other attribute matches np.ran, d[0].k, (a,b).count
|
|
2392
|
+
chain_match = re.search(r".*(.+\.(?:[a-zA-Z]\w*)?)$", line)
|
|
2393
|
+
if chain_match:
|
|
2394
|
+
return self._CompletionContextType.ATTRIBUTE
|
|
2395
|
+
|
|
2396
|
+
return self._CompletionContextType.GLOBAL
|
|
2397
|
+
|
|
2398
|
+
def _is_in_string_or_comment(self, text):
|
|
2399
|
+
"""
|
|
2400
|
+
Determine if the cursor is inside a string or comment.
|
|
2401
|
+
Returns (is_string, is_in_expression) tuple:
|
|
2402
|
+
- is_string: True if in any kind of string
|
|
2403
|
+
- is_in_expression: True if inside an f-string/t-string expression
|
|
2404
|
+
"""
|
|
2405
|
+
in_single_quote = False
|
|
2406
|
+
in_double_quote = False
|
|
2407
|
+
in_triple_single = False
|
|
2408
|
+
in_triple_double = False
|
|
2409
|
+
in_template_string = False # Covers both f-strings and t-strings
|
|
2410
|
+
in_expression = False # For expressions in f/t-strings
|
|
2411
|
+
expression_depth = 0 # Track nested braces in expressions
|
|
2412
|
+
i = 0
|
|
2413
|
+
|
|
2414
|
+
while i < len(text):
|
|
2415
|
+
# Check for f-string or t-string start
|
|
2416
|
+
if (
|
|
2417
|
+
i + 1 < len(text)
|
|
2418
|
+
and text[i] in ("f", "t")
|
|
2419
|
+
and (text[i + 1] == '"' or text[i + 1] == "'")
|
|
2420
|
+
and not (
|
|
2421
|
+
in_single_quote
|
|
2422
|
+
or in_double_quote
|
|
2423
|
+
or in_triple_single
|
|
2424
|
+
or in_triple_double
|
|
2425
|
+
)
|
|
2426
|
+
):
|
|
2427
|
+
in_template_string = True
|
|
2428
|
+
i += 1 # Skip the 'f' or 't'
|
|
2429
|
+
|
|
2430
|
+
# Handle triple quotes
|
|
2431
|
+
if i + 2 < len(text):
|
|
2432
|
+
if (
|
|
2433
|
+
text[i : i + 3] == '"""'
|
|
2434
|
+
and not in_single_quote
|
|
2435
|
+
and not in_triple_single
|
|
2436
|
+
):
|
|
2437
|
+
in_triple_double = not in_triple_double
|
|
2438
|
+
if not in_triple_double:
|
|
2439
|
+
in_template_string = False
|
|
2440
|
+
i += 3
|
|
2441
|
+
continue
|
|
2442
|
+
if (
|
|
2443
|
+
text[i : i + 3] == "'''"
|
|
2444
|
+
and not in_double_quote
|
|
2445
|
+
and not in_triple_double
|
|
2446
|
+
):
|
|
2447
|
+
in_triple_single = not in_triple_single
|
|
2448
|
+
if not in_triple_single:
|
|
2449
|
+
in_template_string = False
|
|
2450
|
+
i += 3
|
|
2451
|
+
continue
|
|
2452
|
+
|
|
2453
|
+
# Handle escapes
|
|
2454
|
+
if text[i] == "\\" and i + 1 < len(text):
|
|
2455
|
+
i += 2
|
|
2456
|
+
continue
|
|
2457
|
+
|
|
2458
|
+
# Handle nested braces within f-strings
|
|
2459
|
+
if in_template_string:
|
|
2460
|
+
# Special handling for consecutive opening braces
|
|
2461
|
+
if i + 1 < len(text) and text[i : i + 2] == "{{":
|
|
2462
|
+
i += 2
|
|
2463
|
+
continue
|
|
2464
|
+
|
|
2465
|
+
# Detect start of an expression
|
|
2466
|
+
if text[i] == "{":
|
|
2467
|
+
# Only increment depth and mark as expression if not already in an expression
|
|
2468
|
+
# or if we're at a top-level nested brace
|
|
2469
|
+
if not in_expression or (in_expression and expression_depth == 0):
|
|
2470
|
+
in_expression = True
|
|
2471
|
+
expression_depth += 1
|
|
2472
|
+
i += 1
|
|
2473
|
+
continue
|
|
2474
|
+
|
|
2475
|
+
# Detect end of an expression
|
|
2476
|
+
if text[i] == "}":
|
|
2477
|
+
expression_depth -= 1
|
|
2478
|
+
if expression_depth <= 0:
|
|
2479
|
+
in_expression = False
|
|
2480
|
+
expression_depth = 0
|
|
2481
|
+
i += 1
|
|
2482
|
+
continue
|
|
2483
|
+
|
|
2484
|
+
in_triple_quote = in_triple_single or in_triple_double
|
|
2485
|
+
|
|
2486
|
+
# Handle quotes - also reset template string when closing quotes are encountered
|
|
2487
|
+
if text[i] == '"' and not in_single_quote and not in_triple_quote:
|
|
2488
|
+
in_double_quote = not in_double_quote
|
|
2489
|
+
if not in_double_quote and not in_triple_quote:
|
|
2490
|
+
in_template_string = False
|
|
2491
|
+
elif text[i] == "'" and not in_double_quote and not in_triple_quote:
|
|
2492
|
+
in_single_quote = not in_single_quote
|
|
2493
|
+
if not in_single_quote and not in_triple_quote:
|
|
2494
|
+
in_template_string = False
|
|
2495
|
+
|
|
2496
|
+
# Check for comment
|
|
2497
|
+
if text[i] == "#" and not (
|
|
2498
|
+
in_single_quote or in_double_quote or in_triple_quote
|
|
2499
|
+
):
|
|
2500
|
+
return True, False
|
|
2501
|
+
|
|
2502
|
+
i += 1
|
|
2503
|
+
|
|
2504
|
+
is_string = (
|
|
2505
|
+
in_single_quote or in_double_quote or in_triple_single or in_triple_double
|
|
2506
|
+
)
|
|
2507
|
+
|
|
2508
|
+
# Return tuple (is_string, is_in_expression)
|
|
2509
|
+
return (
|
|
2510
|
+
is_string or (in_template_string and not in_expression),
|
|
2511
|
+
in_expression and expression_depth > 0,
|
|
2512
|
+
)
|
|
2513
|
+
|
|
2363
2514
|
@context_matcher()
|
|
2364
2515
|
def python_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
|
|
2365
2516
|
"""Match attributes or global python names"""
|
|
2366
|
-
text = context.
|
|
2367
|
-
|
|
2517
|
+
text = context.text_until_cursor
|
|
2518
|
+
completion_type = self._determine_completion_context(text)
|
|
2519
|
+
if completion_type == self._CompletionContextType.ATTRIBUTE:
|
|
2368
2520
|
try:
|
|
2369
2521
|
matches, fragment = self._attr_matches(text, include_prefix=False)
|
|
2370
2522
|
if text.endswith(".") and self.omit__names:
|
|
@@ -58,6 +58,10 @@ class DisplayTrap(Configurable):
|
|
|
58
58
|
# Returning False will cause exceptions to propagate
|
|
59
59
|
return False
|
|
60
60
|
|
|
61
|
+
@property
|
|
62
|
+
def is_active(self) -> bool:
|
|
63
|
+
return self._nested_level != 0
|
|
64
|
+
|
|
61
65
|
def set(self):
|
|
62
66
|
"""Set the hook."""
|
|
63
67
|
if sys.displayhook is not self.hook:
|
|
@@ -16,6 +16,8 @@ from traitlets.config.configurable import Configurable
|
|
|
16
16
|
from traitlets import Instance, Float
|
|
17
17
|
from warnings import warn
|
|
18
18
|
|
|
19
|
+
from .history import HistoryOutput
|
|
20
|
+
|
|
19
21
|
# TODO: Move the various attributes (cache_size, [others now moved]). Some
|
|
20
22
|
# of these are also attributes of InteractiveShell. They should be on ONE object
|
|
21
23
|
# only and the other objects should ask that one object for their values.
|
|
@@ -35,6 +37,7 @@ class DisplayHook(Configurable):
|
|
|
35
37
|
|
|
36
38
|
def __init__(self, shell=None, cache_size=1000, **kwargs):
|
|
37
39
|
super(DisplayHook, self).__init__(shell=shell, **kwargs)
|
|
40
|
+
self._is_active = False
|
|
38
41
|
cache_size_min = 3
|
|
39
42
|
if cache_size <= 0:
|
|
40
43
|
self.do_full_cache = 0
|
|
@@ -51,7 +54,7 @@ class DisplayHook(Configurable):
|
|
|
51
54
|
|
|
52
55
|
# we need a reference to the user-level namespace
|
|
53
56
|
self.shell = shell
|
|
54
|
-
|
|
57
|
+
|
|
55
58
|
self._,self.__,self.___ = '','',''
|
|
56
59
|
|
|
57
60
|
# these are deliberately global:
|
|
@@ -84,13 +87,13 @@ class DisplayHook(Configurable):
|
|
|
84
87
|
def quiet(self):
|
|
85
88
|
"""Should we silence the display hook because of ';'?"""
|
|
86
89
|
# do not print output if input ends in ';'
|
|
87
|
-
|
|
90
|
+
|
|
88
91
|
try:
|
|
89
92
|
cell = self.shell.history_manager.input_hist_parsed[-1]
|
|
90
93
|
except IndexError:
|
|
91
94
|
# some uses of ipshellembed may fail here
|
|
92
95
|
return False
|
|
93
|
-
|
|
96
|
+
|
|
94
97
|
return self.semicolon_at_end_of_expression(cell)
|
|
95
98
|
|
|
96
99
|
@staticmethod
|
|
@@ -110,7 +113,11 @@ class DisplayHook(Configurable):
|
|
|
110
113
|
|
|
111
114
|
def start_displayhook(self):
|
|
112
115
|
"""Start the displayhook, initializing resources."""
|
|
113
|
-
|
|
116
|
+
self._is_active = True
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def is_active(self):
|
|
120
|
+
return self._is_active
|
|
114
121
|
|
|
115
122
|
def write_output_prompt(self):
|
|
116
123
|
"""Write the output prompt.
|
|
@@ -242,7 +249,10 @@ class DisplayHook(Configurable):
|
|
|
242
249
|
|
|
243
250
|
def log_output(self, format_dict):
|
|
244
251
|
"""Log the output."""
|
|
245
|
-
|
|
252
|
+
self.shell.history_manager.outputs[self.prompt_count].append(
|
|
253
|
+
HistoryOutput(output_type="execute_result", bundle=format_dict)
|
|
254
|
+
)
|
|
255
|
+
if "text/plain" not in format_dict:
|
|
246
256
|
# nothing to do
|
|
247
257
|
return
|
|
248
258
|
if self.shell.logger.log_output:
|
|
@@ -254,6 +264,7 @@ class DisplayHook(Configurable):
|
|
|
254
264
|
"""Finish up all displayhook activities."""
|
|
255
265
|
sys.stdout.write(self.shell.separate_out2)
|
|
256
266
|
sys.stdout.flush()
|
|
267
|
+
self._is_active = False
|
|
257
268
|
|
|
258
269
|
def __call__(self, result=None):
|
|
259
270
|
"""Printing with history cache management.
|
|
@@ -280,13 +291,12 @@ class DisplayHook(Configurable):
|
|
|
280
291
|
cull_count = max(int(sz * self.cull_fraction), 2)
|
|
281
292
|
warn('Output cache limit (currently {sz} entries) hit.\n'
|
|
282
293
|
'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
|
|
283
|
-
|
|
294
|
+
|
|
284
295
|
for i, n in enumerate(sorted(oh)):
|
|
285
296
|
if i >= cull_count:
|
|
286
297
|
break
|
|
287
298
|
self.shell.user_ns.pop('_%i' % n, None)
|
|
288
299
|
oh.pop(n, None)
|
|
289
|
-
|
|
290
300
|
|
|
291
301
|
def flush(self):
|
|
292
302
|
if not self.do_full_cache:
|
|
@@ -22,6 +22,7 @@ from traitlets import List
|
|
|
22
22
|
|
|
23
23
|
# This used to be defined here - it is imported for backwards compatibility
|
|
24
24
|
from .display_functions import publish_display_data
|
|
25
|
+
from .history import HistoryOutput
|
|
25
26
|
|
|
26
27
|
import typing as t
|
|
27
28
|
|
|
@@ -41,6 +42,7 @@ class DisplayPublisher(Configurable):
|
|
|
41
42
|
|
|
42
43
|
def __init__(self, shell=None, *args, **kwargs):
|
|
43
44
|
self.shell = shell
|
|
45
|
+
self._is_publishing = False
|
|
44
46
|
super().__init__(*args, **kwargs)
|
|
45
47
|
|
|
46
48
|
def _validate_data(self, data, metadata=None):
|
|
@@ -129,13 +131,25 @@ class DisplayPublisher(Configurable):
|
|
|
129
131
|
if self.shell is not None:
|
|
130
132
|
handlers = getattr(self.shell, "mime_renderers", {})
|
|
131
133
|
|
|
134
|
+
outputs = self.shell.history_manager.outputs
|
|
135
|
+
|
|
136
|
+
outputs[self.shell.execution_count].append(
|
|
137
|
+
HistoryOutput(output_type="display_data", bundle=data)
|
|
138
|
+
)
|
|
139
|
+
|
|
132
140
|
for mime, handler in handlers.items():
|
|
133
141
|
if mime in data:
|
|
134
142
|
handler(data[mime], metadata.get(mime, None))
|
|
135
143
|
return
|
|
136
144
|
|
|
145
|
+
self._is_publishing = True
|
|
137
146
|
if "text/plain" in data:
|
|
138
147
|
print(data["text/plain"])
|
|
148
|
+
self._is_publishing = False
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def is_publishing(self):
|
|
152
|
+
return self._is_publishing
|
|
139
153
|
|
|
140
154
|
def clear_output(self, wait=False):
|
|
141
155
|
"""Clear the output of the cell receiving output."""
|
|
@@ -14,7 +14,9 @@ import re
|
|
|
14
14
|
import threading
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
|
|
17
|
+
from collections import defaultdict
|
|
17
18
|
from contextlib import contextmanager
|
|
19
|
+
from dataclasses import dataclass
|
|
18
20
|
from decorator import decorator
|
|
19
21
|
from traitlets import (
|
|
20
22
|
Any,
|
|
@@ -583,6 +585,14 @@ class HistoryAccessor(HistoryAccessorBase):
|
|
|
583
585
|
yield from self.get_range(sess, s, e, raw=raw, output=output)
|
|
584
586
|
|
|
585
587
|
|
|
588
|
+
@dataclass
|
|
589
|
+
class HistoryOutput:
|
|
590
|
+
output_type: typing.Literal[
|
|
591
|
+
"out_stream", "err_stream", "display_data", "execute_result"
|
|
592
|
+
]
|
|
593
|
+
bundle: typing.Dict[str, str]
|
|
594
|
+
|
|
595
|
+
|
|
586
596
|
class HistoryManager(HistoryAccessor):
|
|
587
597
|
"""A class to organize all history-related functionality in one place."""
|
|
588
598
|
|
|
@@ -610,7 +620,11 @@ class HistoryManager(HistoryAccessor):
|
|
|
610
620
|
# execution count.
|
|
611
621
|
output_hist = Dict()
|
|
612
622
|
# The text/plain repr of outputs.
|
|
613
|
-
output_hist_reprs:
|
|
623
|
+
output_hist_reprs: typing.Dict[int, str] = Dict() # type: ignore [assignment]
|
|
624
|
+
# Maps execution_count to MIME bundles
|
|
625
|
+
outputs: typing.Dict[int, typing.List[HistoryOutput]] = defaultdict(list)
|
|
626
|
+
# Maps execution_count to exception tracebacks
|
|
627
|
+
exceptions: typing.Dict[int, typing.Dict[str, Any]] = Dict() # type: ignore [assignment]
|
|
614
628
|
|
|
615
629
|
# The number of the current session in the history database
|
|
616
630
|
session_number: int = Integer() # type: ignore [assignment]
|
|
@@ -749,6 +763,9 @@ class HistoryManager(HistoryAccessor):
|
|
|
749
763
|
"""Clear the session history, releasing all object references, and
|
|
750
764
|
optionally open a new session."""
|
|
751
765
|
self.output_hist.clear()
|
|
766
|
+
self.outputs.clear()
|
|
767
|
+
self.exceptions.clear()
|
|
768
|
+
|
|
752
769
|
# The directory history can't be completely empty
|
|
753
770
|
self.dir_hist[:] = [Path.cwd()]
|
|
754
771
|
|
|
@@ -59,9 +59,9 @@ class HistoryTrim(BaseIPythonApplication):
|
|
|
59
59
|
print("There are already at most %d entries in the history database." % self.keep)
|
|
60
60
|
print("Not doing anything. Use --keep= argument to keep fewer entries")
|
|
61
61
|
return
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
print("Trimming history to the most recent %d entries." % self.keep)
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
inputs.pop() # Remove the extra element we got to check the length.
|
|
66
66
|
inputs.reverse()
|
|
67
67
|
if inputs:
|
|
@@ -71,7 +71,7 @@ class HistoryTrim(BaseIPythonApplication):
|
|
|
71
71
|
sessions = list(con.execute('SELECT session, start, end, num_cmds, remark FROM '
|
|
72
72
|
'sessions WHERE session >= ?', (first_session,)))
|
|
73
73
|
con.close()
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
# Create the new history database.
|
|
76
76
|
new_hist_file = profile_dir / "history.sqlite.new"
|
|
77
77
|
i = 0
|
|
@@ -28,12 +28,13 @@ import traceback
|
|
|
28
28
|
import types
|
|
29
29
|
import warnings
|
|
30
30
|
from ast import stmt
|
|
31
|
+
from contextlib import contextmanager
|
|
31
32
|
from io import open as io_open
|
|
32
33
|
from logging import error
|
|
33
34
|
from pathlib import Path
|
|
34
35
|
from typing import Callable
|
|
35
36
|
from typing import List as ListType, Any as AnyType
|
|
36
|
-
from typing import Optional, Sequence, Tuple
|
|
37
|
+
from typing import Literal, Optional, Sequence, Tuple
|
|
37
38
|
from warnings import warn
|
|
38
39
|
|
|
39
40
|
from IPython.external.pickleshare import PickleShareDB
|
|
@@ -71,7 +72,7 @@ from IPython.core.error import InputRejected, UsageError
|
|
|
71
72
|
from IPython.core.events import EventManager, available_events
|
|
72
73
|
from IPython.core.extensions import ExtensionManager
|
|
73
74
|
from IPython.core.formatters import DisplayFormatter
|
|
74
|
-
from IPython.core.history import HistoryManager
|
|
75
|
+
from IPython.core.history import HistoryManager, HistoryOutput
|
|
75
76
|
from IPython.core.inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
|
|
76
77
|
from IPython.core.logger import Logger
|
|
77
78
|
from IPython.core.macro import Macro
|
|
@@ -324,6 +325,7 @@ def _modified_open(file, *args, **kwargs):
|
|
|
324
325
|
|
|
325
326
|
return io_open(file, *args, **kwargs)
|
|
326
327
|
|
|
328
|
+
|
|
327
329
|
class InteractiveShell(SingletonConfigurable):
|
|
328
330
|
"""An enhanced, interactive shell for Python."""
|
|
329
331
|
|
|
@@ -466,7 +468,7 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
466
468
|
# Monotonically increasing execution counter
|
|
467
469
|
execution_count = Integer(1)
|
|
468
470
|
filename = Unicode("<ipython console>")
|
|
469
|
-
ipython_dir= Unicode(
|
|
471
|
+
ipython_dir = Unicode("").tag(config=True) # Set to get_ipython_dir() in __init__
|
|
470
472
|
|
|
471
473
|
# Used to transform cells before running them, and check whether code is complete
|
|
472
474
|
input_transformer_manager = Instance('IPython.core.inputtransformer2.TransformerManager',
|
|
@@ -661,6 +663,7 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
661
663
|
# inside a single Trio event loop. If used, it is set from
|
|
662
664
|
# `ipykernel.kernelapp`.
|
|
663
665
|
self.trio_runner = None
|
|
666
|
+
self.showing_traceback = False
|
|
664
667
|
|
|
665
668
|
@property
|
|
666
669
|
def user_ns(self):
|
|
@@ -868,7 +871,7 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
868
871
|
cache_size=self.cache_size,
|
|
869
872
|
)
|
|
870
873
|
self.configurables.append(self.displayhook)
|
|
871
|
-
# This is a context manager that installs/
|
|
874
|
+
# This is a context manager that installs/removes the displayhook at
|
|
872
875
|
# the appropriate time.
|
|
873
876
|
self.display_trap = DisplayTrap(hook=self.displayhook)
|
|
874
877
|
|
|
@@ -2200,10 +2203,12 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
2200
2203
|
place, like a side channel.
|
|
2201
2204
|
"""
|
|
2202
2205
|
val = self.InteractiveTB.stb2text(stb)
|
|
2206
|
+
self.showing_traceback = True
|
|
2203
2207
|
try:
|
|
2204
2208
|
print(val)
|
|
2205
2209
|
except UnicodeEncodeError:
|
|
2206
2210
|
print(val.encode("utf-8", "backslashreplace").decode())
|
|
2211
|
+
self.showing_traceback = False
|
|
2207
2212
|
|
|
2208
2213
|
def showsyntaxerror(self, filename=None, running_compiled_code=False):
|
|
2209
2214
|
"""Display the syntax error that just occurred.
|
|
@@ -3006,6 +3011,51 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
3006
3011
|
self.showtraceback()
|
|
3007
3012
|
warn('Unknown failure executing module: <%s>' % mod_name)
|
|
3008
3013
|
|
|
3014
|
+
@contextmanager
|
|
3015
|
+
def _tee(self, channel: Literal["stdout", "stderr"]):
|
|
3016
|
+
"""Capture output of a given standard stream and store it in history.
|
|
3017
|
+
|
|
3018
|
+
Uses patching of write method for maximal compatibility,
|
|
3019
|
+
because ipykernel checks for instances of the stream class,
|
|
3020
|
+
and stream classes in ipykernel implement more complex logic.
|
|
3021
|
+
"""
|
|
3022
|
+
stream = getattr(sys, channel)
|
|
3023
|
+
original_write = stream.write
|
|
3024
|
+
|
|
3025
|
+
def write(data, *args, **kwargs):
|
|
3026
|
+
"""Write data to both the original destination and the capture dictionary."""
|
|
3027
|
+
result = original_write(data, *args, **kwargs)
|
|
3028
|
+
if any(
|
|
3029
|
+
[
|
|
3030
|
+
self.display_pub.is_publishing,
|
|
3031
|
+
self.displayhook.is_active,
|
|
3032
|
+
self.showing_traceback,
|
|
3033
|
+
]
|
|
3034
|
+
):
|
|
3035
|
+
return result
|
|
3036
|
+
if not data:
|
|
3037
|
+
return result
|
|
3038
|
+
execution_count = self.execution_count
|
|
3039
|
+
output_stream = None
|
|
3040
|
+
outputs_by_counter = self.history_manager.outputs
|
|
3041
|
+
output_type = "out_stream" if channel == "stdout" else "err_stream"
|
|
3042
|
+
if execution_count in outputs_by_counter:
|
|
3043
|
+
outputs = outputs_by_counter[execution_count]
|
|
3044
|
+
if outputs[-1].output_type == output_type:
|
|
3045
|
+
output_stream = outputs[-1]
|
|
3046
|
+
if output_stream is None:
|
|
3047
|
+
output_stream = HistoryOutput(
|
|
3048
|
+
output_type=output_type, bundle={"stream": ""}
|
|
3049
|
+
)
|
|
3050
|
+
outputs_by_counter[execution_count].append(output_stream)
|
|
3051
|
+
|
|
3052
|
+
output_stream.bundle["stream"] += data # Append to existing stream
|
|
3053
|
+
return result
|
|
3054
|
+
|
|
3055
|
+
stream.write = write
|
|
3056
|
+
yield
|
|
3057
|
+
stream.write = original_write
|
|
3058
|
+
|
|
3009
3059
|
def run_cell(
|
|
3010
3060
|
self,
|
|
3011
3061
|
raw_cell,
|
|
@@ -3043,14 +3093,15 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
3043
3093
|
result : :class:`ExecutionResult`
|
|
3044
3094
|
"""
|
|
3045
3095
|
result = None
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3096
|
+
with self._tee(channel="stdout"), self._tee(channel="stderr"):
|
|
3097
|
+
try:
|
|
3098
|
+
result = self._run_cell(
|
|
3099
|
+
raw_cell, store_history, silent, shell_futures, cell_id
|
|
3100
|
+
)
|
|
3101
|
+
finally:
|
|
3102
|
+
self.events.trigger("post_execute")
|
|
3103
|
+
if not silent:
|
|
3104
|
+
self.events.trigger("post_run_cell", result)
|
|
3054
3105
|
return result
|
|
3055
3106
|
|
|
3056
3107
|
def _run_cell(
|
|
@@ -3208,6 +3259,11 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
3208
3259
|
|
|
3209
3260
|
def error_before_exec(value):
|
|
3210
3261
|
if store_history:
|
|
3262
|
+
if self.history_manager:
|
|
3263
|
+
# Store formatted traceback and error details
|
|
3264
|
+
self.history_manager.exceptions[self.execution_count] = (
|
|
3265
|
+
self._format_exception_for_storage(value)
|
|
3266
|
+
)
|
|
3211
3267
|
self.execution_count += 1
|
|
3212
3268
|
result.error_before_exec = value
|
|
3213
3269
|
self.last_execution_succeeded = False
|
|
@@ -3318,11 +3374,73 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
3318
3374
|
# Write output to the database. Does nothing unless
|
|
3319
3375
|
# history output logging is enabled.
|
|
3320
3376
|
self.history_manager.store_output(self.execution_count)
|
|
3377
|
+
exec_count = self.execution_count
|
|
3378
|
+
if result.error_in_exec:
|
|
3379
|
+
# Store formatted traceback and error details
|
|
3380
|
+
self.history_manager.exceptions[exec_count] = (
|
|
3381
|
+
self._format_exception_for_storage(result.error_in_exec)
|
|
3382
|
+
)
|
|
3383
|
+
|
|
3321
3384
|
# Each cell is a *single* input, regardless of how many lines it has
|
|
3322
3385
|
self.execution_count += 1
|
|
3323
3386
|
|
|
3324
3387
|
return result
|
|
3325
3388
|
|
|
3389
|
+
def _format_exception_for_storage(
|
|
3390
|
+
self, exception, filename=None, running_compiled_code=False
|
|
3391
|
+
):
|
|
3392
|
+
"""
|
|
3393
|
+
Format an exception's traceback and details for storage, with special handling
|
|
3394
|
+
for different types of errors.
|
|
3395
|
+
"""
|
|
3396
|
+
etype = type(exception)
|
|
3397
|
+
evalue = exception
|
|
3398
|
+
tb = exception.__traceback__
|
|
3399
|
+
|
|
3400
|
+
# Handle SyntaxError and IndentationError with specific formatting
|
|
3401
|
+
if issubclass(etype, (SyntaxError, IndentationError)):
|
|
3402
|
+
if filename and isinstance(evalue, SyntaxError):
|
|
3403
|
+
try:
|
|
3404
|
+
evalue.filename = filename
|
|
3405
|
+
except:
|
|
3406
|
+
pass # Keep the original filename if modification fails
|
|
3407
|
+
|
|
3408
|
+
# Extract traceback if the error happened during compiled code execution
|
|
3409
|
+
elist = traceback.extract_tb(tb) if running_compiled_code else []
|
|
3410
|
+
stb = self.SyntaxTB.structured_traceback(etype, evalue, elist)
|
|
3411
|
+
|
|
3412
|
+
# Handle UsageError with a simple message
|
|
3413
|
+
elif etype is UsageError:
|
|
3414
|
+
stb = [f"UsageError: {evalue}"]
|
|
3415
|
+
|
|
3416
|
+
else:
|
|
3417
|
+
# Check if the exception (or its context) is an ExceptionGroup.
|
|
3418
|
+
def contains_exceptiongroup(val):
|
|
3419
|
+
if val is None:
|
|
3420
|
+
return False
|
|
3421
|
+
return isinstance(val, BaseExceptionGroup) or contains_exceptiongroup(
|
|
3422
|
+
val.__context__
|
|
3423
|
+
)
|
|
3424
|
+
|
|
3425
|
+
if contains_exceptiongroup(evalue):
|
|
3426
|
+
# Fallback: use the standard library's formatting for exception groups.
|
|
3427
|
+
stb = traceback.format_exception(etype, evalue, tb)
|
|
3428
|
+
else:
|
|
3429
|
+
try:
|
|
3430
|
+
# If the exception has a custom traceback renderer, use it.
|
|
3431
|
+
if hasattr(evalue, "_render_traceback_"):
|
|
3432
|
+
stb = evalue._render_traceback_()
|
|
3433
|
+
else:
|
|
3434
|
+
# Otherwise, use InteractiveTB to format the traceback.
|
|
3435
|
+
stb = self.InteractiveTB.structured_traceback(
|
|
3436
|
+
etype, evalue, tb, tb_offset=1
|
|
3437
|
+
)
|
|
3438
|
+
except Exception:
|
|
3439
|
+
# In case formatting fails, fallback to Python's built-in formatting.
|
|
3440
|
+
stb = traceback.format_exception(etype, evalue, tb)
|
|
3441
|
+
|
|
3442
|
+
return {"ename": etype.__name__, "evalue": str(evalue), "traceback": stb}
|
|
3443
|
+
|
|
3326
3444
|
def transform_cell(self, raw_cell):
|
|
3327
3445
|
"""Transform an input cell before parsing it.
|
|
3328
3446
|
|