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 2021-08-06 22:44:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-spyder-kernels (Old)
 and      /work/SRC/openSUSE:Factory/.python-spyder-kernels.new.1899 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-spyder-kernels"

Fri Aug  6 22:44:47 2021 rev:26 rq:910383 version:2.1.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-spyder-kernels/python-spyder-kernels.changes  
    2021-06-14 23:11:55.472841415 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-spyder-kernels.new.1899/python-spyder-kernels.changes
    2021-08-06 22:45:25.966001207 +0200
@@ -1,0 +2,8 @@
+Thu Aug  5 20:11:03 UTC 2021 - Ben Greiner <c...@bnavigator.de>
+
+- Update to version 2.1.0
+  * Add support for the Rich and Colorama libraries.
+  * Load big modules (e.g. Numpy, Pandas and Scipy) only until it's
+    really necessary.
+
+-------------------------------------------------------------------

Old:
----
  python-spyder-kernels-2.0.4.tar.gz

New:
----
  python-spyder-kernels-2.1.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-spyder-kernels.spec ++++++
--- /var/tmp/diff_new_pack.mI5n7m/_old  2021-08-06 22:45:26.398000441 +0200
+++ /var/tmp/diff_new_pack.mI5n7m/_new  2021-08-06 22:45:26.410000419 +0200
@@ -20,7 +20,7 @@
 %define skip_python2 1
 %define skip_python36 1
 Name:           python-spyder-kernels
-Version:        2.0.4
+Version:        2.1.0
 Release:        0
 Summary:        Jupyter kernels for Spyder's console
 License:        MIT

++++++ python-spyder-kernels-2.0.4.tar.gz -> python-spyder-kernels-2.1.0.tar.gz 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/.github/workflows/linux-pip-tests.yml 
new/spyder-kernels-2.1.0/.github/workflows/linux-pip-tests.yml
--- old/spyder-kernels-2.0.4/.github/workflows/linux-pip-tests.yml      
1970-01-01 01:00:00.000000000 +0100
+++ new/spyder-kernels-2.1.0/.github/workflows/linux-pip-tests.yml      
2021-07-31 20:21:53.000000000 +0200
@@ -0,0 +1,53 @@
+name: Linux pip tests
+
+on:
+  push:
+    branches:
+    - master
+    - 2.*
+  pull_request:
+    branches:
+    - master
+    - 2.*
+
+jobs:
+  linux:
+    name: Py${{ matrix.PYTHON_VERSION }}
+    runs-on: ubuntu-latest
+    env:
+      CI: True
+      PYTHON_VERSION: ${{ matrix.PYTHON_VERSION }}
+      RUNNER_OS: 'ubuntu'
+    strategy:
+      fail-fast: false 
+      matrix:
+        PYTHON_VERSION: ['2.7', '3.7', '3.8', '3.9']
+    steps:
+      - name: Checkout branch
+        uses: actions/checkout@v1
+      - name: Install System Packages
+        run: | 
+          sudo apt-get update
+          sudo apt-get install libegl1-mesa
+      - name: Install Conda
+        uses: conda-incubator/setup-miniconda@v2
+        with:
+           activate-environment: test
+           auto-update-conda: false
+           auto-activate-base: false
+           python-version: ${{ matrix.PYTHON_VERSION }} 
+      - name: Install package and dependencies
+        shell: bash -l {0}
+        run: pip install -e .[test]
+      - name: Show environment information
+        shell: bash -l {0}
+        run: |
+          conda info
+          conda list
+      - name: Run tests
+        shell: bash -l {0}
+        run: xvfb-run --auto-servernum pytest spyder_kernels 
--cov=spyder_kernels -x -vv
+      - name: Upload coverage to Codecov
+        if: matrix.PYTHON_VERSION == '3.8'
+        shell: bash -l {0}
+        run: codecov -t 02fa9892-fa7f-4cf8-ac3c-d54143ddc933
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/.github/workflows/linux-tests.yml 
new/spyder-kernels-2.1.0/.github/workflows/linux-tests.yml
--- old/spyder-kernels-2.0.4/.github/workflows/linux-tests.yml  2021-06-11 
00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/.github/workflows/linux-tests.yml  2021-07-31 
20:21:53.000000000 +0200
@@ -4,15 +4,15 @@
   push:
     branches:
     - master
-    - 2.x
+    - 2.*
   pull_request:
     branches:
     - master
-    - 2.x
+    - 2.*
 
 jobs:
   linux:
-    name: Linux Py${{ matrix.PYTHON_VERSION }}
+    name: Py${{ matrix.PYTHON_VERSION }}
     runs-on: ubuntu-latest
     env:
       CI: True
@@ -21,7 +21,7 @@
     strategy:
       fail-fast: false 
       matrix:
-        PYTHON_VERSION: ['2.7', '3.6', '3.7', '3.8']
+        PYTHON_VERSION: ['2.7', '3.7', '3.8', '3.9']
     steps:
       - name: Checkout branch
         uses: actions/checkout@v1
@@ -44,7 +44,6 @@
         run: |
           conda install nomkl -y -q
           conda install --file requirements/tests.txt -y -q
-          if [ "$PYTHON_VERSION" != "2.7" ]; then conda install -y -q 
jedi=0.17.2; fi
           if [ "$PYTHON_VERSION" = "2.7" ]; then conda install -y -q click=7; 
fi
       - name: Install Package
         shell: bash -l {0}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/.github/workflows/macos-tests.yml 
new/spyder-kernels-2.1.0/.github/workflows/macos-tests.yml
--- old/spyder-kernels-2.0.4/.github/workflows/macos-tests.yml  2021-06-11 
00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/.github/workflows/macos-tests.yml  2021-07-31 
20:21:53.000000000 +0200
@@ -4,15 +4,15 @@
   push:
     branches:
     - master
-    - 2.x
+    - 2.*
   pull_request:
     branches:
     - master
-    - 2.x
+    - 2.*
 
 jobs:
   macos:
-    name: Mac Py${{ matrix.PYTHON_VERSION }}
+    name: Py${{ matrix.PYTHON_VERSION }}
     runs-on: macos-latest
     env:
       CI: True
@@ -21,7 +21,7 @@
     strategy:
       fail-fast: false 
       matrix:
-        PYTHON_VERSION: ['2.7', '3.6', '3.7', '3.8']
+        PYTHON_VERSION: ['2.7', '3.7', '3.8', '3.9']
     steps:
       - name: Checkout branch
         uses: actions/checkout@v1
@@ -40,7 +40,6 @@
         run: |
           conda install nomkl -y -q
           conda install --file requirements/tests.txt -y -q
-          if [ "$PYTHON_VERSION" != "2.7" ]; then conda install -y -q 
jedi=0.17.2; fi
           if [ "$PYTHON_VERSION" = "2.7" ]; then conda install -y -q click=7; 
fi
       - name: Install Package
         shell: bash -l {0}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/.github/workflows/windows-tests.yml 
new/spyder-kernels-2.1.0/.github/workflows/windows-tests.yml
--- old/spyder-kernels-2.0.4/.github/workflows/windows-tests.yml        
2021-06-11 00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/.github/workflows/windows-tests.yml        
2021-07-31 20:21:53.000000000 +0200
@@ -4,15 +4,15 @@
   push:
     branches:
     - master
