Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-spyder-kernels for
openSUSE:Factory checked in at 2022-07-26 19:45:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-spyder-kernels (Old)
and /work/SRC/openSUSE:Factory/.python-spyder-kernels.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-spyder-kernels"
Tue Jul 26 19:45:02 2022 rev:35 rq:991040 version:2.3.2
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-spyder-kernels/python-spyder-kernels.changes
2022-05-31 15:47:55.548009871 +0200
+++
/work/SRC/openSUSE:Factory/.python-spyder-kernels.new.1533/python-spyder-kernels.changes
2022-07-26 19:45:04.549765431 +0200
@@ -1,0 +2,21 @@
+Mon Jul 25 12:31:50 UTC 2022 - Ben Greiner <[email protected]>
+
+- Update to version 2.3.2
+ * Fixed issue 394 - The variable explorer is broken while
+ debugging
+ * PR 399: Increase minimal required version of jupyter_client to
+ 7.3.4, by @ccordoba12
+ * PR 398: Fix module namespace, by @impact27
+ * PR 395: Fix running namespace and improve eventloop integration
+ while debugging, by @impact27 (394)
+ * PR 389: Fix debug filename path for remote debugging, by
+ @impact27 (18330)
+ * PR 388: Fix getting args from functions or methods, by
+ @ccordoba12
+ * PR 386: Fix flaky test, by @impact27
+ * PR 381: Eliminate unnecessary updates of the Variable Explorer
+ while debugging, by @rear1019
+ * PR 378: Append paths that come from Spyder's Python path
+ manager to the end of sys.path, by @mrclary
+
+-------------------------------------------------------------------
Old:
----
python-spyder-kernels-2.3.1.tar.gz
New:
----
python-spyder-kernels-2.3.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-spyder-kernels.spec ++++++
--- /var/tmp/diff_new_pack.MzBuxs/_old 2022-07-26 19:45:05.017693125 +0200
+++ /var/tmp/diff_new_pack.MzBuxs/_new 2022-07-26 19:45:05.021692507 +0200
@@ -21,7 +21,7 @@
# flaky for obs, only test locally
%bcond_with dasktest
Name: python-spyder-kernels
-Version: 2.3.1
+Version: 2.3.2
Release: 0
Summary: Jupyter kernels for Spyder's console
License: MIT
@@ -29,7 +29,6 @@
URL: https://github.com/spyder-ide/spyder-kernels
# PyPI tarballs do not include the tests:
https://github.com/spyder-ide/spyder-kernels/issues/66
Source: %{url}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
-BuildRequires: %{python_module base >= 3.7}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
@@ -40,7 +39,7 @@
BuildRequires: %{python_module flaky}
BuildRequires: %{python_module ipykernel >= 6.9.2 with %python-ipykernel < 7}
BuildRequires: %{python_module ipython >= 7.31.1}
-BuildRequires: %{python_module jupyter_client >= 7.3.1 with
%python-jupyter_client < 8}
+BuildRequires: %{python_module jupyter_client >= 7.3.4 with
%python-jupyter_client < 8}
BuildRequires: %{python_module matplotlib}
BuildRequires: %{python_module numpy}
BuildRequires: %{python_module pandas}
@@ -58,7 +57,7 @@
Requires: python-pyzmq >= 22.1
Requires: python-wurlitzer >= 1.0.3
Requires: (python-ipykernel >= 6.9.2 with python-ipykernel < 7)
-Requires: (python-jupyter_client >= 7.3.1 with python-jupyter_client < 8)
+Requires: (python-jupyter_client >= 7.3.4 with python-jupyter_client < 8)
BuildArch: noarch
%python_subpackages
++++++ python-spyder-kernels-2.3.1.tar.gz -> python-spyder-kernels-2.3.2.tar.gz
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/spyder-kernels-2.3.1/CHANGELOG.md
new/spyder-kernels-2.3.2/CHANGELOG.md
--- old/spyder-kernels-2.3.1/CHANGELOG.md 2022-05-21 18:36:00.000000000
+0200
+++ new/spyder-kernels-2.3.2/CHANGELOG.md 2022-07-06 18:22:03.000000000
+0200
@@ -1,5 +1,30 @@
# History of changes
+## Version 2.3.2 (2022-07-06)
+
+### Issues Closed
+
+* [Issue 394](https://github.com/spyder-ide/spyder-kernels/issues/394) - The
variable explorer is broken while debugging ([PR
395](https://github.com/spyder-ide/spyder-kernels/pull/395) by
[@impact27](https://github.com/impact27))
+
+In this release 1 issue was closed.
+
+### Pull Requests Merged
+
+* [PR 399](https://github.com/spyder-ide/spyder-kernels/pull/399) - PR:
Increase minimal required version of jupyter_client to 7.3.4, by
[@ccordoba12](https://github.com/ccordoba12)
+* [PR 398](https://github.com/spyder-ide/spyder-kernels/pull/398) - PR: Fix
module namespace, by [@impact27](https://github.com/impact27)
+* [PR 395](https://github.com/spyder-ide/spyder-kernels/pull/395) - PR: Fix
running namespace and improve eventloop integration while debugging, by
[@impact27](https://github.com/impact27)
([394](https://github.com/spyder-ide/spyder-kernels/issues/394))
+* [PR 389](https://github.com/spyder-ide/spyder-kernels/pull/389) - PR: Fix
debug filename path for remote debugging, by
[@impact27](https://github.com/impact27)
([18330](https://github.com/spyder-ide/spyder/issues/18330))
+* [PR 388](https://github.com/spyder-ide/spyder-kernels/pull/388) - PR: Fix
getting args from functions or methods, by
[@ccordoba12](https://github.com/ccordoba12)
+* [PR 386](https://github.com/spyder-ide/spyder-kernels/pull/386) - PR: Fix
flaky test, by [@impact27](https://github.com/impact27)
+* [PR 381](https://github.com/spyder-ide/spyder-kernels/pull/381) - PR:
Eliminate unnecessary updates of the Variable Explorer while debugging, by
[@rear1019](https://github.com/rear1019)
+* [PR 378](https://github.com/spyder-ide/spyder-kernels/pull/378) - PR: Append
paths that come from Spyder's Python path manager to the end of `sys.path`, by
[@mrclary](https://github.com/mrclary)
+
+In this release 8 pull requests were closed.
+
+
+----
+
+
## Version 2.3.1 (2022-05-21)
### Pull Requests Merged
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/spyder-kernels-2.3.1/requirements/posix.txt
new/spyder-kernels-2.3.2/requirements/posix.txt
--- old/spyder-kernels-2.3.1/requirements/posix.txt 2022-05-21
18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/requirements/posix.txt 2022-07-06
18:22:03.000000000 +0200
@@ -1,6 +1,6 @@
cloudpickle
ipykernel>=6.9.2,<7
ipython>=7.31.1,<8
-jupyter_client>=7.3.1,<8
+jupyter_client>=7.3.4,<8
pyzmq>=22.1.0
wurlitzer>=1.0.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/spyder-kernels-2.3.1/requirements/windows.txt
new/spyder-kernels-2.3.2/requirements/windows.txt
--- old/spyder-kernels-2.3.1/requirements/windows.txt 2022-05-21
18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/requirements/windows.txt 2022-07-06
18:22:03.000000000 +0200
@@ -1,5 +1,5 @@
cloudpickle
ipykernel>=6.9.2,<7
ipython>=7.31.1,<8
-jupyter_client>=7.3.1,<8
+jupyter_client>=7.3.4,<8
pyzmq>=22.1.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/spyder-kernels-2.3.1/setup.py
new/spyder-kernels-2.3.2/setup.py
--- old/spyder-kernels-2.3.1/setup.py 2022-05-21 18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/setup.py 2022-07-06 18:22:03.000000000 +0200
@@ -44,7 +44,7 @@
'ipython<6; python_version<"3"',
'ipython>=7.31.1,<8; python_version>="3"',
'jupyter-client>=5.3.4,<6; python_version<"3"',
- 'jupyter-client>=7.3.1,<8; python_version>="3"',
+ 'jupyter-client>=7.3.4,<8; python_version>="3"',
'pyzmq>=17,<20; python_version<"3"',
'pyzmq>=22.1.0; python_version>="3"',
'wurlitzer>=1.0.3;platform_system!="Windows"',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/spyder-kernels-2.3.1/spyder_kernels/_version.py
new/spyder-kernels-2.3.2/spyder_kernels/_version.py
--- old/spyder-kernels-2.3.1/spyder_kernels/_version.py 2022-05-21
18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/spyder_kernels/_version.py 2022-07-06
18:22:03.000000000 +0200
@@ -8,5 +8,5 @@
"""Version File."""
-VERSION_INFO = (2, 3, 1)
+VERSION_INFO = (2, 3, 2)
__version__ = '.'.join(map(str, VERSION_INFO))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder-kernels-2.3.1/spyder_kernels/console/kernel.py
new/spyder-kernels-2.3.2/spyder_kernels/console/kernel.py
--- old/spyder-kernels-2.3.1/spyder_kernels/console/kernel.py 2022-05-21
18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/spyder_kernels/console/kernel.py 2022-07-06
18:22:03.000000000 +0200
@@ -24,8 +24,8 @@
# Local imports
from spyder_kernels.py3compat import (
- TEXT_TYPES, to_text_string, PY3, input, TimeoutError)
-from spyder_kernels.comms.frontendcomm import FrontendComm, CommError
+ TEXT_TYPES, to_text_string, PY3)
+from spyder_kernels.comms.frontendcomm import FrontendComm
from spyder_kernels.utils.iofuncs import iofunctions
from spyder_kernels.utils.mpl import (
MPL_BACKENDS_FROM_SPYDER, MPL_BACKENDS_TO_SPYDER, INLINE_FIGURE_FORMATS)
@@ -96,7 +96,6 @@
self.namespace_view_settings = {}
self._mpl_backend_error = None
self._running_namespace = None
- self._pdb_input_line = None
self.faulthandler_handle = None
# -- Public API -----------------------------------------------------------
@@ -306,21 +305,6 @@
return self.shell.pdb_session.do_complete(code, cursor_pos)
return self._do_complete(code, cursor_pos)
- def publish_pdb_state(self, step):
- """
- Publish Variable Explorer state and Pdb step through
- send_spyder_msg.
- """
- state = dict(
- namespace_view=self.get_namespace_view(),
- var_properties=self.get_var_properties(),
- step=step
- )
- try:
- self.frontend_call(blocking=False).pdb_state(state)
- except (CommError, TimeoutError):
- logger.debug("Could not send Pdb state to the frontend.")
-
def set_spyder_breakpoints(self, breakpoints):
"""
Handle a message from the frontend
@@ -352,10 +336,10 @@
def pdb_input_reply(self, line, echo_stack_entry=True):
"""Get a pdb command from the frontend."""
- if self.shell.pdb_session:
- self.shell.pdb_session._disable_next_stack_entry = (
- not echo_stack_entry)
- self._pdb_input_line = line
+ debugger = self.shell.pdb_session
+ if debugger:
+ debugger._disable_next_stack_entry = not echo_stack_entry
+ debugger._cmd_input_line = line
if self.eventloop:
# Interrupting the eventloop is only implemented when a message is
# received on the shell channel, but this message is queued and
@@ -365,47 +349,6 @@
# stop the eventloop. This will call back `_interrupt_eventloop`.
self.frontend_call().request_interrupt_eventloop()
- def cmd_input(self, prompt=''):
- """
- Special input function for commands.
- Runs the eventloop while debugging.
- """
- # Only works if the comm is open and this is a pdb prompt.
- if not self.frontend_comm.is_open() or not self.shell.is_debugging():
- return input(prompt)
-
- # Flush output before making the request.
- sys.stderr.flush()
- sys.stdout.flush()
-
- # Send the input request.
- self._pdb_input_line = None
- self.frontend_call().pdb_input(prompt)
-
- # Allow GUI event loop to update
- if PY3:
- is_main_thread = (
- threading.current_thread() is threading.main_thread())
- else:
- is_main_thread = isinstance(
- threading.current_thread(), threading._MainThread)
-
- # Get input by running eventloop
- if is_main_thread and self.eventloop:
- while self._pdb_input_line is None:
- eventloop = self.eventloop
- if eventloop:
- eventloop(self)
- else:
- break
-
- # Get input by blocking
- if self._pdb_input_line is None:
- self.frontend_comm.wait_until(
- lambda: self._pdb_input_line is not None)
-
- return self._pdb_input_line
-
def _interrupt_eventloop(self):
"""Interrupts the eventloop."""
# Receiving the request is enough to stop the eventloop.
@@ -634,11 +577,12 @@
sys.path.remove(path)
# Add new paths
- # We do this in reverse order as we use `sys.path.insert(1, path)`.
- # This ensures the end result has the correct path order.
- for path, active in reversed(new_path_dict.items()):
- if active:
- sys.path.insert(1, path)
+ pypath = [path for path, active in new_path_dict.items() if active]
+ if pypath:
+ sys.path.extend(pypath)
+ os.environ.update({'PYTHONPATH': os.pathsep.join(pypath)})
+ else:
+ os.environ.pop('PYTHONPATH', None)
# -- Private API ---------------------------------------------------
# --- For the Variable Explorer
@@ -650,17 +594,21 @@
both locals() and globals() for current frame when debugging
"""
ns = {}
- if self._running_namespace is None:
+ if self.shell.is_debugging() and self.shell.pdb_session.prompt_waiting:
+ # Stopped at a pdb prompt
ns.update(self.shell.user_ns)
+ ns.update(self.shell._pdb_locals)
else:
- # This is true when a file is executing.
- running_globals, running_locals = self._running_namespace
- ns.update(running_globals)
- if running_locals is not None:
- ns.update(running_locals)
+ # Give access to the running namespace if there is one
+ if self._running_namespace is None:
+ ns.update(self.shell.user_ns)
+ else:
+ # This is true when a file is executing.
+ running_globals, running_locals = self._running_namespace
+ ns.update(running_globals)
+ if running_locals is not None:
+ ns.update(running_locals)
- # Add debugging locals
- ns.update(self.shell._pdb_locals)
# Add magics to ns so we can show help about them on the Help
# plugin
if with_magics:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder-kernels-2.3.1/spyder_kernels/console/tests/test_console_kernel.py
new/spyder-kernels-2.3.2/spyder_kernels/console/tests/test_console_kernel.py
---
old/spyder-kernels-2.3.1/spyder_kernels/console/tests/test_console_kernel.py
2022-05-21 18:36:00.000000000 +0200
+++
new/spyder-kernels-2.3.2/spyder_kernels/console/tests/test_console_kernel.py
2022-07-06 18:22:03.000000000 +0200
@@ -831,6 +831,7 @@
# test pdb
pdb_obj = SpyderPdb()
pdb_obj.curframe = inspect.currentframe()
+ pdb_obj.prompt_waiting = True
pdb_obj.completenames = lambda *ignore: ['baba']
kernel.shell.pdb_session = pdb_obj
match = kernel.do_complete('ba', 2)
@@ -889,6 +890,7 @@
"""
pdb_obj = SpyderPdb()
pdb_obj.curframe = inspect.currentframe()
+ pdb_obj.prompt_waiting = True
pdb_obj.curframe_locals = pdb_obj.curframe.f_locals
kernel.shell.pdb_session = pdb_obj
@@ -915,6 +917,7 @@
"""
pdb_obj = SpyderPdb()
pdb_obj.curframe = inspect.currentframe()
+ pdb_obj.prompt_waiting = True
pdb_obj.curframe_locals = pdb_obj.curframe.f_locals
kernel.shell.pdb_session = pdb_obj
@@ -941,6 +944,7 @@
kernel.shell.user_ns["test"] = 0
pdb_obj = SpyderPdb()
pdb_obj.curframe = inspect.currentframe()
+ pdb_obj.prompt_waiting = True
pdb_obj.curframe_locals = pdb_obj.curframe.f_locals
kernel.shell.pdb_session = pdb_obj
@@ -1022,6 +1026,7 @@
baba = 1
pdb_obj = SpyderPdb()
pdb_obj.curframe = inspect.currentframe()
+ pdb_obj.prompt_waiting = True
pdb_obj.curframe_locals = pdb_obj.curframe.f_locals
kernel.shell.pdb_session = pdb_obj
@@ -1059,6 +1064,7 @@
a = 1
pdb_obj = SpyderPdb()
pdb_obj.curframe = inspect.currentframe()
+ pdb_obj.prompt_waiting = True
pdb_obj.curframe_locals = pdb_obj.curframe.f_locals
kernel.shell.pdb_session = pdb_obj
@@ -1116,6 +1122,8 @@
if backend is not None:
client.execute("%matplotlib {}".format(backend))
client.get_shell_msg(timeout=TIMEOUT)
+ client.execute("import time; time.sleep(.1)")
+ client.get_shell_msg(timeout=TIMEOUT)
# Get backend
code = "backend = get_ipython().kernel.get_mpl_interactive_backend()"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder-kernels-2.3.1/spyder_kernels/customize/namespace_manager.py
new/spyder-kernels-2.3.2/spyder_kernels/customize/namespace_manager.py
--- old/spyder-kernels-2.3.1/spyder_kernels/customize/namespace_manager.py
2022-05-21 18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/spyder_kernels/customize/namespace_manager.py
2022-07-06 18:22:03.000000000 +0200
@@ -6,6 +6,7 @@
import linecache
import os.path
+import types
import sys
from IPython.core.getipython import get_ipython
@@ -13,6 +14,25 @@
from spyder_kernels.py3compat import PY2
+def new_main_mod(filename, modname):
+ """
+ Reimplemented from IPython/core/interactiveshell.py to avoid caching
+ and clearing recursive namespace.
+ """
+ filename = os.path.abspath(filename)
+
+ main_mod = types.ModuleType(
+ modname,
+ doc="Module created for script run in IPython")
+
+ 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
+
+
class NamespaceManager(object):
"""
Get a namespace and set __file__ to filename for this namespace.
@@ -29,6 +49,7 @@
self.current_namespace = current_namespace
self._previous_filename = None
self._previous_main = None
+ self._previous_running_namespace = None
self._reset_main = False
self._file_code = file_code
ipython_shell = get_ipython()
@@ -49,9 +70,7 @@
self._previous_filename = self.ns_globals['__file__']
self.ns_globals['__file__'] = self.filename
else:
-
- main_mod = ipython_shell.new_main_mod(
- self.filename, '__main__')
+ main_mod = new_main_mod(self.filename, '__main__')
self.ns_globals = main_mod.__dict__
self.ns_locals = None
# Needed to allow pickle to reference main
@@ -61,6 +80,8 @@
self._reset_main = True
# Save current namespace for access by variable explorer
+ self._previous_running_namespace = (
+ ipython_shell.kernel._running_namespace)
ipython_shell.kernel._running_namespace = (
self.ns_globals, self.ns_locals)
@@ -86,7 +107,8 @@
Reset the namespace.
"""
ipython_shell = get_ipython()
- ipython_shell.kernel._running_namespace = None
+ ipython_shell.kernel._running_namespace = (
+ self._previous_running_namespace)
if self._previous_filename:
self.ns_globals['__file__'] = self._previous_filename
elif '__file__' in self.ns_globals:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder-kernels-2.3.1/spyder_kernels/customize/spydercustomize.py
new/spyder-kernels-2.3.2/spyder_kernels/customize/spydercustomize.py
--- old/spyder-kernels-2.3.1/spyder_kernels/customize/spydercustomize.py
2022-05-21 18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/spyder_kernels/customize/spydercustomize.py
2022-07-06 18:22:03.000000000 +0200
@@ -13,7 +13,6 @@
import ast
import bdb
-import cmd
import io
import logging
import os
@@ -23,17 +22,15 @@
import time
import warnings
-from IPython import __version__ as ipy_version
from IPython.core.getipython import get_ipython
-from spyder_kernels.comms.frontendcomm import CommError, frontend_request
+from spyder_kernels.comms.frontendcomm import frontend_request
from spyder_kernels.customize.namespace_manager import NamespaceManager
from spyder_kernels.customize.spyderpdb import SpyderPdb, get_new_debugger
from spyder_kernels.customize.umr import UserModuleReloader
from spyder_kernels.py3compat import (
- TimeoutError, PY2, _print, encode, compat_exec, FileNotFoundError)
-from spyder_kernels.customize.utils import (
- capture_last_Expr, normalise_filename)
+ PY2, _print, encode, compat_exec, FileNotFoundError)
+from spyder_kernels.customize.utils import capture_last_Expr, canonic
if not PY2:
from IPython.core.inputtransformer2 import (
@@ -330,18 +327,8 @@
# =============================================================================
# Pdb adjustments
# =============================================================================
-def cmd_input(prompt=''):
- return get_ipython().kernel.cmd_input(prompt)
-
-
pdb.Pdb = SpyderPdb
-if PY2:
- cmd.raw_input = cmd_input
-else:
- cmd.input = cmd_input
-
-
# =============================================================================
# User module reloader
# =============================================================================
@@ -505,18 +492,23 @@
__tracebackhide__ = "__pdb_exit__"
-def get_file_code(filename, save_all=True):
- """Retrive the content of a file."""
+def get_file_code(filename, save_all=True, raise_exception=False):
+ """Retrieve the content of a file."""
# Get code from spyder
try:
- file_code = frontend_request(blocking=True).get_file_code(
+ return frontend_request(blocking=True).get_file_code(
filename, save_all=save_all)
- except (CommError, TimeoutError, RuntimeError, FileNotFoundError):
- file_code = None
- if file_code is None:
- with open(filename, 'r') as f:
- return f.read()
- return file_code
+ except Exception:
+ # Maybe this is a local file
+ try:
+ with open(filename, 'r') as f:
+ return f.read()
+ except FileNotFoundError:
+ pass
+ if raise_exception:
+ raise
+ # Else return None
+ return None
def runfile(filename=None, args=None, wdir=None, namespace=None,
@@ -536,7 +528,7 @@
def _exec_file(filename=None, args=None, wdir=None, namespace=None,
post_mortem=False, current_namespace=False, stack_depth=0,
- exec_fun=None):
+ exec_fun=None, canonic_filename=None):
# Tell IPython to hide this frame (>7.16)
__tracebackhide__ = True
ipython_shell = get_ipython()
@@ -544,11 +536,6 @@
filename = get_current_file_name()
if filename is None:
return
- else:
- # get_debugger replaces \\ by / so we must undo that here
- # Otherwise code caching doesn't work
- if os.name == 'nt':
- filename = filename.replace('/', '\\')
try:
filename = filename.decode('utf-8')
@@ -562,22 +549,23 @@
__umr__.run()
if args is not None and not isinstance(args, basestring):
raise TypeError("expected a character buffer object")
+
try:
- file_code = get_file_code(filename)
+ file_code = get_file_code(filename, raise_exception=True)
except Exception:
+ # Show an error and return None
_print(
"This command failed to be executed because an error occurred"
" while trying to get the file code from Spyder's"
" editor. The error was:\n\n")
get_ipython().showtraceback(exception_only=True)
return
- if file_code is None:
- _print("Could not get code from editor.\n")
- return
- # Normalise the filename
- filename = os.path.abspath(filename)
- filename = os.path.normcase(filename)
+ # Here the remote filename has been used. It must now be valid locally.
+ if canonic_filename is not None:
+ filename = canonic_filename
+ else:
+ filename = canonic(filename)
with NamespaceManager(filename, namespace, current_namespace,
file_code=file_code, stack_depth=stack_depth + 1
@@ -655,7 +643,7 @@
if shell.is_debugging():
# Recursive
code = (
- "runfile({}".format(repr(normalise_filename(filename))) +
+ "runfile({}".format(repr(filename)) +
", args=%r, wdir=%r, current_namespace=%r)" % (
args, wdir, current_namespace)
)
@@ -666,11 +654,13 @@
else:
debugger = get_new_debugger(filename, True)
_exec_file(
- filename=debugger.canonic(filename),
- args=args, wdir=wdir,
+ filename=filename,
+ canonic_filename=debugger.canonic(filename),
+ args=args,
+ wdir=wdir,
current_namespace=current_namespace,
exec_fun=debugger.run,
- stack_depth=1
+ stack_depth=1,
)
@@ -696,7 +686,7 @@
def _exec_cell(cellname, filename=None, post_mortem=False, stack_depth=0,
- exec_fun=None):
+ exec_fun=None, canonic_filename=None):
"""
Execute a code cell with a given exec function.
"""
@@ -706,11 +696,6 @@
filename = get_current_file_name()
if filename is None:
return
- else:
- # get_debugger replaces \\ by / so we must undo that here
- # Otherwise code caching doesn't work
- if os.name == 'nt':
- filename = filename.replace('/', '\\')
try:
filename = filename.decode('utf-8')
except (UnicodeError, TypeError, AttributeError):
@@ -736,14 +721,14 @@
# Trigger `post_execute` to exit the additional pre-execution.
# See Spyder PR #7310.
ipython_shell.events.trigger('post_execute')
- try:
- file_code = get_file_code(filename, save_all=False)
- except Exception:
- file_code = None
+ file_code = get_file_code(filename, save_all=False)
- # Normalise the filename
- filename = os.path.abspath(filename)
- filename = os.path.normcase(filename)
+ # Here the remote filename has been used. It must now be valid locally.
+ if canonic_filename is not None:
+ filename = canonic_filename
+ else:
+ # Normalise the filename
+ filename = canonic(filename)
with NamespaceManager(filename, current_namespace=True,
file_code=file_code, stack_depth=stack_depth + 1
@@ -770,7 +755,7 @@
# Recursive
code = (
"runcell({}, ".format(repr(cellname)) +
- "{})".format(repr(normalise_filename(filename)))
+ "{})".format(repr(filename))
)
shell.pdb_session.enter_recursive_debugger(
code, filename, False,
@@ -779,7 +764,8 @@
debugger = get_new_debugger(filename, False)
_exec_cell(
cellname=cellname,
- filename=debugger.canonic(filename),
+ filename=filename,
+ canonic_filename=debugger.canonic(filename),
exec_fun=debugger.run,
stack_depth=1
)
@@ -814,12 +800,15 @@
# =============================================================================
-# Extend sys.path with paths that come from Spyder
+# PYTHONPATH and sys.path Adjustments
# =============================================================================
+# PYTHONPATH is not passed to kernel directly, see spyder-ide/spyder#13519
+# This allows the kernel to start without crashing if modules in PYTHONPATH
+# shadow standard library modules.
def set_spyder_pythonpath():
pypath = os.environ.get('SPY_PYTHONPATH')
if pypath:
- pathlist = pypath.split(os.pathsep)
- sys.path.extend(pathlist)
+ sys.path.extend(pypath.split(os.pathsep))
+ os.environ.update({'PYTHONPATH': pypath})
set_spyder_pythonpath()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder-kernels-2.3.1/spyder_kernels/customize/spyderpdb.py
new/spyder-kernels-2.3.2/spyder_kernels/customize/spyderpdb.py
--- old/spyder-kernels-2.3.1/spyder_kernels/customize/spyderpdb.py
2022-05-21 18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/spyder_kernels/customize/spyderpdb.py
2022-07-06 18:22:03.000000000 +0200
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
#
# Copyright (c) 2009- Spyder Kernels Contributors
#
@@ -9,9 +10,9 @@
import ast
import bdb
import logging
-import os
import sys
import traceback
+import threading
from collections import namedtuple
from IPython.core.autocall import ZMQExitAutocall
@@ -20,7 +21,8 @@
from spyder_kernels.comms.frontendcomm import CommError, frontend_request
from spyder_kernels.customize.utils import path_is_library, capture_last_Expr
-from spyder_kernels.py3compat import TimeoutError, PY2, _print, isidentifier
+from spyder_kernels.py3compat import (
+ TimeoutError, PY2, _print, isidentifier, PY3, input)
if not PY2:
from IPython.core.inputtransformer2 import TransformerManager
@@ -92,10 +94,23 @@
self._pdb_breaking = False
self._frontend_notified = False
+ # content of tuple: (filename, line number)
+ self._previous_step = None
+
# Don't report hidden frames for IPython 7.24+. This attribute
# has no effect in previous versions.
self.report_skipped = False
+
+ # Keep track of remote filename
+ self.remote_filename = None
+
+ # State of the prompt
+ self.prompt_waiting = False
+
+ # Line received from the frontend
+ self._cmd_input_line = None
+
# --- Methods overriden for code execution
def print_exclamation_warning(self):
"""Print pdb warning for exclamation mark."""
@@ -107,10 +122,6 @@
def default(self, line):
"""
Default way of running pdb statment.
-
- The only difference with Pdb.default is that if line contains multiple
- statments, the code will be compiled with 'exec'. It will not print the
- result but will run without failing.
"""
execute_events = self.pdb_execute_events
if line[:1] == '!':
@@ -542,6 +553,12 @@
return result
# --- Methods overriden by us for Spyder integration
+ def postloop(self):
+ # postloop() is called when the debugger???s input prompt exists. Reset
+ # _previous_step so that publish_pdb_state() actually notifies Spyder
+ # about a changed frame the next the input prompt is entered again.
+ self._previous_step = None
+
def preloop(self):
"""Ask Spyder for breakpoints before the first prompt is created."""
try:
@@ -554,7 +571,7 @@
if self.starting:
self.set_spyder_breakpoints(pdb_settings['breakpoints'])
if self.send_initial_notification:
- self.notify_spyder()
+ self.publish_pdb_state()
except (CommError, TimeoutError):
logger.debug("Could not get breakpoints from the frontend.")
super(SpyderPdb, self).preloop()
@@ -625,6 +642,75 @@
"For copying text while debugging, use Ctrl+Shift+C",
file=self.stdout)
+
+ def cmdloop(self, intro=None):
+ """
+ Repeatedly issue a prompt, accept input, parse an initial prefix
+ off the received input, and dispatch to action methods, passing them
+ the remainder of the line as argument.
+ """
+ self.preloop()
+ if intro is not None:
+ self.intro = intro
+ if self.intro:
+ self.stdout.write(str(self.intro)+"\n")
+ stop = None
+ while not stop:
+ if self.cmdqueue:
+ line = self.cmdqueue.pop(0)
+ else:
+ try:
+ self.prompt_waiting = True
+ line = self.cmd_input(self.prompt)
+ except EOFError:
+ line = 'EOF'
+ self.prompt_waiting = False
+ line = self.precmd(line)
+ stop = self.onecmd(line)
+ stop = self.postcmd(stop, line)
+ self.postloop()
+
+ def cmd_input(self, prompt=''):
+ """
+ Get input from frontend. Blocks until return
+ """
+ kernel = get_ipython().kernel
+ # Only works if the comm is open
+ if not kernel.frontend_comm.is_open():
+ return input(prompt)
+
+ # Flush output before making the request.
+ sys.stderr.flush()
+ sys.stdout.flush()
+
+ # Send the input request.
+ self._cmd_input_line = None
+ kernel.frontend_call().pdb_input(prompt)
+
+ # Allow GUI event loop to update
+ if PY3:
+ is_main_thread = (
+ threading.current_thread() is threading.main_thread())
+ else:
+ is_main_thread = isinstance(
+ threading.current_thread(), threading._MainThread)
+
+ # Get input by running eventloop
+ if is_main_thread and kernel.eventloop:
+ while self._cmd_input_line is None:
+ eventloop = kernel.eventloop
+ if eventloop:
+ eventloop(kernel)
+ else:
+ break
+
+ # Get input by blocking
+ if self._cmd_input_line is None:
+ kernel.frontend_comm.wait_until(
+ lambda: self._cmd_input_line is not None)
+
+ return self._cmd_input_line
+
def precmd(self, line):
"""
Hook method executed just before the command line is
@@ -644,9 +730,11 @@
def postcmd(self, stop, line):
"""
- Notify spyder on any pdb command.
+ Notify spyder about (possibly) changed frame
+
+ Note: The PDB commands ???up???, ???down??? and ???jump??? change the
current frame.
"""
- self.notify_spyder()
+ self.publish_pdb_state()
return super(SpyderPdb, self).postcmd(stop, line)
if PY2:
@@ -743,11 +831,16 @@
logger.debug(
"Could not send a Pdb continue call to the frontend.")
- def notify_spyder(self):
- """Send kernel state to the frontend."""
+ def publish_pdb_state(self):
+ """
+ Send debugger state (frame position) to the frontend.
+
+ The state is only sent if it has changed since the last update.
+ """
frame = self.curframe
if frame is None:
+ self._previous_step = None
return
# Get filename and line number of the current frame
@@ -757,14 +850,24 @@
fname = unicode(fname, "utf-8")
except TypeError:
pass
+ if fname == self.mainpyfile and self.remote_filename is not None:
+ fname = self.remote_filename
lineno = frame.f_lineno
+ if self._previous_step == (fname, lineno):
+ return
+
# Set step of the current frame (if any)
step = {}
+ self._previous_step = None
if isinstance(fname, basestring) and isinstance(lineno, int):
step = dict(fname=fname, lineno=lineno)
+ self._previous_step = (fname, lineno)
- get_ipython().kernel.publish_pdb_state(step)
+ try:
+ frontend_request(blocking=False).pdb_state(dict(step=step))
+ except (CommError, TimeoutError):
+ logger.debug("Could not send Pdb state to the frontend.")
def run(self, cmd, globals=None, locals=None):
"""Debug a statement executed via the exec() function.
@@ -808,11 +911,8 @@
debugger.use_rawinput = self.use_rawinput
debugger.prompt = "(%s) " % self.prompt.strip()
- filename = debugger.canonic(filename)
- debugger._wait_for_mainpyfile = True
- debugger.mainpyfile = filename
+ debugger.set_remote_filename(filename)
debugger.continue_if_has_breakpoints = continue_if_has_breakpoints
- debugger._user_requested_quit = False
# Enter recursive debugger
sys.call_tracing(debugger.run, (code, globals, locals))
@@ -821,14 +921,22 @@
self.lastcmd = debugger.lastcmd
get_ipython().pdb_session = self
+ # Reset _previous_step so that publish_pdb_state() called from within
+ # postcmd() notifies Spyder about a changed debugger position. The
reset
+ # is required because the recursive debugger might change the position,
+ # but the parent debugger (self) is not aware of this.
+ self._previous_step = None
+
+ def set_remote_filename(self, filename):
+ """Set remote filename to signal Spyder on mainpyfile."""
+ self.remote_filename = filename
+ self.mainpyfile = self.canonic(filename)
+ self._wait_for_mainpyfile = True
+
def get_new_debugger(filename, continue_if_has_breakpoints):
"""Get a new debugger."""
debugger = SpyderPdb()
-
- filename = debugger.canonic(filename)
- debugger._wait_for_mainpyfile = True
- debugger.mainpyfile = filename
+ debugger.set_remote_filename(filename)
debugger.continue_if_has_breakpoints = continue_if_has_breakpoints
- debugger._user_requested_quit = False
return debugger
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder-kernels-2.3.1/spyder_kernels/customize/utils.py
new/spyder-kernels-2.3.2/spyder_kernels/customize/utils.py
--- old/spyder-kernels-2.3.1/spyder_kernels/customize/utils.py 2022-05-21
18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/spyder_kernels/customize/utils.py 2022-07-06
18:22:03.000000000 +0200
@@ -117,9 +117,15 @@
return code_ast, capture_last_expression
-def normalise_filename(filename):
- """Normalise path for window."""
- # Recursive
- if os.name == 'nt':
- return filename.replace('\\', '/')
- return filename
+def canonic(filename):
+ """
+ Return canonical form of filename.
+
+ This is a copy of bdb.canonic, so that the debugger will process
+ filenames in the same way
+ """
+ if filename == "<" + filename[1:-1] + ">":
+ return filename
+ canonic = os.path.abspath(filename)
+ canonic = os.path.normcase(canonic)
+ return canonic
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder-kernels-2.3.1/spyder_kernels/utils/dochelpers.py
new/spyder-kernels-2.3.2/spyder_kernels/utils/dochelpers.py
--- old/spyder-kernels-2.3.1/spyder_kernels/utils/dochelpers.py 2022-05-21
18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/spyder_kernels/utils/dochelpers.py 2022-07-06
18:22:03.000000000 +0200
@@ -238,7 +238,8 @@
func_obj = getattr(obj, '__init__')
else:
return []
- if not hasattr(func_obj, 'func_code'):
+
+ if not hasattr(func_obj, '__code__'):
# Builtin: try to extract info from doc
args = getargsfromdoc(func_obj)
if args is not None:
@@ -246,24 +247,29 @@
else:
# Example: PyQt5
return getargsfromdoc(obj)
- args, _, _ = inspect.getargs(func_obj.func_code)
+
+ args, _, _ = inspect.getargs(func_obj.__code__)
if not args:
return getargsfromdoc(obj)
-
+
# Supporting tuple arguments in def statement:
for i_arg, arg in enumerate(args):
if isinstance(arg, list):
args[i_arg] = "(%s)" % ", ".join(arg)
-
+
defaults = get_func_defaults(func_obj)
if defaults is not None:
for index, default in enumerate(defaults):
- args[index+len(args)-len(defaults)] += '='+repr(default)
+ args[index + len(args) - len(defaults)] += '=' + repr(default)
+
if inspect.isclass(obj) or inspect.ismethod(obj):
if len(args) == 1:
return None
- if 'self' in args:
- args.remove('self')
+
+ # Remove 'self' from args
+ if 'self' in args:
+ args.remove('self')
+
return args
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder-kernels-2.3.1/spyder_kernels/utils/tests/test_dochelpers.py
new/spyder-kernels-2.3.2/spyder_kernels/utils/tests/test_dochelpers.py
--- old/spyder-kernels-2.3.1/spyder_kernels/utils/tests/test_dochelpers.py
2022-05-21 18:36:00.000000000 +0200
+++ new/spyder-kernels-2.3.2/spyder_kernels/utils/tests/test_dochelpers.py
2022-07-06 18:22:03.000000000 +0200
@@ -9,9 +9,9 @@
"""
Tests for dochelpers.py
"""
+
# Standard library imports
import os
-import sys
# Test library imports
import pytest
@@ -27,57 +27,29 @@
pass
[email protected](not PY2, reason="It fails in Python 3")
[email protected](PY2 or os.name == 'nt',
+ reason="Only works on Linux and Mac")
def test_dochelpers():
"""Test dochelpers."""
+ assert getargtxt(Test.method) == ['x, ', 'y=2']
assert not getargtxt(Test.__init__)
- if PY2:
- assert getargtxt(Test.method) == ['x, ', 'y=2']
- assert getdoc(sorted) == {'note': 'Function of __builtin__ module',
- 'argspec': u'(iterable, cmp=None, key=None, '
- 'reverse=False)',
- 'docstring': u'sorted(iterable, cmp=None, '
- 'key=None, reverse=False) --> '
- 'new sorted list',
- 'name': 'sorted'}
- assert getargtxt(sorted) == ['iterable, ', ' cmp=None, ',
- ' key=None, ', ' reverse=False']
- else:
- assert not getargtxt(Test.method)
- if os.name == 'nt':
- assert getdoc(sorted) == {'note': 'Function of builtins module',
- 'argspec': '(...)',
- 'docstring': 'Return a new list '
- 'containing '
- 'all items from the '
- 'iterable in ascending '
- 'order.\n\nA custom '
- 'key function can be '
- 'supplied to customise the '
- 'sort order, and '
- 'the\nreverse flag can be '
- 'set to request the result '
- 'in descending order.',
- 'name': 'sorted'}
- else:
- assert getdoc(sorted) == {'note': 'Function of builtins module',
- 'argspec': '(...)',
- 'docstring': 'Return a new list '
- 'containing '
- 'all items from the '
- 'iterable in ascending '
- 'order.\n\nA custom '
- 'key function can be '
- 'supplied to customize the '
- 'sort order, and '
- 'the\nreverse flag can be '
- 'set to request the result '
- 'in descending order.',
- 'name': 'sorted'}
- assert not getargtxt(sorted)
+
+ assert getdoc(sorted) == {
+ 'note': 'Function of builtins module',
+ 'argspec': '(...)',
+ 'docstring': 'Return a new list containing all items from the '
+ 'iterable in ascending order.\n\nA custom key function '
+ 'can be supplied to customize the sort order, and the\n'
+ 'reverse flag can be set to request the result in '
+ 'descending order.',
+ 'name': 'sorted'
+ }
+ assert not getargtxt(sorted)
+
assert isdefined('numpy.take', force_import=True)
assert isdefined('__import__')
- assert not isdefined('.keys', force_import=True)
+ assert not isdefined('zzz', force_import=True)
+
assert getobj('globals') == 'globals'
assert not getobj('globals().keys')
assert getobj('+scipy.signal.') == 'scipy.signal'