From 082e891fcf14bd468eaf82492e1973dcf1bfb365 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Sat, 29 Aug 2020 14:39:57 -0700 Subject: [PATCH 001/174] back to dev --- IPython/core/release.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/IPython/core/release.py b/IPython/core/release.py index 00e5499923a..570947666ed 100644 --- a/IPython/core/release.py +++ b/IPython/core/release.py @@ -20,11 +20,11 @@ # release. 'dev' as a _version_extra string means this is a development # version _version_major = 7 -_version_minor = 18 -_version_patch = 1 +_version_minor = 19 +_version_patch = 0 _version_extra = '.dev' # _version_extra = 'b1' -_version_extra = '' # Uncomment this for full releases +# _version_extra = '' # Uncomment this for full releases # Construct full version string from these. _ver = [_version_major, _version_minor, _version_patch] From b08c1817a03714449d5ce104feb8464a11ce3d21 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Mon, 7 Sep 2020 09:39:17 -0700 Subject: [PATCH 002/174] Backport PR #12543: allow specifying multiple extensions on the command-line with traitlets 5 --- IPython/core/shellapp.py | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/IPython/core/shellapp.py b/IPython/core/shellapp.py index 9e8bfbfbb81..ee65d3af6c8 100644 --- a/IPython/core/shellapp.py +++ b/IPython/core/shellapp.py @@ -19,8 +19,10 @@ from IPython.core import pylabtools from IPython.utils.contexts import preserve_keys from IPython.utils.path import filefind +import traitlets from traitlets import ( Unicode, Instance, List, Bool, CaselessStrEnum, observe, + DottedObjectName, ) from IPython.terminal import pt_inputhooks @@ -89,13 +91,18 @@ logappend='InteractiveShell.logappend', c='InteractiveShellApp.code_to_run', m='InteractiveShellApp.module_to_run', - ext='InteractiveShellApp.extra_extension', + ext="InteractiveShellApp.extra_extensions", gui='InteractiveShellApp.gui', pylab='InteractiveShellApp.pylab', matplotlib='InteractiveShellApp.matplotlib', ) shell_aliases['cache-size'] = 'InteractiveShell.cache_size' +if traitlets.version_info < (5, 0): + # traitlets 4 doesn't handle lists on CLI + shell_aliases["ext"] = "InteractiveShellApp.extra_extension" + + #----------------------------------------------------------------------------- # Main classes and functions #----------------------------------------------------------------------------- @@ -118,8 +125,27 @@ class InteractiveShellApp(Configurable): extensions = List(Unicode(), help="A list of dotted module names of IPython extensions to load." ).tag(config=True) - extra_extension = Unicode('', - help="dotted module name of an IPython extension to load." + + extra_extension = Unicode( + "", + help=""" + DEPRECATED. Dotted module name of a single extra IPython extension to load. + + Only one extension can be added this way. + + Only used with traitlets < 5.0, plural extra_extensions list is used in traitlets 5. + """, + ).tag(config=True) + + extra_extensions = List( + DottedObjectName(), + help=""" + Dotted module name(s) of one or more IPython extensions to load. + + For specifying extra extensions to load on the command-line. + + .. versionadded:: 7.10 + """, ).tag(config=True) reraise_ipython_extension_failures = Bool(False, @@ -264,7 +290,9 @@ def init_extensions(self): """ try: self.log.debug("Loading IPython extensions...") - extensions = self.default_extensions + self.extensions + extensions = ( + self.default_extensions + self.extensions + self.extra_extensions + ) if self.extra_extension: extensions.append(self.extra_extension) for ext in extensions: From 7477d1265ba2d6561b9e85f957423a9bea0368e2 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Tue, 6 Oct 2020 11:24:57 -0700 Subject: [PATCH 003/174] Backport PR #12587: [Docs] Improve installing docs if on zsh --- docs/source/install/install.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/install/install.rst b/docs/source/install/install.rst index 9888a8d3d95..5804fa83d52 100644 --- a/docs/source/install/install.rst +++ b/docs/source/install/install.rst @@ -90,7 +90,7 @@ grab the latest stable tarball of IPython `from PyPI tar -xzf ipython-5.1.0.tar.gz cd ipython-5.1.0 # The [test] extra ensures test dependencies are installed too: - pip install .[test] + pip install '.[test]' Do not invoke ``setup.py`` directly as this can have undesirable consequences for further upgrades. We do not recommend using ``easy_install`` either. @@ -123,7 +123,7 @@ Then do: $ git clone https://github.com/ipython/ipython.git $ cd ipython - $ pip install -e .[test] + $ pip install -e '.[test]' The :command:`pip install -e .` command allows users and developers to follow the development branch as it changes by creating links in the right places and From 1c391345835857f38c318dc39eb4a61754ba7fbf Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Thu, 8 Oct 2020 10:10:06 -0700 Subject: [PATCH 004/174] Redo PR #12601: Always display last frame when show tracebacks with hidden frames. Need manual re-implemetation as the code base was too different. --- IPython/core/ultratb.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/IPython/core/ultratb.py b/IPython/core/ultratb.py index 45e22bd7b94..4358ea5b9c0 100644 --- a/IPython/core/ultratb.py +++ b/IPython/core/ultratb.py @@ -886,9 +886,10 @@ def format_records(self, records, last_unique, recursion_repeat): frames = [] skipped = 0 - for r in records[:last_unique+recursion_repeat+1]: + lastrecord = len(records) - 1 + for i, r in enumerate(records[: last_unique + recursion_repeat + 1]): if self.skip_hidden: - if r[0].f_locals.get("__tracebackhide__", 0): + if r[0].f_locals.get("__tracebackhide__", 0) and i != lastrecord: skipped += 1 continue if skipped: From 7746415a576b895e1af090b171719d060ac4002c Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Mon, 12 Oct 2020 19:08:16 -0700 Subject: [PATCH 005/174] Backport PR #12617: skip test if ipykernel not there. --- IPython/core/tests/test_display.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/IPython/core/tests/test_display.py b/IPython/core/tests/test_display.py index 95f1eb622e4..0105ee85017 100644 --- a/IPython/core/tests/test_display.py +++ b/IPython/core/tests/test_display.py @@ -138,7 +138,9 @@ def _get_inline_config(): from ipykernel.pylab.config import InlineBackend return InlineBackend.instance() -@dec.skip_without('matplotlib') + +@dec.skip_without("ipykernel") +@dec.skip_without("matplotlib") def test_set_matplotlib_close(): cfg = _get_inline_config() cfg.close_figures = False @@ -173,7 +175,9 @@ def test_set_matplotlib_formats(): else: nt.assert_not_in(Figure, f) -@dec.skip_without('matplotlib') + +@dec.skip_without("ipykernel") +@dec.skip_without("matplotlib") def test_set_matplotlib_formats_kwargs(): from matplotlib.figure import Figure ip = get_ipython() From 86fe6bb5fa5056cbf824f01dde6f157050684994 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Tue, 20 Oct 2020 09:30:07 -0700 Subject: [PATCH 006/174] Backport PR #12625: Don't register the same callback multiple times --- IPython/core/events.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/IPython/core/events.py b/IPython/core/events.py index 6ebd790d4de..1af13ca406f 100644 --- a/IPython/core/events.py +++ b/IPython/core/events.py @@ -60,7 +60,8 @@ def register(self, event, function): if not callable(function): raise TypeError('Need a callable, got %r' % function) callback_proto = available_events.get(event) - self.callbacks[event].append(callback_proto.adapt(function)) + if function not in self.callbacks[event]: + self.callbacks[event].append(callback_proto.adapt(function)) def unregister(self, event, function): """Remove a callback from the given event.""" From 8660d404ee3b49716fb166778ad074ecbc1246be Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Wed, 21 Oct 2020 08:00:01 -0700 Subject: [PATCH 007/174] Backport PR #12631: Mark initial frame as not hidden. --- IPython/core/debugger.py | 13 ++++++++++--- IPython/core/interactiveshell.py | 5 +++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/IPython/core/debugger.py b/IPython/core/debugger.py index bf0a8eff3c3..4a311c2688e 100644 --- a/IPython/core/debugger.py +++ b/IPython/core/debugger.py @@ -287,6 +287,11 @@ def set_colors(self, scheme): self.color_scheme_table.set_active_scheme(scheme) self.parser.style = scheme + def set_trace(self, frame=None): + if frame is None: + frame = sys._getframe().f_back + self.initial_frame = frame + return super().set_trace(frame) def hidden_frames(self, stack): """ @@ -299,9 +304,11 @@ def hidden_frames(self, stack): # avoid calling it here to preserve self.curframe_locals. # Futhermore, there is no good reason to hide the current frame. ip_hide = [ - False if s[0] is self.curframe else s[0].f_locals.get( - "__tracebackhide__", False) - for s in stack] + False + if s[0] in (self.curframe, getattr(self, "initial_frame", None)) + else s[0].f_locals.get("__tracebackhide__", False) + for s in stack + ] ip_start = [i for i, s in enumerate(ip_hide) if s == "__ipython_bottom__"] if ip_start: ip_hide = [h if i > ip_start[0] else True for (i, h) in enumerate(ip_hide)] diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 8b10d58f6a7..a6906ebf229 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -740,8 +740,9 @@ def init_profile_dir(self, profile_dir): if profile_dir is not None: self.profile_dir = profile_dir return - self.profile_dir =\ - ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default') + self.profile_dir = ProfileDir.create_profile_dir_by_name( + self.ipython_dir, "default" + ) def init_instance_attrs(self): self.more = False From 8b0c699a384ee78e7c761f4c57c98807f1f583de Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Thu, 22 Oct 2020 17:26:07 -0700 Subject: [PATCH 008/174] Backport PR #12659: Fix settrace for recursive debugger --- IPython/core/debugger.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/IPython/core/debugger.py b/IPython/core/debugger.py index 4a311c2688e..94eebb66587 100644 --- a/IPython/core/debugger.py +++ b/IPython/core/debugger.py @@ -597,6 +597,7 @@ def do_debug(self, arg): argument (which is an arbitrary expression or statement to be executed in the current environment). """ + trace_function = sys.gettrace() sys.settrace(None) globals = self.curframe.f_globals locals = self.curframe_locals @@ -607,7 +608,7 @@ def do_debug(self, arg): self.message("ENTERING RECURSIVE DEBUGGER") sys.call_tracing(p.run, (arg, globals, locals)) self.message("LEAVING RECURSIVE DEBUGGER") - sys.settrace(self.trace_dispatch) + sys.settrace(trace_function) self.lastcmd = p.lastcmd def do_pdef(self, arg): From c64b113650d1e7110a1f1befa3df40b6c5dc86cf Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Mon, 26 Oct 2020 10:12:52 -0700 Subject: [PATCH 009/174] Backport PR #12627: Don't call curframe.f_locals --- IPython/core/debugger.py | 48 +++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/IPython/core/debugger.py b/IPython/core/debugger.py index 94eebb66587..ff83856211f 100644 --- a/IPython/core/debugger.py +++ b/IPython/core/debugger.py @@ -615,48 +615,60 @@ def do_pdef(self, arg): """Print the call signature for any callable object. The debugger interface to %pdef""" - namespaces = [('Locals', self.curframe.f_locals), - ('Globals', self.curframe.f_globals)] - self.shell.find_line_magic('pdef')(arg, namespaces=namespaces) + namespaces = [ + ("Locals", self.curframe_locals), + ("Globals", self.curframe.f_globals), + ] + self.shell.find_line_magic("pdef")(arg, namespaces=namespaces) def do_pdoc(self, arg): """Print the docstring for an object. The debugger interface to %pdoc.""" - namespaces = [('Locals', self.curframe.f_locals), - ('Globals', self.curframe.f_globals)] - self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces) + namespaces = [ + ("Locals", self.curframe_locals), + ("Globals", self.curframe.f_globals), + ] + self.shell.find_line_magic("pdoc")(arg, namespaces=namespaces) def do_pfile(self, arg): """Print (or run through pager) the file where an object is defined. The debugger interface to %pfile. """ - namespaces = [('Locals', self.curframe.f_locals), - ('Globals', self.curframe.f_globals)] - self.shell.find_line_magic('pfile')(arg, namespaces=namespaces) + namespaces = [ + ("Locals", self.curframe_locals), + ("Globals", self.curframe.f_globals), + ] + self.shell.find_line_magic("pfile")(arg, namespaces=namespaces) def do_pinfo(self, arg): """Provide detailed information about an object. The debugger interface to %pinfo, i.e., obj?.""" - namespaces = [('Locals', self.curframe.f_locals), - ('Globals', self.curframe.f_globals)] - self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces) + namespaces = [ + ("Locals", self.curframe_locals), + ("Globals", self.curframe.f_globals), + ] + self.shell.find_line_magic("pinfo")(arg, namespaces=namespaces) def do_pinfo2(self, arg): """Provide extra detailed information about an object. The debugger interface to %pinfo2, i.e., obj??.""" - namespaces = [('Locals', self.curframe.f_locals), - ('Globals', self.curframe.f_globals)] - self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces) + namespaces = [ + ("Locals", self.curframe_locals), + ("Globals", self.curframe.f_globals), + ] + self.shell.find_line_magic("pinfo2")(arg, namespaces=namespaces) def do_psource(self, arg): """Print (or run through pager) the source code for an object.""" - namespaces = [('Locals', self.curframe.f_locals), - ('Globals', self.curframe.f_globals)] - self.shell.find_line_magic('psource')(arg, namespaces=namespaces) + namespaces = [ + ("Locals", self.curframe_locals), + ("Globals", self.curframe.f_globals), + ] + self.shell.find_line_magic("psource")(arg, namespaces=namespaces) def do_where(self, arg): """w(here) From 09b525534d8cb82c434aac7f740ea8c98cf61151 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Tue, 27 Oct 2020 20:37:21 -0700 Subject: [PATCH 010/174] Backport PR #12681: Start working on whatsnew notes for 7.19. --- docs/source/whatsnew/version7.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/source/whatsnew/version7.rst b/docs/source/whatsnew/version7.rst index 2aeef66be21..f73728a4648 100644 --- a/docs/source/whatsnew/version7.rst +++ b/docs/source/whatsnew/version7.rst @@ -2,6 +2,36 @@ 7.x Series ============ +.. _version 719: + +IPython 7.19 +============ + +IPython 7.19 accumulative two month of works, bug fixes and improvements, there +was exceptionally no release last month. + + - Fix to restore the ability to specify more than one extension using command + line flags when using traitlets 5.0 :ghpull:`12543` + - Docs docs formatting that make the install commands work on zsh + :ghpull:`12587` + - Always display the last frame in tracebacks even if hidden with + ``__traceback_hide__`` :ghpull:`12601` + - Avoid an issue where a callback can be registered multiple times. + :ghpull:`12625` + - Avoid an issue in debugger mode where frames changes could be lost. + :ghpull:`12627` + + - Never hide the frames that invoke a debugger, even if marked as hidden by + ``__traceback_hide__`` :ghpull:`12631` + - Fix calling the debugger in a recursive manner :ghpull:`12659` + + +A number of code changes have landed on master and we are getting close to +enough new features and codebase improvement that a 8.0 start to make sens. +For downstream packages, please start working on migrating downstream testing +away from iptest and using pytest, as nose will not work on Python 3.10 and we +will likely start removing it as a dependency for testing. + .. _version 718: IPython 7.18 From 223e783c447a773a497809646ca0d874ea10ceeb Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Fri, 30 Oct 2020 11:12:26 -0700 Subject: [PATCH 011/174] release 7.19.0 --- IPython/core/release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IPython/core/release.py b/IPython/core/release.py index 570947666ed..988a1c6e3a1 100644 --- a/IPython/core/release.py +++ b/IPython/core/release.py @@ -24,7 +24,7 @@ _version_patch = 0 _version_extra = '.dev' # _version_extra = 'b1' -# _version_extra = '' # Uncomment this for full releases +_version_extra = '' # Uncomment this for full releases # Construct full version string from these. _ver = [_version_major, _version_minor, _version_patch] From 15a90c0890a9dfa3261af0f681bdb6a3db2247e6 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Fri, 30 Oct 2020 11:13:20 -0700 Subject: [PATCH 012/174] back to dev --- IPython/core/release.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IPython/core/release.py b/IPython/core/release.py index 988a1c6e3a1..d013a7f4b68 100644 --- a/IPython/core/release.py +++ b/IPython/core/release.py @@ -20,11 +20,11 @@ # release. 'dev' as a _version_extra string means this is a development # version _version_major = 7 -_version_minor = 19 +_version_minor = 20 _version_patch = 0 _version_extra = '.dev' # _version_extra = 'b1' -_version_extra = '' # Uncomment this for full releases +# _version_extra = '' # Uncomment this for full releases # Construct full version string from these. _ver = [_version_major, _version_minor, _version_patch] From b4029af73740a2cc1bf4ffa11e5dbe591d141feb Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Fri, 4 Dec 2020 11:47:50 -0800 Subject: [PATCH 013/174] Backport PR #12715: qt: sip changes for PyQt5 >= 5.11 --- IPython/external/qt_loaders.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/IPython/external/qt_loaders.py b/IPython/external/qt_loaders.py index 46cd9c35cb9..ca7483ec1c9 100644 --- a/IPython/external/qt_loaders.py +++ b/IPython/external/qt_loaders.py @@ -155,7 +155,12 @@ def qtapi_version(): try: import sip except ImportError: - return + # as of PyQt5 5.11, sip is no longer available as a top-level + # module and needs to be imported from the PyQt5 namespace + try: + from PyQt5 import sip + except ImportError: + return try: return sip.getapi('QString') except ValueError: From fd40c165f870f0665011574efcd777d4ef39e565 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Fri, 4 Dec 2020 11:49:22 -0800 Subject: [PATCH 014/174] Backport PR #12718: Mare reset -f more agressive and cull sys.modules; --- IPython/core/interactiveshell.py | 11 ++++++++++- IPython/core/magics/namespace.py | 10 +++++++--- IPython/core/shellapp.py | 1 + 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index a6906ebf229..75d8ff761c8 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -1410,7 +1410,7 @@ def all_ns_refs(self): return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \ [m.__dict__ for m in self._main_mod_cache.values()] - def reset(self, new_session=True): + def reset(self, new_session=True, aggressive=False): """Clear all internal namespaces, and attempt to release references to user objects. @@ -1447,6 +1447,15 @@ def reset(self, new_session=True): # Restore the user namespaces to minimal usability self.init_user_ns() + if aggressive and not hasattr(self, "_sys_modules_keys"): + print("Cannot restore sys.module, no snapshot") + elif aggressive: + print("culling sys module...") + current_keys = set(sys.modules.keys()) + for k in current_keys - self._sys_modules_keys: + if k.startswith("multiprocessing"): + continue + del sys.modules[k] # Restore the default and user aliases self.alias_manager.clear_aliases() diff --git a/IPython/core/magics/namespace.py b/IPython/core/magics/namespace.py index acc4620549b..5cc2d81ca2a 100644 --- a/IPython/core/magics/namespace.py +++ b/IPython/core/magics/namespace.py @@ -491,6 +491,10 @@ def reset(self, parameter_s=''): we do a 'hard' reset, giving you a new session and removing all references to objects from the current session. + --aggressive: Try to aggressively remove modules from sys.modules ; this + may allow you to reimport Python modules that have been updated and + pick up changes, but can have unattended consequences. + in : reset input history out : reset output history @@ -533,8 +537,8 @@ def reset(self, parameter_s=''): such as the ipython notebook interface, will reset the namespace without confirmation. """ - opts, args = self.parse_options(parameter_s,'sf', mode='list') - if 'f' in opts: + opts, args = self.parse_options(parameter_s, "sf", "aggressive", mode="list") + if "f" in opts: ans = True else: try: @@ -552,7 +556,7 @@ def reset(self, parameter_s=''): for i in self.who_ls(): del(user_ns[i]) elif len(args) == 0: # Hard reset - self.shell.reset(new_session = False) + self.shell.reset(new_session=False, aggressive=("aggressive" in opts)) # reset in/out/dhist/array: previously extensinions/clearcmd.py ip = self.shell diff --git a/IPython/core/shellapp.py b/IPython/core/shellapp.py index ee65d3af6c8..c442658ae70 100644 --- a/IPython/core/shellapp.py +++ b/IPython/core/shellapp.py @@ -331,6 +331,7 @@ def init_code(self): # flush output, so itwon't be attached to the first cell sys.stdout.flush() sys.stderr.flush() + self.shell._sys_modules_keys = set(sys.modules.keys()) def _run_exec_lines(self): """Run lines of code in IPythonApp.exec_lines in the user's namespace.""" From a1b87bd0a9aa47b6eb7b389fc807a152d53d7aef Mon Sep 17 00:00:00 2001 From: Damian Yurzola Date: Thu, 31 Dec 2020 13:44:34 -0800 Subject: [PATCH 015/174] Pin Jedi dependency. --- setup.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index f26c588c9de..95abf7106af 100755 --- a/setup.py +++ b/setup.py @@ -186,14 +186,14 @@ ) install_requires = [ - 'setuptools>=18.5', - 'jedi>=0.10', - 'decorator', - 'pickleshare', - 'traitlets>=4.2', - 'prompt_toolkit>=2.0.0,<3.1.0,!=3.0.0,!=3.0.1', - 'pygments', - 'backcall', + "setuptools>=18.5", + "jedi>=0.16,<0.18.0", + "decorator", + "pickleshare", + "traitlets>=4.2", + "prompt_toolkit>=2.0.0,<3.1.0,!=3.0.0,!=3.0.1", + "pygments", + "backcall", ] # Platform-specific dependencies: From f28565ddc6137cf50520e853e7619aed35e67d9c Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Mon, 11 Jan 2021 08:22:45 -0800 Subject: [PATCH 016/174] Backport PR #12765: Doc: Fix broken link --- docs/source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 090fb8865f7..39481bd2ba8 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -17,7 +17,7 @@ interactively. Its main components are: * A powerful interactive Python shell -.. image:: /_images/ipython-6-screenshot.png +.. image:: ./_images/ipython-6-screenshot.png :alt: Screenshot of IPython 6.0 :align: center From 595b77571c38f497e8e4692609528abcae9bed62 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Fri, 29 Jan 2021 15:21:40 +0200 Subject: [PATCH 017/174] Remove old ultratb.getargs See #12781. --- IPython/core/ultratb.py | 69 ----------------------------------------- 1 file changed, 69 deletions(-) diff --git a/IPython/core/ultratb.py b/IPython/core/ultratb.py index 4358ea5b9c0..de85a1f8ea6 100644 --- a/IPython/core/ultratb.py +++ b/IPython/core/ultratb.py @@ -234,72 +234,6 @@ def findsource(object): raise IOError('could not find code object') -# This is a patched version of inspect.getargs that applies the (unmerged) -# patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes -# https://github.com/ipython/ipython/issues/8205 and -# https://github.com/ipython/ipython/issues/8293 -def getargs(co): - """Get information about the arguments accepted by a code object. - - Three things are returned: (args, varargs, varkw), where 'args' is - a list of argument names (possibly containing nested lists), and - 'varargs' and 'varkw' are the names of the * and ** arguments or None.""" - if not iscode(co): - raise TypeError('{!r} is not a code object'.format(co)) - - nargs = co.co_argcount - names = co.co_varnames - args = list(names[:nargs]) - step = 0 - - # The following acrobatics are for anonymous (tuple) arguments. - for i in range(nargs): - if args[i][:1] in ('', '.'): - stack, remain, count = [], [], [] - while step < len(co.co_code): - op = ord(co.co_code[step]) - step = step + 1 - if op >= dis.HAVE_ARGUMENT: - opname = dis.opname[op] - value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256 - step = step + 2 - if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'): - remain.append(value) - count.append(value) - elif opname in ('STORE_FAST', 'STORE_DEREF'): - if op in dis.haslocal: - stack.append(co.co_varnames[value]) - elif op in dis.hasfree: - stack.append((co.co_cellvars + co.co_freevars)[value]) - # Special case for sublists of length 1: def foo((bar)) - # doesn't generate the UNPACK_TUPLE bytecode, so if - # `remain` is empty here, we have such a sublist. - if not remain: - stack[0] = [stack[0]] - break - else: - remain[-1] = remain[-1] - 1 - while remain[-1] == 0: - remain.pop() - size = count.pop() - stack[-size:] = [stack[-size:]] - if not remain: - break - remain[-1] = remain[-1] - 1 - if not remain: - break - args[i] = stack[0] - - varargs = None - if co.co_flags & inspect.CO_VARARGS: - varargs = co.co_varnames[nargs] - nargs = nargs + 1 - varkw = None - if co.co_flags & inspect.CO_VARKEYWORDS: - varkw = co.co_varnames[nargs] - return inspect.Arguments(args, varargs, varkw) - - # Monkeypatch inspect to apply our bugfix. def with_patch_inspect(f): """ @@ -309,14 +243,11 @@ def with_patch_inspect(f): def wrapped(*args, **kwargs): save_findsource = inspect.findsource - save_getargs = inspect.getargs inspect.findsource = findsource - inspect.getargs = getargs try: return f(*args, **kwargs) finally: inspect.findsource = save_findsource - inspect.getargs = save_getargs return wrapped From 5e979ec2119487e0d6ac33292f07ab62826645a5 Mon Sep 17 00:00:00 2001 From: Diego Fernandez Date: Thu, 26 Mar 2020 14:07:22 -0600 Subject: [PATCH 018/174] Backport PR #12207 on 7.x This should make jedi 0.18 compatible with 7.x. Pinning is not an option as the resolver is free to pick older IPython with jedi 0.18 -- Bump jedi to at least 0.16.0 and fix deprecated function usage --- IPython/core/completer.py | 5 +++-- setup.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/IPython/core/completer.py b/IPython/core/completer.py index bc114f0f66b..374a35d7aed 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -988,7 +988,8 @@ def _make_signature(completion)-> str: """ - return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for p in completion.params) if f]) + return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for signature in completion.get_signatures() + for p in signature.defined_names()) if f]) class IPCompleter(Completer): """Extension of the completer class with IPython-specific features""" @@ -1398,7 +1399,7 @@ def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str): if not try_jedi: return [] try: - return filter(completion_filter, interpreter.completions()) + return filter(completion_filter, interpreter.complete()) except Exception as e: if self.debug: return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))] diff --git a/setup.py b/setup.py index 95abf7106af..52919284683 100755 --- a/setup.py +++ b/setup.py @@ -187,7 +187,7 @@ install_requires = [ "setuptools>=18.5", - "jedi>=0.16,<0.18.0", + "jedi>=0.16", "decorator", "pickleshare", "traitlets>=4.2", From 477d9a611747a0da0787cd3af97bb5426dd9ec64 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Fri, 29 Jan 2021 15:15:29 -0800 Subject: [PATCH 019/174] forgotten imports --- IPython/terminal/ptutils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/IPython/terminal/ptutils.py b/IPython/terminal/ptutils.py index 3cf3c11215b..3e5d3c5c770 100644 --- a/IPython/terminal/ptutils.py +++ b/IPython/terminal/ptutils.py @@ -9,6 +9,8 @@ import unicodedata from wcwidth import wcwidth +import sys +import traceback from IPython.core.completer import ( provisionalcompleter, cursor_to_position, From 21d3379ce83462caf75d78479420e457e7bc48aa Mon Sep 17 00:00:00 2001 From: gorogoroumaru Date: Fri, 10 Apr 2020 10:24:52 +0900 Subject: [PATCH 020/174] Backport PR #12227 on brnach 7.x This is for Jedi 0.18 compatibility. Fix DeprecationWarning on autocompletion with jedi 0.17.0 --- IPython/core/completer.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/IPython/core/completer.py b/IPython/core/completer.py index 374a35d7aed..b5d5a836fbc 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -110,26 +110,23 @@ # Copyright (C) 2001 Python Software Foundation, www.python.org -import __main__ import builtins as builtin_mod import glob -import time import inspect import itertools import keyword import os import re +import string import sys +import time import unicodedata -import string import warnings - from contextlib import contextmanager from importlib import import_module -from typing import Iterator, List, Tuple, Iterable from types import SimpleNamespace +from typing import Iterable, Iterator, List, Tuple -from traitlets.config.configurable import Configurable from IPython.core.error import TryNext from IPython.core.inputtransformer2 import ESC_MAGIC from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol @@ -137,7 +134,10 @@ from IPython.utils import generics from IPython.utils.dir2 import dir2, get_real_method from IPython.utils.process import arg_split -from traitlets import Bool, Enum, observe, Int +from traitlets import Bool, Enum, Int, observe +from traitlets.config.configurable import Configurable + +import __main__ # skip module docstests skip_doctest = True @@ -1371,8 +1371,7 @@ def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str): else: raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names)) - interpreter = jedi.Interpreter( - text[:offset], namespaces, column=cursor_column, line=cursor_line + 1) + interpreter = jedi.Interpreter(text[:offset], namespaces) try_jedi = True try: @@ -1399,7 +1398,7 @@ def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str): if not try_jedi: return [] try: - return filter(completion_filter, interpreter.complete()) + return filter(completion_filter, interpreter.complete(column=cursor_column, line=cursor_line + 1)) except Exception as e: if self.debug: return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))] From 8abc94f7cb4001e1a39d7890cb239ad59ee86350 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Tue, 21 Apr 2020 21:10:23 -0700 Subject: [PATCH 021/174] Backport PR #12255: fix getting signatures in jedi 0.17 --- IPython/core/completer.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/IPython/core/completer.py b/IPython/core/completer.py index b5d5a836fbc..77bcd44b710 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -988,6 +988,15 @@ def _make_signature(completion)-> str: """ + # it looks like this might work on jedi 0.17 + if hasattr(completion, 'get_signatures'): + signatures = completion.get_signatures() + if not signatures: + return '(?)' + + c0 = completion.get_signatures()[0] + return '('+c0.to_string().split('(', maxsplit=1)[1] + return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for signature in completion.get_signatures() for p in signature.defined_names()) if f]) From f4ee99f997949d57fcccb9c4e1b3eecfa45eff32 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Mon, 1 Feb 2021 10:27:25 -0800 Subject: [PATCH 022/174] Backport PR #12799: Whats new 7.20 --- docs/source/whatsnew/version7.rst | 35 ++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/source/whatsnew/version7.rst b/docs/source/whatsnew/version7.rst index f73728a4648..3bad5272d2c 100644 --- a/docs/source/whatsnew/version7.rst +++ b/docs/source/whatsnew/version7.rst @@ -2,6 +2,39 @@ 7.x Series ============ +.. _version 720: + +IPython 7.20 +============ + +IPython 7.20 is the accumulation of 3 month of work on IPython, spacing between +IPython release have been increased from the usual once a month for various +reason. + + - Mainly as I'm too busy and the effectively sole maintainer, and + - Second because not much changes happened before mid December. + +The main driver for this release was the new version of Jedi 0.18 breaking API; +which was taken care of in the master branch early in 2020 but not in 7.x as I +though that by now 8.0 would be out. + +The inclusion of a resolver in pip did not help and actually made things worse. +If usually I would have simply pinned Jedi to ``<0.18``; this is not a solution +anymore as now pip is free to install Jedi 0.18, and downgrade IPython. + +I'll do my best to keep the regular release, but as the 8.0-dev branch and 7.x +are starting to diverge this is becoming difficult in particular with my limited +time, so if you have any cycles to spare I'll appreciate your help to respond to +issues and pushing 8.0 forward. + +Here are thus some of the changes for IPython 7.20. + + - Support for PyQt5 >= 5.11 :ghpull:`12715` + - ``%reset`` remove imports more agressively :ghpull:`12718` + - fix the ``%conda`` magic :ghpull:`12739` + - compatibility with Jedi 0.18, and bump minimum Jedi version. :ghpull:`12793` + + .. _version 719: IPython 7.19 @@ -55,7 +88,7 @@ IPython 7.17 ============ IPython 7.17 brings a couple of new improvements to API and a couple of user -facing changes to make the terminal experience more user friendly. +facing changes to make the terminal experience more user friendly. :ghpull:`12407` introduces the ability to pass extra argument to the IPython debugger class; this is to help a new project from ``kmaork`` From ebfd01dae45798fc57d9b4d8661d378c670ad37c Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Mon, 1 Feb 2021 11:15:15 -0800 Subject: [PATCH 023/174] release 7.20.0 --- IPython/core/release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IPython/core/release.py b/IPython/core/release.py index d013a7f4b68..786ce6d5f54 100644 --- a/IPython/core/release.py +++ b/IPython/core/release.py @@ -24,7 +24,7 @@ _version_patch = 0 _version_extra = '.dev' # _version_extra = 'b1' -# _version_extra = '' # Uncomment this for full releases +_version_extra = '' # Uncomment this for full releases # Construct full version string from these. _ver = [_version_major, _version_minor, _version_patch] From d54611b6bff7ea09f458c1bb5ba6c24e74ecd88e Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Mon, 1 Feb 2021 11:19:11 -0800 Subject: [PATCH 024/174] back to dev --- IPython/core/release.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IPython/core/release.py b/IPython/core/release.py index 786ce6d5f54..bf87fe1a21d 100644 --- a/IPython/core/release.py +++ b/IPython/core/release.py @@ -20,11 +20,11 @@ # release. 'dev' as a _version_extra string means this is a development # version _version_major = 7 -_version_minor = 20 +_version_minor = 21 _version_patch = 0 _version_extra = '.dev' # _version_extra = 'b1' -_version_extra = '' # Uncomment this for full releases +# _version_extra = '' # Uncomment this for full releases # Construct full version string from these. _ver = [_version_major, _version_minor, _version_patch] From d9a654c558623c77e7dd393a1a89572fb2cfaa81 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Tue, 2 Feb 2021 10:08:06 -0800 Subject: [PATCH 025/174] Backport PR #12804: Add explicit argtype counting, required for osx-arm64. --- IPython/terminal/pt_inputhooks/osx.py | 44 +++++++++++++++++++-------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/IPython/terminal/pt_inputhooks/osx.py b/IPython/terminal/pt_inputhooks/osx.py index 53f4e3838b8..a3131ee4683 100644 --- a/IPython/terminal/pt_inputhooks/osx.py +++ b/IPython/terminal/pt_inputhooks/osx.py @@ -77,24 +77,42 @@ def C(classname): def _NSApp(): """Return the global NSApplication instance (NSApp)""" + objc.objc_msgSend.argtypes = [void_p, void_p] return msg(C('NSApplication'), n('sharedApplication')) def _wake(NSApp): """Wake the Application""" - event = msg(C('NSEvent'), - n('otherEventWithType:location:modifierFlags:' - 'timestamp:windowNumber:context:subtype:data1:data2:'), - 15, # Type - 0, # location - 0, # flags - 0, # timestamp - 0, # window - None, # context - 0, # subtype - 0, # data1 - 0, # data2 + objc.objc_msgSend.argtypes = [ + void_p, + void_p, + void_p, + void_p, + void_p, + void_p, + void_p, + void_p, + void_p, + void_p, + void_p, + ] + event = msg( + C("NSEvent"), + n( + "otherEventWithType:location:modifierFlags:" + "timestamp:windowNumber:context:subtype:data1:data2:" + ), + 15, # Type + 0, # location + 0, # flags + 0, # timestamp + 0, # window + None, # context + 0, # subtype + 0, # data1 + 0, # data2 ) + objc.objc_msgSend.argtypes = [void_p, void_p, void_p, void_p] msg(NSApp, n('postEvent:atStart:'), void_p(event), True) @@ -106,6 +124,7 @@ def _input_callback(fdref, flags, info): CFFileDescriptorInvalidate(fdref) CFRelease(fdref) NSApp = _NSApp() + objc.objc_msgSend.argtypes = [void_p, void_p, void_p] msg(NSApp, n('stop:'), NSApp) _wake(NSApp) @@ -128,6 +147,7 @@ def inputhook(context): """Inputhook for Cocoa (NSApp)""" NSApp = _NSApp() _stop_on_read(context.fileno()) + objc.objc_msgSend.argtypes = [void_p, void_p] msg(NSApp, n('run')) if not _triggered.is_set(): # app closed without firing callback, From 7915fc24f05a6ec2d073ed805c2db9e8d4a6f0ba Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Thu, 4 Feb 2021 10:15:58 -0800 Subject: [PATCH 026/174] Backport PR #12807: Fix CFFileDescriptorCreate argtypes. --- IPython/terminal/pt_inputhooks/osx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IPython/terminal/pt_inputhooks/osx.py b/IPython/terminal/pt_inputhooks/osx.py index 53f4e3838b8..de96a52d5c5 100644 --- a/IPython/terminal/pt_inputhooks/osx.py +++ b/IPython/terminal/pt_inputhooks/osx.py @@ -41,7 +41,7 @@ def C(classname): CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate CFFileDescriptorCreate.restype = void_p -CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p] +CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p, void_p] CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int From 3d73b3e52c8dc184dab3e10f5e71c297a8bd47de Mon Sep 17 00:00:00 2001 From: Sylvain Corlay Date: Thu, 11 Feb 2021 22:04:55 +0100 Subject: [PATCH 027/174] Backport PR #12809: Allow passing a custom CachingCompiler to the interactive shell --- IPython/core/compilerop.py | 44 ++++++++-- IPython/core/interactiveshell.py | 142 +++++++++++++++++-------------- 2 files changed, 112 insertions(+), 74 deletions(-) diff --git a/IPython/core/compilerop.py b/IPython/core/compilerop.py index c4771af7303..50672a19541 100644 --- a/IPython/core/compilerop.py +++ b/IPython/core/compilerop.py @@ -99,7 +99,7 @@ def ast_parse(self, source, filename='', symbol='exec'): Arguments are exactly the same as ast.parse (in the standard library), and are passed to the built-in compile function.""" return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1) - + def reset_compiler_flags(self): """Reset compiler flags to default state.""" # This value is copied from codeop.Compile.__init__, so if that ever @@ -112,25 +112,53 @@ def compiler_flags(self): """ return self.flags - def cache(self, code, number=0): + def get_code_name(self, raw_code, transformed_code, number): + """Compute filename given the code, and the cell number. + + Parameters + ---------- + raw_code : str + The raw cell code. + transformed_code : str + The executable Python source code to cache and compile. + number : int + A number which forms part of the code's name. Used for the execution + counter. + + Returns + ------- + The computed filename. + """ + return code_name(transformed_code, number) + + def cache(self, transformed_code, number=0, raw_code=None): """Make a name for a block of code, and cache the code. Parameters ---------- - code : str - The Python source code to cache. + transformed_code : str + The executable Python source code to cache and compile. number : int A number which forms part of the code's name. Used for the execution counter. + raw_code : str + The raw code before transformation, if None, set to `transformed_code`. Returns ------- The name of the cached code (as a string). Pass this as the filename argument to compilation, so that tracebacks are correctly hooked up. """ - name = code_name(code, number) - entry = (len(code), time.time(), - [line+'\n' for line in code.splitlines()], name) + if raw_code is None: + raw_code = transformed_code + + name = self.get_code_name(raw_code, transformed_code, number) + entry = ( + len(transformed_code), + time.time(), + [line + "\n" for line in transformed_code.splitlines()], + name, + ) linecache.cache[name] = entry linecache._ipython_cache[name] = entry return name @@ -146,7 +174,7 @@ def extra_flags(self, flags): yield finally: # turn off only the bits we turned on so that something like - # __future__ that set flags stays. + # __future__ that set flags stays. self.flags &= ~turn_on_bits diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 75d8ff761c8..6ab436fc566 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -340,7 +340,7 @@ class InteractiveShell(SingletonConfigurable): """An enhanced, interactive shell for Python.""" _instance = None - + ast_transformers = List([], help= """ A list of ast.NodeTransformer subclass instances, which will be applied @@ -407,7 +407,7 @@ def _import_runner(self, proposal): Enable magic commands to be called without the leading %. """ ).tag(config=True) - + banner1 = Unicode(default_banner, help="""The part of the banner to be printed before the profile""" ).tag(config=True) @@ -443,7 +443,8 @@ def _import_runner(self, proposal): display_formatter = Instance(DisplayFormatter, allow_none=True) displayhook_class = Type(DisplayHook) display_pub_class = Type(DisplayPublisher) - + compiler_class = Type(CachingCompiler) + sphinxify_docstring = Bool(False, help= """ Enables rich html representation of docstrings. (This requires the @@ -534,7 +535,7 @@ def input_splitter(self): ).tag(config=True) # deprecated prompt traits: - + prompt_in1 = Unicode('In [\\#]: ', help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." ).tag(config=True) @@ -547,14 +548,14 @@ def input_splitter(self): prompts_pad_left = Bool(True, help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." ).tag(config=True) - + @observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left') def _prompt_trait_changed(self, change): name = change['name'] warn("InteractiveShell.{name} is deprecated since IPython 4.0" " and ignored since 5.0, set TerminalInteractiveShell.prompts" " object directly.".format(name=name)) - + # protect against weird cases where self.config may not exist: show_rewritten_input = Bool(True, @@ -638,7 +639,7 @@ def __init__(self, ipython_dir=None, profile_dir=None, self.init_profile_dir(profile_dir) self.init_instance_attrs() self.init_environment() - + # Check if we're in a virtualenv, and set up sys.path. self.init_virtualenv() @@ -748,7 +749,7 @@ def init_instance_attrs(self): self.more = False # command compiler - self.compile = CachingCompiler() + self.compile = self.compiler_class() # Make an empty namespace, which extension writers can rely on both # existing and NEVER being used by ipython itself. This gives them a @@ -975,7 +976,7 @@ def restore_sys_module_state(self): #------------------------------------------------------------------------- # Things related to the banner #------------------------------------------------------------------------- - + @property def banner(self): banner = self.banner1 @@ -989,7 +990,7 @@ def show_banner(self, banner=None): if banner is None: banner = self.banner sys.stdout.write(banner) - + #------------------------------------------------------------------------- # Things related to hooks #------------------------------------------------------------------------- @@ -1006,10 +1007,10 @@ def init_hooks(self): # default hooks have priority 100, i.e. low; user hooks should have # 0-100 priority self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False) - + if self.display_page: self.set_hook('show_in_pager', page.as_hook(page.display_page), 90) - + def set_hook(self,name,hook, priority=50, str_key=None, re_key=None, _warn_deprecated=True): """set_hook(name,hook) -> sets an internal IPython hook. @@ -1073,7 +1074,7 @@ def register_post_execute(self, func): warn("ip.register_post_execute is deprecated, use " "ip.events.register('post_run_cell', func) instead.", stacklevel=2) self.events.register('post_run_cell', func) - + def _clear_warning_registry(self): # clear the warning registry, so that different code blocks with # overlapping line number ranges don't cause spurious suppression of @@ -1115,12 +1116,12 @@ def new_main_mod(self, filename, modname): else: main_mod.__dict__.clear() main_mod.__name__ = modname - + main_mod.__file__ = filename # It seems pydoc (and perhaps others) needs any module instance to # implement a __nonzero__ method main_mod.__nonzero__ = lambda : True - + return main_mod def clear_main_mod_cache(self): @@ -1273,7 +1274,7 @@ def init_create_namespaces(self, user_module=None, user_ns=None): 'user_local':self.user_ns, 'builtin':builtin_mod.__dict__ } - + @property def user_global_ns(self): return self.user_module.__dict__ @@ -1306,17 +1307,17 @@ def prepare_user_module(self, user_module=None, user_ns=None): user_ns.setdefault("__name__", "__main__") user_module = DummyMod() user_module.__dict__ = user_ns - + if user_module is None: user_module = types.ModuleType("__main__", doc="Automatically created module for IPython interactive environment") - + # We must ensure that __builtin__ (without the final 's') is always # available and pointing to the __builtin__ *module*. For more details: # http://mail.python.org/pipermail/python-dev/2001-April/014068.html user_module.__dict__.setdefault('__builtin__', builtin_mod) user_module.__dict__.setdefault('__builtins__', builtin_mod) - + if user_ns is None: user_ns = user_module.__dict__ @@ -1372,7 +1373,7 @@ def init_user_ns(self): # For more details: # http://mail.python.org/pipermail/python-dev/2001-April/014068.html ns = {} - + # make global variables for user access to the histories ns['_ih'] = self.history_manager.input_hist_parsed ns['_oh'] = self.history_manager.output_hist @@ -1385,7 +1386,7 @@ def init_user_ns(self): # Store myself as the public api!!! ns['get_ipython'] = self.get_ipython - + ns['exit'] = self.exiter ns['quit'] = self.exiter @@ -1399,7 +1400,7 @@ def init_user_ns(self): # Finally, update the real user's namespace self.user_ns.update(ns) - + @property def all_ns_refs(self): """Get a list of references to all the namespace dictionaries in which @@ -1425,7 +1426,7 @@ def reset(self, new_session=True, aggressive=False): # Reset last execution result self.last_execution_succeeded = True self.last_execution_result = None - + # Flush cached output items if self.displayhook.do_full_cache: self.displayhook.flush() @@ -1490,7 +1491,7 @@ def del_var(self, varname, by_name=False): raise ValueError("Refusing to delete %s" % varname) ns_refs = self.all_ns_refs - + if by_name: # Delete by name for ns in ns_refs: try: @@ -1765,8 +1766,14 @@ def _inspect(self, meth, oname, namespaces=None, **kw): if meth == 'pdoc': pmethod(info.obj, oname, formatter) elif meth == 'pinfo': - pmethod(info.obj, oname, formatter, info, - enable_html_pager=self.enable_html_pager, **kw) + pmethod( + info.obj, + oname, + formatter, + info, + enable_html_pager=self.enable_html_pager, + **kw + ) else: pmethod(info.obj, oname) else: @@ -1890,7 +1897,7 @@ def dummy_handler(self, etype, value, tb, tb_offset=None): print('Exception type :', etype) print('Exception value:', value) print('Traceback :', tb) - + def validate_stb(stb): """validate structured traceback return type @@ -1919,7 +1926,7 @@ def validate_stb(stb): else: def wrapped(self,etype,value,tb,tb_offset=None): """wrap CustomTB handler, to protect IPython from user code - + This makes it harder (but not impossible) for custom exception handlers to crash IPython. """ @@ -1968,10 +1975,10 @@ def excepthook(self, etype, value, tb): def _get_exc_info(self, exc_tuple=None): """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc. - + Ensures sys.last_type,value,traceback hold the exc_info we found, from whichever source. - + raises ValueError if none of these contain any information """ if exc_tuple is None: @@ -1983,10 +1990,10 @@ def _get_exc_info(self, exc_tuple=None): if hasattr(sys, 'last_type'): etype, value, tb = sys.last_type, sys.last_value, \ sys.last_traceback - + if etype is None: raise ValueError("No exception to find") - + # Now store the exception info in sys.last_type etc. # WARNING: these variables are somewhat deprecated and not # necessarily safe to use in a threaded environment, but tools @@ -1995,16 +2002,16 @@ def _get_exc_info(self, exc_tuple=None): sys.last_type = etype sys.last_value = value sys.last_traceback = tb - + return etype, value, tb - + def show_usage_error(self, exc): """Show a short message for UsageErrors - + These are special exceptions that shouldn't show a traceback. """ print("UsageError: %s" % exc, file=sys.stderr) - + def get_exception_only(self, exc_tuple=None): """ Return as a string (ending with a newline) the exception that @@ -2118,7 +2125,7 @@ def showindentationerror(self): def init_readline(self): """DEPRECATED - + Moved to terminal subclass, here only to simplify the init logic.""" # Set a number of methods that depend on readline to be no-op warnings.warn('`init_readline` is no-op since IPython 5.0 and is Deprecated', @@ -2285,12 +2292,13 @@ def init_magics(self): # should be split into a prompt manager and displayhook. We probably # even need a centralize colors management object. self.run_line_magic('colors', self.colors) - + # Defined here so that it's included in the documentation @functools.wraps(magic.MagicsManager.register_function) def register_magic_function(self, func, magic_kind='line', magic_name=None): - self.magics_manager.register_function(func, - magic_kind=magic_kind, magic_name=magic_name) + self.magics_manager.register_function( + func, magic_kind=magic_kind, magic_name=magic_name + ) def run_line_magic(self, magic_name, line, _stack_depth=1): """Execute the given line magic. @@ -2525,7 +2533,7 @@ def system_raw(self, cmd): ec = 130 if ec > 128: ec = -(ec - 128) - + # We explicitly do NOT return the subprocess status code, because # a non-None value would trigger :func:`sys.displayhook` calls. # Instead, we store the exit_code in user_ns. Note the semantics @@ -2588,7 +2596,7 @@ def init_extension_manager(self): def init_payload(self): self.payload_manager = PayloadManager(parent=self) self.configurables.append(self.payload_manager) - + #------------------------------------------------------------------------- # Things related to the prefilter #------------------------------------------------------------------------- @@ -2628,13 +2636,13 @@ def auto_rewrite_input(self, cmd): def _user_obj_error(self): """return simple exception dict - + for use in user_expressions """ - + etype, evalue, tb = self._get_exc_info() stb = self.InteractiveTB.get_exception_only(etype, evalue) - + exc_info = { u'status' : 'error', u'traceback' : stb, @@ -2643,13 +2651,13 @@ def _user_obj_error(self): } return exc_info - + def _format_user_obj(self, obj): """format a user object to display dict - + for use in user_expressions """ - + data, md = self.display_formatter.format(obj) value = { 'status' : 'ok', @@ -2657,7 +2665,7 @@ def _format_user_obj(self, obj): 'metadata' : md, } return value - + def user_expressions(self, expressions): """Evaluate a dict of expressions in the user's namespace. @@ -2676,7 +2684,7 @@ def user_expressions(self, expressions): out = {} user_ns = self.user_ns global_ns = self.user_global_ns - + for key, expr in expressions.items(): try: value = self._format_user_obj(eval(expr, global_ns, user_ns)) @@ -3092,12 +3100,14 @@ def error_before_exec(value): # Our own compiler remembers the __future__ environment. If we want to # run code with a separate __future__ environment, use the default # compiler - compiler = self.compile if shell_futures else CachingCompiler() + compiler = self.compile if shell_futures else self.compiler_class() _run_async = False with self.builtin_trap: - cell_name = self.compile.cache(cell, self.execution_count) + cell_name = self.compile.cache( + cell, self.execution_count, raw_code=raw_cell + ) with self.display_trap: # Compile to bytecode @@ -3203,13 +3213,13 @@ def transform_cell(self, raw_cell): def transform_ast(self, node): """Apply the AST transformations from self.ast_transformers - + Parameters ---------- node : ast.Node The root node to be transformed. Typically called with the ast.Module produced by parsing user input. - + Returns ------- An ast.Node corresponding to the node it was called with. Note that it @@ -3256,7 +3266,7 @@ async def run_ast_nodes(self, nodelist:ListType[AST], cell_name:str, interactivi Experimental value: 'async' Will try to run top level interactive async/await code in default runner, this will not respect the interactivity setting and will only run the last node if it is an - expression. + expression. compiler : callable A function with the same interface as the built-in compile(), to turn @@ -3477,17 +3487,17 @@ def check_complete(self, code: str) -> Tuple[str, str]: def enable_gui(self, gui=None): raise NotImplementedError('Implement enable_gui in a subclass') - + def enable_matplotlib(self, gui=None): """Enable interactive matplotlib and inline figure support. - + This takes the following steps: - + 1. select the appropriate eventloop and matplotlib backend 2. set up matplotlib for interactive use with that backend 3. configure formatters for inline figure display 4. enable the selected gui eventloop - + Parameters ---------- gui : optional, string @@ -3501,7 +3511,7 @@ def enable_matplotlib(self, gui=None): """ from IPython.core import pylabtools as pt gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select) - + if gui != 'inline': # If we have our first gui selection, store it if self.pylab_gui_select is None: @@ -3511,16 +3521,16 @@ def enable_matplotlib(self, gui=None): print('Warning: Cannot change to a different GUI toolkit: %s.' ' Using %s instead.' % (gui, self.pylab_gui_select)) gui, backend = pt.find_gui_and_backend(self.pylab_gui_select) - + pt.activate_matplotlib(backend) pt.configure_inline_support(self, backend) - + # Now we must activate the gui pylab wants to use, and fix %run to take # plot updates into account self.enable_gui(gui) self.magics_manager.registry['ExecutionMagics'].default_runner = \ pt.mpl_runner(self.safe_execfile) - + return gui, backend def enable_pylab(self, gui=None, import_all=True, welcome_message=False): @@ -3530,7 +3540,7 @@ def enable_pylab(self, gui=None, import_all=True, welcome_message=False): namespace all of numpy and pylab, and configures IPython to correctly interact with the GUI event loop. The GUI backend to be used can be optionally selected with the optional ``gui`` argument. - + This method only adds preloading the namespace to InteractiveShell.enable_matplotlib. Parameters @@ -3550,9 +3560,9 @@ def enable_pylab(self, gui=None, import_all=True, welcome_message=False): This argument is ignored, no welcome message will be displayed. """ from IPython.core.pylabtools import import_pylab - + gui, backend = self.enable_matplotlib(gui) - + # We want to prevent the loading of pylab to pollute the user's # namespace as shown by the %who* magics, so we execute the activation # code in an empty namespace, and we update *both* user_ns and From 26c1b1e1a4f77f1399227ec41d60162ca5088772 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Fri, 26 Feb 2021 09:36:12 -0800 Subject: [PATCH 028/174] Backport PR #12824: misc fix doc --- IPython/core/completer.py | 20 +++++++++++++++----- IPython/core/display.py | 16 ++++++++-------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/IPython/core/completer.py b/IPython/core/completer.py index 77bcd44b710..238929cc6ff 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -193,7 +193,9 @@ def provisionalcompleter(action='ignore'): >>> completer.do_experimental_things() # raises. - .. note:: Unstable + .. note:: + + Unstable By using this context manager you agree that the API in use may change without warning, and that you won't complain if they do so. @@ -348,7 +350,9 @@ class Completion: """ Completion object used and return by IPython completers. - .. warning:: Unstable + .. warning:: + + Unstable This function is unstable, API may change without warning. It will also raise unless use in proper context manager. @@ -411,7 +415,9 @@ def _deduplicate_completions(text: str, completions: _IC)-> _IC: """ Deduplicate a set of completions. - .. warning:: Unstable + .. warning:: + + Unstable This function is unstable, API may change without warning. @@ -454,7 +460,9 @@ def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC: """ Rectify a set of completions to all have the same ``start`` and ``end`` - .. warning:: Unstable + .. warning:: + + Unstable This function is unstable, API may change without warning. It will also raise unless use in proper context manager. @@ -1776,7 +1784,9 @@ def completions(self, text: str, offset: int)->Iterator[Completion]: """ Returns an iterator over the possible completions - .. warning:: Unstable + .. warning:: + + Unstable This function is unstable, API may change without warning. It will also raise unless use in proper context manager. diff --git a/IPython/core/display.py b/IPython/core/display.py index 424414a662f..48af5b40390 100644 --- a/IPython/core/display.py +++ b/IPython/core/display.py @@ -1340,19 +1340,19 @@ def __init__(self, data=None, url=None, filename=None, embed=False, ---------- data : unicode, str or bytes The raw video data or a URL or filename to load the data from. - Raw data will require passing `embed=True`. + Raw data will require passing ``embed=True``. url : unicode - A URL for the video. If you specify `url=`, + A URL for the video. If you specify ``url=``, the image data will not be embedded. filename : unicode Path to a local file containing the video. - Will be interpreted as a local URL unless `embed=True`. + Will be interpreted as a local URL unless ``embed=True``. embed : bool Should the video be embedded using a data URI (True) or be loaded using a