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__