-    - 2.x
+    - 2.*
   pull_request:
     branches:
     - master
-    - 2.x
+    - 2.*
 
 jobs:
   windows:
-    name: Windows Py${{ matrix.PYTHON_VERSION }}
+    name: Py${{ matrix.PYTHON_VERSION }}
     runs-on: windows-latest
     env:
       CI: True
@@ -21,7 +21,7 @@
     strategy:
       fail-fast: false 
       matrix:
-        PYTHON_VERSION: ['3.6', '3.7', '3.8']
+        PYTHON_VERSION: ['3.7', '3.8', '3.9']
     steps:
       - name: Checkout branch
         uses: actions/checkout@v1
@@ -39,7 +39,6 @@
         shell: bash -l {0}
         run: |
           conda install --file requirements/tests.txt -y -q
-          if [ "$PYTHON_VERSION" != "2.7" ]; then conda install -q -y 
jedi=0.17.2; fi
       - name: Install Package
         shell: bash -l {0}
         run: pip install -e .
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spyder-kernels-2.0.4/CHANGELOG.md 
new/spyder-kernels-2.1.0/CHANGELOG.md
--- old/spyder-kernels-2.0.4/CHANGELOG.md       2021-06-11 00:53:30.000000000 
+0200
+++ new/spyder-kernels-2.1.0/CHANGELOG.md       2021-07-31 20:21:53.000000000 
+0200
@@ -1,5 +1,45 @@
 # History of changes
 
+## Version 2.1.0 (2021-07-31)
+
+### New features
+
+* Add support for the Rich and Colorama libraries.
+* Load big modules (e.g. Numpy, Pandas and Scipy) only until it's really
+  necessary.
+
+### Issues Closed
+
+* [Issue 302](https://github.com/spyder-ide/spyder-kernels/issues/302) - Add 
option to use custom Outstream in kernel app ([PR 
305](https://github.com/spyder-ide/spyder-kernels/pull/305) by 
[@eendebakpt](https://github.com/eendebakpt))
+
+In this release 1 issue was closed.
+
+### Pull Requests Merged
+
+* [PR 306](https://github.com/spyder-ide/spyder-kernels/pull/306) - PR: Patch 
os.get_terminal_size to return a terminal size, by 
[@ccordoba12](https://github.com/ccordoba12)
+* [PR 305](https://github.com/spyder-ide/spyder-kernels/pull/305) - PR: Use an 
outstream with isatty() equal to True, by 
[@eendebakpt](https://github.com/eendebakpt) 
([302](https://github.com/spyder-ide/spyder-kernels/issues/302))
+* [PR 303](https://github.com/spyder-ide/spyder-kernels/pull/303) - PR: Remove 
an unnecessary check when getting values in Pdb, by 
[@ccordoba12](https://github.com/ccordoba12)
+* [PR 300](https://github.com/spyder-ide/spyder-kernels/pull/300) - PR: Fix 
%debug magic, by [@impact27](https://github.com/impact27)
+* [PR 259](https://github.com/spyder-ide/spyder-kernels/pull/259) - PR: Don't 
import big modules (Numpy, Pandas) until it's really necessary, by 
[@ccordoba12](https://github.com/ccordoba12)
+
+In this release 5 pull requests were closed.
+
+
+----
+
+
+## Version 2.0.5 (2021-07-03)
+
+### Pull Requests Merged
+
+* [PR 292](https://github.com/spyder-ide/spyder-kernels/pull/292) - PR: Add 
support for ipykernel 6, by [@ccordoba12](https://github.com/ccordoba12)
+
+In this release 1 pull request was closed.
+
+
+----
+
+
 ## Version 2.0.4 (2021-06-10)
 
 ### Issues Closed
@@ -61,6 +101,7 @@
 ## Version 2.0.0 (2021-04-01)
 
 ### New features
+
 * Color handling in namespace view was moved to Spyder.
 
 ### Pull Requests Merged
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spyder-kernels-2.0.4/README.md 
new/spyder-kernels-2.1.0/README.md
--- old/spyder-kernels-2.0.4/README.md  2021-06-11 00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/README.md  2021-07-31 20:21:53.000000000 +0200
@@ -13,10 +13,10 @@
 code inside Spyder.
 
 To learn about creating, connecting to and using these kernels with the Spyder
-console, please read our 
[documentation](https://docs.spyder-ide.org/ipythonconsole.html).
+console, please read our 
[documentation](https://docs.spyder-ide.org/current/panes/ipythonconsole.html).
 
-For advice on managing packages and environments with `spyder-kernels`, please 
visit
-our 
[wiki](https://github.com/spyder-ide/spyder/wiki/Working-with-packages-and-environments-in-Spyder).
+For advice on managing packages and environments with `spyder-kernels`, please 
read this
+[FAQ](http://docs.spyder-ide.org/current/faq.html#using-existing-environment) 
in our docs.
 
 
 ## Installation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spyder-kernels-2.0.4/spyder_kernels/_version.py 
new/spyder-kernels-2.1.0/spyder_kernels/_version.py
--- old/spyder-kernels-2.0.4/spyder_kernels/_version.py 2021-06-11 
00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/spyder_kernels/_version.py 2021-07-31 
20:21:53.000000000 +0200
@@ -8,5 +8,5 @@
 
 """Version File."""
 
-VERSION_INFO = (2, 0, 4)
+VERSION_INFO = (2, 1, 0)
 __version__ = '.'.join(map(str, VERSION_INFO))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/spyder_kernels/comms/frontendcomm.py 
new/spyder-kernels-2.1.0/spyder_kernels/comms/frontendcomm.py
--- old/spyder-kernels-2.0.4/spyder_kernels/comms/frontendcomm.py       
2021-06-11 00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/spyder_kernels/comms/frontendcomm.py       
2021-07-31 20:21:53.000000000 +0200
@@ -8,16 +8,18 @@
 In addition to the remote_call mechanism implemented in CommBase:
  - Implements _wait_reply, so blocking calls can be made.
 """
+
 import pickle
 import socket
 import sys
 import threading
 import time
 
+import ipykernel
+from IPython.core.getipython import get_ipython
 from jupyter_client.localinterfaces import localhost
 from tornado import ioloop
 import zmq
-from IPython.core.getipython import get_ipython
 
 from spyder_kernels.comms.commbase import CommBase, CommError
 from spyder_kernels.py3compat import TimeoutError, PY2
@@ -148,7 +150,24 @@
             self.kernel.log.warning("Unknown message type: %r", msg_type)
         else:
             try:
-                handler(out_stream, ident, msg)
+                if not PY2:
+                    import asyncio
+                    if (not getattr(asyncio, 'run', False) or
+                            ipykernel.__version__[0] < '6'):
+                        # This is required for Python 3.6, which doesn't have
+                        # asyncio.run or ipykernel versions less than 6. The
+                        # nice thing is that ipykernel 6, which requires
+                        # asyncio, doesn't support Python 3.6.
+                        handler(out_stream, ident, msg)
+                    else:
+                        # This is needed for ipykernel 6+
+                        asyncio.run(handler(out_stream, ident, msg))
+                else:
+                    handler(out_stream, ident, msg)
+            except ValueError as e:
+                # This avoids showing an unnecessary message about expected
+                # coroutines.
+                return
             except Exception:
                 self.kernel.log.error("Exception in message handler:",
                                       exc_info=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/spyder_kernels/console/kernel.py 
new/spyder-kernels-2.1.0/spyder_kernels/console/kernel.py
--- old/spyder-kernels-2.0.4/spyder_kernels/console/kernel.py   2021-06-11 
00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/spyder_kernels/console/kernel.py   2021-07-31 
20:21:53.000000000 +0200
@@ -26,8 +26,10 @@
 from spyder_kernels.py3compat import TEXT_TYPES, to_text_string
 from spyder_kernels.comms.frontendcomm import FrontendComm
 from spyder_kernels.py3compat import PY3, input
-from spyder_kernels.utils.misc import (
+from spyder_kernels.utils.iofuncs import iofunctions
+from spyder_kernels.utils.mpl import (
     MPL_BACKENDS_FROM_SPYDER, MPL_BACKENDS_TO_SPYDER, INLINE_FIGURE_FORMATS)
+from spyder_kernels.utils.nsview import get_remote_data, make_remote_view
 
 
 # Excluded variables from the Variable Explorer (i.e. they are not
@@ -105,7 +107,6 @@
         self.namespace_view_settings = {}
         self._pdb_obj = None
         self._pdb_step = None
-        self._do_publish_pdb_state = True
         self._mpl_backend_error = None
         self._running_namespace = None
         self._pdb_input_line = None
@@ -157,7 +158,6 @@
         * 'numpy_type' is its Numpy type (if any) computed with
           `get_numpy_type_string`.
         """
-        from spyder_kernels.utils.nsview import make_remote_view
 
         settings = self.namespace_view_settings
         if settings:
@@ -172,8 +172,6 @@
         Get some properties of the variables in the current
         namespace
         """
-        from spyder_kernels.utils.nsview import get_remote_data
-
         settings = self.namespace_view_settings
         if settings:
             ns = self._get_current_namespace()
@@ -202,7 +200,6 @@
     def get_value(self, name):
         """Get the value of a variable"""
         ns = self._get_current_namespace()
-        self._do_publish_pdb_state = False
         return ns[name]
 
     def set_value(self, name, value):
@@ -234,11 +231,9 @@
         In the other hand, with 'overwrite=False', a new variable will be
         created with a sufix starting with 000 i.e 'var000' (default behavior).
         """
-        from spyder_kernels.utils.iofuncs import iofunctions
         from spyder_kernels.utils.misc import fix_reference_name
 
         glbs = self._mglobals()
-
         load_func = iofunctions.load_funcs[ext]
         data, error_message = load_func(filename)
 
@@ -261,9 +256,6 @@
 
     def save_namespace(self, filename):
         """Save namespace into filename"""
-        from spyder_kernels.utils.nsview import get_remote_data
-        from spyder_kernels.utils.iofuncs import iofunctions
-
         ns = self._get_current_namespace()
         settings = self.namespace_view_settings
         data = get_remote_data(ns, settings, mode='picklable',
@@ -292,16 +284,12 @@
         return self._do_complete(code, cursor_pos)
 
     def publish_pdb_state(self):
-        """
-        Publish Variable Explorer state and Pdb step through
-        send_spyder_msg.
-        """
-        if self._pdb_obj and self._do_publish_pdb_state:
+        """Publish Pdb state."""
+        if self._pdb_obj:
             state = dict(namespace_view = self.get_namespace_view(),
                          var_properties = self.get_var_properties(),
                          step = self._pdb_step)
             self.frontend_call(blocking=False).pdb_state(state)
-        self._do_publish_pdb_state = True
 
     def set_spyder_breakpoints(self, breakpoints):
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/spyder_kernels/console/outstream.py 
new/spyder-kernels-2.1.0/spyder_kernels/console/outstream.py
--- old/spyder-kernels-2.0.4/spyder_kernels/console/outstream.py        
1970-01-01 01:00:00.000000000 +0100
+++ new/spyder-kernels-2.1.0/spyder_kernels/console/outstream.py        
2021-07-31 20:21:53.000000000 +0200
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# -----------------------------------------------------------------------------
+# Copyright (c) 2009- Spyder Kernels Contributors
+#
+# Licensed under the terms of the MIT License
+# (see spyder_kernels/__init__.py for details)
+# -----------------------------------------------------------------------------
+
+"""
+Custom Spyder Outstream class.
+"""
+
+from ipykernel.iostream import OutStream
+
+
+class TTYOutStream(OutStream):
+    """Subclass of OutStream that represents a TTY."""
+
+    def __init__(self, session, pub_thread, name, pipe=None, echo=None, *,
+                 watchfd=True):
+        super().__init__(session, pub_thread, name, pipe,
+                         echo=echo, watchfd=watchfd, isatty=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spyder-kernels-2.0.4/spyder_kernels/console/start.py 
new/spyder-kernels-2.1.0/spyder_kernels/console/start.py
--- old/spyder-kernels-2.0.4/spyder_kernels/console/start.py    2021-06-11 
00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/spyder_kernels/console/start.py    2021-07-31 
20:21:53.000000000 +0200
@@ -17,12 +17,18 @@
 import sys
 import site
 
+from traitlets import DottedObjectName
+import ipykernel
+
 # Local imports
-from spyder_kernels.utils.misc import (
-    MPL_BACKENDS_FROM_SPYDER, INLINE_FIGURE_FORMATS, is_module_installed)
+from spyder_kernels.utils.misc import is_module_installed
+from spyder_kernels.utils.mpl import (
+    MPL_BACKENDS_FROM_SPYDER, INLINE_FIGURE_FORMATS)
 
 
 PY2 = sys.version[0] == '2'
+IPYKERNEL_6 = ipykernel.__version__[0] >= '6'
+
 
 
 def import_spydercustomize():
@@ -269,6 +275,10 @@
 
     class SpyderKernelApp(IPKernelApp):
 
+        if IPYKERNEL_6:
+            outstream_class = DottedObjectName(
+                'spyder_kernels.console.outstream.TTYOutStream')
+
         def init_pdb(self):
             """
             This method was added in IPykernel 5.3.1 and it replaces
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/spyder_kernels/console/tests/test_console_kernel.py 
new/spyder-kernels-2.1.0/spyder_kernels/console/tests/test_console_kernel.py
--- 
old/spyder-kernels-2.0.4/spyder_kernels/console/tests/test_console_kernel.py    
    2021-06-11 00:53:30.000000000 +0200
+++ 
new/spyder-kernels-2.1.0/spyder_kernels/console/tests/test_console_kernel.py    
    2021-07-31 20:21:53.000000000 +0200
@@ -21,6 +21,7 @@
 import inspect
 
 # Test imports
+import ipykernel
 import IPython
 import pytest
 from flaky import flaky
@@ -29,17 +30,23 @@
 from ipython_genutils import py3compat
 import numpy as np
 
-
 # Local imports
 from spyder_kernels.py3compat import PY3, to_text_string
 from spyder_kernels.utils.iofuncs import iofunctions
 from spyder_kernels.utils.test_utils import get_kernel, get_log_text
 from spyder_kernels.customize.spyderpdb import SpyderPdb
 
+# For ipykernel 6
+try:
+    import asyncio
+except ImportError:
+    pass
+
 # =============================================================================
 # Constants
 # =============================================================================
 FILES_PATH = os.path.dirname(os.path.realpath(__file__))
+IPYKERNEL_6 = ipykernel.__version__[0] >= '6'
 TIMEOUT = 15
 SETUP_TIMEOUT = 60
 
@@ -131,7 +138,10 @@
 
     # Teardown
     def reset_kernel():
-        kernel.do_execute('reset -f', True)
+        if IPYKERNEL_6:
+            asyncio.run(kernel.do_execute('reset -f', True))
+        else:
+            kernel.do_execute('reset -f', True)
     request.addfinalizer(reset_kernel)
 
     return kernel
@@ -176,7 +186,10 @@
     """
     Test the namespace view of the kernel.
     """
-    execute = kernel.do_execute('a = 1', True)
+    if IPYKERNEL_6:
+        execute = asyncio.run(kernel.do_execute('a = 1', True))
+    else:
+        execute = kernel.do_execute('a = 1', True)
 
     nsview = repr(kernel.get_namespace_view())
     assert "'a':" in nsview
@@ -195,7 +208,10 @@
     """
     Test the properties fo the variables in the namespace.
     """
-    execute = kernel.do_execute('a = 1', True)
+    if IPYKERNEL_6:
+        asyncio.run(kernel.do_execute('a = 1', True))
+    else:
+        kernel.do_execute('a = 1', True)
 
     var_properties = repr(kernel.get_var_properties())
     assert "'a'" in var_properties
@@ -213,7 +229,10 @@
 def test_get_value(kernel):
     """Test getting the value of a variable."""
     name = 'a'
-    kernel.do_execute("a = 124", True)
+    if IPYKERNEL_6:
+        asyncio.run(kernel.do_execute("a = 124", True))
+    else:
+        kernel.do_execute("a = 124", True)
 
     # Check data type send
     assert kernel.get_value(name) == 124
@@ -222,7 +241,10 @@
 def test_set_value(kernel):
     """Test setting the value of a variable."""
     name = 'a'
-    execute = kernel.do_execute('a = 0', True)
+    if IPYKERNEL_6:
+         asyncio.run(kernel.do_execute('a = 0', True))
+    else:
+        kernel.do_execute('a = 0', True)
     value = 10
     kernel.set_value(name, value)
     log_text = get_log_text(kernel)
@@ -236,7 +258,10 @@
 def test_remove_value(kernel):
     """Test the removal of a variable."""
     name = 'a'
-    execute = kernel.do_execute('a = 1', True)
+    if IPYKERNEL_6:
+        asyncio.run(kernel.do_execute('a = 1', True))
+    else:
+        kernel.do_execute('a = 1', True)
 
     var_properties = repr(kernel.get_var_properties())
     assert "'a'" in var_properties
@@ -258,7 +283,10 @@
     """Test the copy of a variable."""
     orig_name = 'a'
     new_name = 'b'
-    execute = kernel.do_execute('a = 1', True)
+    if IPYKERNEL_6:
+         asyncio.run(kernel.do_execute('a = 1', True))
+    else:
+        kernel.do_execute('a = 1', True)
 
     var_properties = repr(kernel.get_var_properties())
     assert "'a'" in var_properties
@@ -294,7 +322,12 @@
     namespace_file = osp.join(FILES_PATH, 'load_data.npz')
     extention = '.npz'
     overwrite, execute, variables = load
-    kernel.do_execute(execute, True)
+
+    if IPYKERNEL_6:
+        asyncio.run(kernel.do_execute(execute, True))
+    else:
+        kernel.do_execute(execute, True)
+
     kernel.load_data(namespace_file, extention, overwrite=overwrite)
     for var, value in variables.items():
         assert value == kernel.get_value(var)
@@ -321,7 +354,11 @@
 def test_save_namespace(kernel):
     """Test saving the namespace into filename."""
     namespace_file = osp.join(FILES_PATH, 'save_data.spydata')
-    execute = kernel.do_execute('b = 1', True)
+
+    if IPYKERNEL_6:
+        asyncio.run(kernel.do_execute('b = 1', True))
+    else:
+        kernel.do_execute('b = 1', True)
 
     kernel.save_namespace(namespace_file)
     assert osp.isfile(namespace_file)
@@ -365,7 +402,11 @@
 
     # With Wurlitzer we have the expected output
     kernel._load_wurlitzer()
-    reply = kernel.do_execute(code, True)
+
+    if IPYKERNEL_6:
+        asyncio.run(kernel.do_execute(code, True))
+    else:
+        kernel.do_execute(code, True)
     captured = capsys.readouterr()
     assert captured.out == "Hello from C\n"
 
@@ -701,7 +742,10 @@
     """
     Check do complete works in normal and debugging mode.
     """
-    kernel.do_execute('abba = 1', True)
+    if IPYKERNEL_6:
+        asyncio.run(kernel.do_execute('abba = 1', True))
+    else:
+        kernel.do_execute('abba = 1', True)
     assert kernel.get_value('abba') == 1
     match = kernel.do_complete('ab', 2)
     assert 'abba' in match['matches']
@@ -723,9 +767,15 @@
     Tests that callables and modules are in the namespace view only
     when the right options are passed to the kernel.
     """
-    kernel.do_execute('import numpy', True)
-    kernel.do_execute('a = 10', True)
-    kernel.do_execute('def f(x): return x', True)
+    if IPYKERNEL_6:
+        asyncio.run(kernel.do_execute('import numpy', True))
+        asyncio.run(kernel.do_execute('a = 10', True))
+        asyncio.run(kernel.do_execute('def f(x): return x', True))
+    else:
+        kernel.do_execute('import numpy', True)
+        kernel.do_execute('a = 10', True)
+        kernel.do_execute('def f(x): return x', True)
+
     settings = kernel.namespace_view_settings
 
     settings['exclude_callables_and_modules'] = exclude_callables_and_modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/spyder_kernels/customize/spydercustomize.py 
new/spyder-kernels-2.1.0/spyder_kernels/customize/spydercustomize.py
--- old/spyder-kernels-2.0.4/spyder_kernels/customize/spydercustomize.py        
2021-06-11 00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/spyder_kernels/customize/spydercustomize.py        
2021-07-31 20:21:53.000000000 +0200
@@ -109,6 +109,7 @@
 
     subprocess.Popen = SubprocessPopen
 
+
 # =============================================================================
 # Importing user's sitecustomize
 # =============================================================================
@@ -185,6 +186,7 @@
 except Exception:
     pass
 
+
 # =============================================================================
 # IPython adjustments
 # =============================================================================
@@ -312,6 +314,16 @@
 
 
 # =============================================================================
+# os adjustments
+# =============================================================================
+# This is necessary to have better support for Rich and Colorama.
+def _patched_get_terminal_size(fd=None):
+    return os.terminal_size((80, 30))
+
+os.get_terminal_size = _patched_get_terminal_size
+
+
+# =============================================================================
 # Pdb adjustments
 # =============================================================================
 def cmd_input(prompt=''):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/spyder_kernels/customize/spyderpdb.py 
new/spyder-kernels-2.1.0/spyder_kernels/customize/spyderpdb.py
--- old/spyder-kernels-2.0.4/spyder_kernels/customize/spyderpdb.py      
2021-06-11 00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/spyder_kernels/customize/spyderpdb.py      
2021-07-31 20:21:53.000000000 +0200
@@ -36,7 +36,7 @@
 
 class DebugWrapper(object):
     """
-    Notifies the frontend when debuggging starts/stops
+    Notifies the frontend when debugging starts/stops
     """
     def __init__(self, pdb_obj):
         self.pdb_obj = pdb_obj
@@ -712,6 +712,7 @@
 
         globals defaults to __main__.dict; locals defaults to globals.
         """
+        self.starting = True
         with DebugWrapper(self):
             super(SpyderPdb, self).run(cmd, globals, locals)
 
@@ -720,6 +721,7 @@
 
         globals defaults to __main__.dict; locals defaults to globals.
         """
+        self.starting = True
         with DebugWrapper(self):
             super(SpyderPdb, self).runeval(expr, globals, locals)
 
@@ -728,6 +730,7 @@
 
         Return the result of the function call.
         """
+        self.starting = True
         with DebugWrapper(self):
             super(SpyderPdb, self).runcall(*args, **kwds)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spyder-kernels-2.0.4/spyder_kernels/utils/iofuncs.py 
new/spyder-kernels-2.1.0/spyder_kernels/utils/iofuncs.py
--- old/spyder-kernels-2.0.4/spyder_kernels/utils/iofuncs.py    2021-06-11 
00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/spyder_kernels/utils/iofuncs.py    2021-07-31 
20:21:53.000000000 +0200
@@ -30,18 +30,10 @@
 import copy
 import glob
 
-# Third party imports
-# - If pandas fails to import here (for any reason), Spyder
-#   will crash at startup (e.g. see Issue 2300)
-# - This also prevents Spyder to start IPython kernels
-#   (see Issue 2456)
-try:
-    import pandas as pd
-except:
-    pd = None            #analysis:ignore
-
 # Local imports
 from spyder_kernels.py3compat import getcwd, pickle, PY2, to_text_string
+from spyder_kernels.utils.lazymodules import (
+    FakeObject, numpy as np, pandas as pd, PIL, scipy as sp)
 
 
 class MatlabStruct(dict):
@@ -110,8 +102,6 @@
     From the oct2py project, see
     https://pythonhosted.org/oct2py/conversions.html
     """
-    import numpy as np
-
     # Extract each item of a list.
     if isinstance(val, list):
         return [get_matlab_value(v) for v in val]
@@ -156,113 +146,102 @@
     return val
 
 
-try:
-    import numpy as np
+def load_matlab(filename):
+    if sp.io is FakeObject:
+        return None, ''
+
     try:
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore")
-            import scipy.io as spio
-    except AttributeError:
-        # Python 2.5: warnings.catch_warnings was introduced in Python 2.6
-        import scipy.io as spio  # analysis:ignore
-    except:
-        spio = None
-
-    if spio is None:
-        load_matlab = None
-        save_matlab = None
-    else:
-        def load_matlab(filename):
-            try:
-                out = spio.loadmat(filename, struct_as_record=True)
-                data = dict()
-                for (key, value) in out.items():
-                    data[key] = get_matlab_value(value)
-                return data, None
-            except Exception as error:
-                return None, str(error)
+        out = sp.io.loadmat(filename, struct_as_record=True)
+        data = dict()
+        for (key, value) in out.items():
+            data[key] = get_matlab_value(value)
+        return data, None
+    except Exception as error:
+        return None, str(error)
 
-        def save_matlab(data, filename):
-            try:
-                spio.savemat(filename, data, oned_as='row')
-            except Exception as error:
-                return str(error)
-except:
-    load_matlab = None
-    save_matlab = None
 
+def save_matlab(data, filename):
+    if sp.io is FakeObject:
+        return
 
-try:
-    import numpy as np  # analysis:ignore
+    try:
+        sp.io.savemat(filename, data, oned_as='row')
+    except Exception as error:
+        return str(error)
 
-    def load_array(filename):
-        try:
-            name = osp.splitext(osp.basename(filename))[0]
-            data = np.load(filename)
-            if isinstance(data, np.lib.npyio.NpzFile):
-                return dict(data), None
-            elif hasattr(data, 'keys'):
-                return data, None
-            else:
-                return {name: data}, None
-        except Exception as error:
-            return None, str(error)
-
-    def __save_array(data, basename, index):
-        """Save numpy array"""
-        fname = basename + '_%04d.npy' % index
-        np.save(fname, data)
-        return fname
-except:
-    load_array = None
 
+def load_array(filename):
+    if np.load is FakeObject:
+        return None, ''
 
-try:
-    from spyder.pil_patch import Image
+    try:
+        name = osp.splitext(osp.basename(filename))[0]
+        data = np.load(filename)
+        if isinstance(data, np.lib.npyio.NpzFile):
+            return dict(data), None
+        elif hasattr(data, 'keys'):
+            return data, None
+        else:
+            return {name: data}, None
+    except Exception as error:
+        return None, str(error)
+
+
+def __save_array(data, basename, index):
+    """Save numpy array"""
+    fname = basename + '_%04d.npy' % index
+    np.save(fname, data)
+    return fname
+
+
+if sys.byteorder == 'little':
+    _ENDIAN = '<'
+else:
+    _ENDIAN = '>'
+
+DTYPES = {
+    "1": ('|b1', None),
+    "L": ('|u1', None),
+    "I": ('%si4' % _ENDIAN, None),
+    "F": ('%sf4' % _ENDIAN, None),
+    "I;16": ('|u2', None),
+    "I;16S": ('%si2' % _ENDIAN, None),
+    "P": ('|u1', None),
+    "RGB": ('|u1', 3),
+    "RGBX": ('|u1', 4),
+    "RGBA": ('|u1', 4),
+    "CMYK": ('|u1', 4),
+    "YCbCr": ('|u1', 4),
+}
 
-    if sys.byteorder == 'little':
-        _ENDIAN = '<'
-    else:
-        _ENDIAN = '>'
-    DTYPES = {
-              "1": ('|b1', None),
-              "L": ('|u1', None),
-              "I": ('%si4' % _ENDIAN, None),
-              "F": ('%sf4' % _ENDIAN, None),
-              "I;16": ('|u2', None),
-              "I;16S": ('%si2' % _ENDIAN, None),
-              "P": ('|u1', None),
-              "RGB": ('|u1', 3),
-              "RGBX": ('|u1', 4),
-              "RGBA": ('|u1', 4),
-              "CMYK": ('|u1', 4),
-              "YCbCr": ('|u1', 4),
-              }
-    def __image_to_array(filename):
-        img = Image.open(filename)
-        try:
-            dtype, extra = DTYPES[img.mode]
-        except KeyError:
-            raise RuntimeError("%s mode is not supported" % img.mode)
-        shape = (img.size[1], img.size[0])
-        if extra is not None:
-            shape += (extra,)
-        return np.array(img.getdata(), dtype=np.dtype(dtype)).reshape(shape)
 
-    def load_image(filename):
-        try:
-            name = osp.splitext(osp.basename(filename))[0]
-            return {name: __image_to_array(filename)}, None
-        except Exception as error:
-            return None, str(error)
-except:
-    load_image = None
+def __image_to_array(filename):
+    img = PIL.Image.open(filename)
+    try:
+        dtype, extra = DTYPES[img.mode]
+    except KeyError:
+        raise RuntimeError("%s mode is not supported" % img.mode)
+    shape = (img.size[1], img.size[0])
+    if extra is not None:
+        shape += (extra,)
+    return np.array(img.getdata(), dtype=np.dtype(dtype)).reshape(shape)
+
+
+def load_image(filename):
+    if PIL.Image is FakeObject or np.array is FakeObject:
+        return None, ''
+
+    try:
+        name = osp.splitext(osp.basename(filename))[0]
+        return {name: __image_to_array(filename)}, None
+    except Exception as error:
+        return None, str(error)
 
 
 def load_pickle(filename):
     """Load a pickle file as a dictionary"""
     try:
-        if pd:
+        if pd.read_pickle is not FakeObject:
             return pd.read_pickle(filename), None
         else:
             with open(filename, 'rb') as fid:
@@ -315,13 +294,13 @@
             raise RuntimeError('No supported objects to save')
 
         saved_arrays = {}
-        if load_array is not None:
+        if np.ndarray is not FakeObject:
             # Saving numpy arrays with np.save
             arr_fname = osp.splitext(filename)[0]
             for name in list(data.keys()):
                 try:
-                    if isinstance(data[name],
-                                  np.ndarray) and data[name].size > 0:
+                    if (isinstance(data[name], np.ndarray) and
+                            data[name].size > 0):
                         # Save arrays at data root
                         fname = __save_array(data[name], arr_fname,
                                              len(saved_arrays))
@@ -335,8 +314,8 @@
                             iterator = iter(list(data[name].items()))
                         to_remove = []
                         for index, value in iterator:
-                            if isinstance(value,
-                                          np.ndarray) and value.size > 0:
+                            if (isinstance(value, np.ndarray) and
+                                    value.size > 0):
                                 fname = __save_array(value, arr_fname,
                                                      len(saved_arrays))
                                 saved_arrays[(name, index)] = (
@@ -407,12 +386,12 @@
         with open(pickle_filename, 'rb') as fdesc:
             data = pickle.loads(fdesc.read())
         saved_arrays = {}
-        if load_array is not None:
+        if np.load is not FakeObject:
             # Loading numpy arrays saved with np.save
             try:
                 saved_arrays = data.pop('__saved_arrays__')
                 for (name, index), fname in list(saved_arrays.items()):
-                    arr = np.load( osp.join(tmp_folder, fname) )
+                    arr = np.load(osp.join(tmp_folder, fname))
                     if index is None:
                         data[name] = arr
                     elif isinstance(data[name], dict):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/spyder_kernels/utils/lazymodules.py 
new/spyder-kernels-2.1.0/spyder_kernels/utils/lazymodules.py
--- old/spyder-kernels-2.0.4/spyder_kernels/utils/lazymodules.py        
1970-01-01 01:00:00.000000000 +0100
+++ new/spyder-kernels-2.1.0/spyder_kernels/utils/lazymodules.py        
2021-07-31 20:21:53.000000000 +0200
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+# -----------------------------------------------------------------------------
+# Copyright (c) 2009- Spyder Kernels Contributors
+#
+# Licensed under the terms of the MIT License
+# (see spyder_kernels/__init__.py for details)
+# -----------------------------------------------------------------------------
+
+"""
+Lazy modules.
+
+They are useful to not import big modules until it's really necessary.
+"""
+
+from spyder_kernels.utils.misc import is_module_installed
+
+
+# =============================================================================
+# Auxiliary classes
+# =============================================================================
+class FakeObject(object):
+    """Fake class used in replacement of missing objects"""
+    pass
+
+
+class LazyModule(object):
+    """Lazy module loader class."""
+
+    def __init__(self, modname, second_level_attrs=None):
+        """
+        Lazy module loader class.
+
+        Parameters
+        ----------
+        modname: str
+            Module name to lazy load.
+        second_level_attrs: list (optional)
+            List of second level attributes to add to the FakeObject
+            that stands for the module in case it's not found.
+        """
+        self.__spy_modname__ = modname
+        self.__spy_mod__ = FakeObject
+
+        # Set required second level attributes
+        if second_level_attrs is not None:
+            for attr in second_level_attrs:
+                setattr(self.__spy_mod__, attr, FakeObject)
+
+    def __getattr__(self, name):
+        if is_module_installed(self.__spy_modname__):
+            self.__spy_mod__ = __import__(self.__spy_modname__)
+        else:
+            return self.__spy_mod__
+
+        return getattr(self.__spy_mod__, name)
+
+
+# =============================================================================
+# Lazy modules
+# =============================================================================
+numpy = LazyModule('numpy', ['MaskedArray'])
+
+pandas = LazyModule('pandas')
+
+PIL = LazyModule('PIL.Image', ['Image'])
+
+bs4 = LazyModule('bs4', ['NavigableString'])
+
+scipy = LazyModule('scipy.io')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spyder-kernels-2.0.4/spyder_kernels/utils/misc.py 
new/spyder-kernels-2.1.0/spyder_kernels/utils/misc.py
--- old/spyder-kernels-2.0.4/spyder_kernels/utils/misc.py       2021-06-11 
00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/spyder_kernels/utils/misc.py       2021-07-31 
20:21:53.000000000 +0200
@@ -11,25 +11,6 @@
 import re
 
 
-# Mapping of inline figure formats
-INLINE_FIGURE_FORMATS = {
-    '0': 'png',
-    '1': 'svg'
-}
-
-# Mapping of matlotlib backends options to Spyder
-MPL_BACKENDS_TO_SPYDER = {
-    'module://ipykernel.pylab.backend_inline': 0,
-    'Qt5Agg': 2,
-    'Qt4Agg': 3,
-    'MacOSX': 4,
-    'GTK3Agg': 5,
-    'GTKAgg': 6,
-    'WX': 7,
-    'TkAgg': 8
-}
-
-
 def is_module_installed(module_name):
     """
     Simpler version of spyder.utils.programs.is_module_installed.
@@ -47,33 +28,6 @@
         return False
 
 
-def automatic_backend():
-    """Get Matplolib automatic backend option."""
-    if is_module_installed('PyQt5'):
-        auto_backend = 'qt5'
-    elif is_module_installed('PyQt4'):
-        auto_backend = 'qt4'
-    elif is_module_installed('_tkinter'):
-        auto_backend = 'tk'
-    else:
-        auto_backend = 'inline'
-    return auto_backend
-
-
-# Mapping of Spyder options to backends
-MPL_BACKENDS_FROM_SPYDER = {
-    '0': 'inline',
-    '1': automatic_backend(),
-    '2': 'qt5',
-    '3': 'qt4',
-    '4': 'osx',
-    '5': 'gtk3',
-    '6': 'gtk',
-    '7': 'wx',
-    '8': 'tk'
-}
-
-
 def fix_reference_name(name, blacklist=None):
     """Return a syntax-valid Python reference name from an arbitrary name"""
     name = "".join(re.split(r'[^0-9a-zA-Z_]', name))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spyder-kernels-2.0.4/spyder_kernels/utils/mpl.py 
new/spyder-kernels-2.1.0/spyder_kernels/utils/mpl.py
--- old/spyder-kernels-2.0.4/spyder_kernels/utils/mpl.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/spyder-kernels-2.1.0/spyder_kernels/utils/mpl.py        2021-07-31 
20:21:53.000000000 +0200
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+# -----------------------------------------------------------------------------
+# Copyright (c) 2009- Spyder Kernels Contributors
+#
+# Licensed under the terms of the MIT License
+# (see spyder_kernels/__init__.py for details)
+# -----------------------------------------------------------------------------
+
+"""Matplotlib utilities."""
+
+from spyder_kernels.utils.misc import is_module_installed
+
+
+# Mapping of inline figure formats
+INLINE_FIGURE_FORMATS = {
+    '0': 'png',
+    '1': 'svg'
+}
+
+
+# Mapping of matlotlib backends options to Spyder
+MPL_BACKENDS_TO_SPYDER = {
+    'module://ipykernel.pylab.backend_inline': 0,
+    'Qt5Agg': 2,
+    'Qt4Agg': 3,
+    'MacOSX': 4,
+    'GTK3Agg': 5,
+    'GTKAgg': 6,
+    'WX': 7,
+    'TkAgg': 8
+}
+
+
+def automatic_backend():
+    """Get Matplolib automatic backend option."""
+    if is_module_installed('PyQt5'):
+        auto_backend = 'qt5'
+    elif is_module_installed('PyQt4'):
+        auto_backend = 'qt4'
+    elif is_module_installed('_tkinter'):
+        auto_backend = 'tk'
+    else:
+        auto_backend = 'inline'
+    return auto_backend
+
+
+# Mapping of Spyder options to backends
+MPL_BACKENDS_FROM_SPYDER = {
+    '0': 'inline',
+    '1': automatic_backend(),
+    '2': 'qt5',
+    '3': 'qt4',
+    '4': 'osx',
+    '5': 'gtk3',
+    '6': 'gtk',
+    '7': 'wx',
+    '8': 'tk'
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spyder-kernels-2.0.4/spyder_kernels/utils/nsview.py 
new/spyder-kernels-2.1.0/spyder_kernels/utils/nsview.py
--- old/spyder-kernels-2.0.4/spyder_kernels/utils/nsview.py     2021-06-11 
00:53:30.000000000 +0200
+++ new/spyder-kernels-2.1.0/spyder_kernels/utils/nsview.py     2021-07-31 
20:21:53.000000000 +0200
@@ -7,7 +7,7 @@
 # -----------------------------------------------------------------------------
 
 """
-Utilities
+Utilities to build a namespace view.
 """
 
 from __future__ import print_function
@@ -22,44 +22,25 @@
                                       is_type_text_string,
                                       is_binary_string, PY2,
                                       to_binary_string, iteritems)
+from spyder_kernels.utils.lazymodules import (
+    bs4, FakeObject, numpy as np, pandas as pd, PIL)
 
 
 #==============================================================================
-# FakeObject
+# Numpy support
 #==============================================================================
-class FakeObject(object):
-    """Fake class used in replacement of missing modules"""
-    pass
-
-
-#==============================================================================
-# Numpy arrays and numeric types support
-#==============================================================================
-try:
-    from numpy import (ndarray, array, matrix, recarray, integer,
-                       int64, int32, int16, int8, uint64, uint32, uint16, 
uint8,
-                       float64, float32, float16, complex64, complex128, bool_)
-    from numpy.ma import MaskedArray
-    from numpy import savetxt as np_savetxt
-    from numpy import get_printoptions, set_printoptions
-except:
-    ndarray = array = matrix = recarray = MaskedArray = np_savetxt = \
-     int64 = int32 = int16 = int8 = uint64 = uint32 = uint16 = uint8 = \
-     float64 = float32 = float16 = complex64 = complex128 = bool_ = FakeObject
-
-
-NUMERIC_NUMPY_TYPES = (int64, int32, int16, int8, uint64, uint32, uint16,
-                       uint8, float64, float32, float16, complex64, complex128,
-                       bool_)
+def get_numeric_numpy_types():
+    return (np.int64, np.int32, np.int16, np.int8, np.uint64, np.uint32,
+            np.uint16, np.uint8, np.float64, np.float32, np.float16,
+            np.complex64, np.complex128, np.bool_)
 
 
 def get_numpy_dtype(obj):
     """Return NumPy data type associated to obj
     Return None if NumPy is not available
     or if obj is not a NumPy array or scalar"""
-    if ndarray is not FakeObject:
+    if np.ndarray is not FakeObject:
         # NumPy is available
-        import numpy as np
         if isinstance(obj, np.generic) or isinstance(obj, np.ndarray):
         # Numpy scalars all inherit from np.generic.
         # Numpy arrays all inherit from np.ndarray.
@@ -85,35 +66,6 @@
 
 
 #==============================================================================
-# Pandas support
-#==============================================================================
-try:
-    from pandas import DataFrame, Index, Series
-except:
-    DataFrame = Index = Series = FakeObject
-
-
-#==============================================================================
-# PIL Images support
-#==============================================================================
-try:
-    from spyder import pil_patch
-    Image = pil_patch.Image.Image
-except:
-    Image = FakeObject  # analysis:ignore
-
-
-#==============================================================================
-# BeautifulSoup support (see Issue 2448)
-#==============================================================================
-try:
-    import bs4
-    NavigableString = bs4.element.NavigableString
-except:
-    NavigableString = FakeObject  # analysis:ignore
-
-
-#==============================================================================
 # Misc.
 #==============================================================================
 def address(obj):
@@ -133,7 +85,8 @@
 def get_size(item):
     """Return shape/size/len of an item of arbitrary type"""
     try:
-        if hasattr(item, 'shape') and isinstance(item.shape, (tuple, integer)):
+        if (hasattr(item, 'shape') and
+                isinstance(item.shape, (tuple, np.integer))):
             try:
                 if item.shape:
                     return item.shape
@@ -145,7 +98,8 @@
                 # get the shape of these objects.
                 # Fixes spyder-ide/spyder-kernels#217
                 return (-1, -1)
-        elif hasattr(item, 'size') and isinstance(item.size, (tuple, integer)):
+        elif (hasattr(item, 'size') and
+                isinstance(item.size, (tuple, np.integer))):
             try:
                 return item.size
             except RecursionError:
@@ -176,7 +130,6 @@
 #==============================================================================
 import datetime
 
-
 try:
     from dateutil.parser import parse as dateparse
 except:
@@ -239,7 +192,7 @@
         ]
 
         if (get_type_string(value) not in supported_types and
-                not isinstance(value, Index)):
+                not isinstance(value, pd.Index)):
             np_dtype = get_numpy_dtype(value)
             if np_dtype is None or not hasattr(value, 'size'):
                 return False
@@ -350,33 +303,34 @@
     """Convert value for display purpose"""
     # To save current Numpy printoptions
     np_printoptions = FakeObject
+    numeric_numpy_types = get_numeric_numpy_types()
 
     try:
-        if ndarray is not FakeObject:
+        if np.ndarray is not FakeObject:
             # Save printoptions
-            np_printoptions = get_printoptions()
+            np_printoptions = np.get_printoptions()
             # Set max number of elements to show for Numpy arrays
             # in our display
-            set_printoptions(threshold=10)
-        if isinstance(value, recarray):
+            np.set_printoptions(threshold=10)
+        if isinstance(value, np.recarray):
             if level == 0:
                 fields = value.names
                 display = 'Field names: ' + ', '.join(fields)
             else:
                 display = 'Recarray'
-        elif isinstance(value, MaskedArray):
+        elif isinstance(value, np.ma.MaskedArray):
             display = 'Masked array'
-        elif isinstance(value, ndarray):
+        elif isinstance(value, np.ndarray):
             if level == 0:
                 if minmax:
                     try:
                         display = 'Min: %r\nMax: %r' % (value.min(), 
value.max())
                     except (TypeError, ValueError):
-                        if value.dtype.type in NUMERIC_NUMPY_TYPES:
+                        if value.dtype.type in numeric_numpy_types:
                             display = str(value)
                         else:
                             display = default_display(value)
-                elif value.dtype.type in NUMERIC_NUMPY_TYPES:
+                elif value.dtype.type in numeric_numpy_types:
                     display = str(value)
                 else:
                     display = default_display(value)
@@ -384,12 +338,12 @@
                 display = 'Numpy array'
         elif any([type(value) == t for t in [list, set, tuple, dict]]):
             display = collections_display(value, level+1)
-        elif isinstance(value, Image):
+        elif isinstance(value, PIL.Image.Image):
             if level == 0:
                 display = '%s  Mode: %s' % (address(value), value.mode)
             else:
                 display = 'Image'
-        elif isinstance(value, DataFrame):
+        elif isinstance(value, pd.DataFrame):
             if level == 0:
                 cols = value.columns
                 if PY2 and len(cols) > 0:
@@ -408,12 +362,12 @@
                 display = 'Column names: ' + ', '.join(list(cols))
             else:
                 display = 'Dataframe'
-        elif isinstance(value, NavigableString):
+        elif isinstance(value, bs4.element.NavigableString):
             # Fixes Issue 2448
             display = to_text_string(value)
             if level > 0:
                 display = u"'" + display + u"'"
-        elif isinstance(value, Index):
+        elif isinstance(value, pd.Index):
             if level == 0:
                 try:
                     display = value._summary()
@@ -449,14 +403,14 @@
             display = str(value)
         elif (isinstance(value, NUMERIC_TYPES) or
               isinstance(value, bool) or
-              isinstance(value, NUMERIC_NUMPY_TYPES)):
+              isinstance(value, numeric_numpy_types)):
             display = repr(value)
         else:
             if level == 0:
                 display = default_display(value)
             else:
                 display = default_display(value, with_module=False)
-    except:
+    except Exception:
         display = default_display(value)
 
     # Truncate display at 70 chars to avoid freezing Spyder
@@ -470,7 +424,7 @@
 
     # Restore Numpy printoptions
     if np_printoptions is not FakeObject:
-        set_printoptions(**np_printoptions)
+        np.set_printoptions(**np_printoptions)
 
     return display
 
@@ -530,19 +484,19 @@
 def get_type_string(item):
     """Return type string of an object."""
     # Numpy objects (don't change the order!)
-    if isinstance(item, MaskedArray):
+    if isinstance(item, np.ma.MaskedArray):
         return "MaskedArray"
-    if isinstance(item, matrix):
+    if isinstance(item, np.matrix):
         return "Matrix"
-    if isinstance(item, ndarray):
+    if isinstance(item, np.ndarray):
         return "NDArray"
 
     # Pandas objects
-    if isinstance(item, DataFrame):
+    if isinstance(item, pd.DataFrame):
         return "DataFrame"
-    if isinstance(item, Index):
+    if isinstance(item, pd.Index):
         return type(item).__name__
-    if isinstance(item, Series):
+    if isinstance(item, pd.Series):
         return "Series"
 
     found = re.findall(r"<(?:type|class) '(\S*)'>",
@@ -558,14 +512,15 @@
 def is_known_type(item):
     """Return True if object has a known type"""
     # Unfortunately, the masked array case is specific
-    return isinstance(item, MaskedArray) or get_type_string(item) != 'Unknown'
+    return (isinstance(item, np.ma.MaskedArray) or
+            get_type_string(item) != 'Unknown')
 
 
 def get_human_readable_type(item):
     """Return human-readable type string of an item"""
-    if isinstance(item, (ndarray, MaskedArray)):
+    if isinstance(item, (np.ndarray, np.ma.MaskedArray)):
         return u'Array of ' + item.dtype.name
-    elif isinstance(item, Image):
+    elif isinstance(item, PIL.Image.Image):
         return "Image"
     else:
         text = get_type_string(item)
@@ -671,7 +626,7 @@
         pass
     picklable_types = editable_types[:]
     try:
-        from spyder.pil_patch import Image
+        from PIL import Image
         editable_types.append(Image.Image)
     except:
         pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/spyder-kernels-2.0.4/spyder_kernels/utils/tests/test_lazymodules.py 
new/spyder-kernels-2.1.0/spyder_kernels/utils/tests/test_lazymodules.py
--- old/spyder-kernels-2.0.4/spyder_kernels/utils/tests/test_lazymodules.py     
1970-01-01 01:00:00.000000000 +0100
+++ new/spyder-kernels-2.1.0/spyder_kernels/utils/tests/test_lazymodules.py     
2021-07-31 20:21:53.000000000 +0200
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# -----------------------------------------------------------------------------
+# Copyright (c) 2009- Spyder Kernels Contributors
+#
+# Licensed under the terms of the MIT License
+# (see spyder_kernels/__init__.py for details)
+# -----------------------------------------------------------------------------
+
+import pytest
+
+from spyder_kernels.utils.lazymodules import LazyModule, FakeObject
+
+
+def test_non_existent_module():
+    """Test that we retun FakeObject's for non-existing modules."""
+    mod = LazyModule('no_module', second_level_attrs=['a'])
+
+    # First level attributes must return FakeObject
+    assert mod.foo is FakeObject
+
+    # Second level attributes in second_level_attrs should return
+    # FakeObject too.
+    assert mod.foo.a is FakeObject
+
+    # Other second level attributes should raise an error.
+    with pytest.raises(AttributeError):
+        mod.foo.b
+
+
+def test_existing_modules():
+    """Test that lazy modules work for existing modules."""
+    np = LazyModule('numpy')
+    import numpy
+
+    # Both the lazy and actual modules should return the same.
+    assert np.ndarray == numpy.ndarray
+
+    # The lazy module should have these extra attributes
+    assert np.__spy_mod__
+    assert np.__spy_modname__

Reply via email to