From 4db6cd0c78cf2c8c147ffa6bd3786f8e027bb2ce Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sun, 28 Aug 2022 10:16:33 -0500 Subject: [PATCH] git subrepo pull external-deps/qtconsole subrepo: subdir: "external-deps/qtconsole" merged: "be40bce4c" upstream: origin: "https://github.com/jupyter/qtconsole.git" branch: "master" commit: "be40bce4c" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo" commit: "2f68596" --- .../.github/workflows/linux-tests.yml | 6 ++- .../.github/workflows/macos-tests.yml | 8 ++- .../.github/workflows/windows-tests.yml | 8 ++- external-deps/qtconsole/.gitrepo | 4 +- .../qtconsole/docs/source/changelog.rst | 18 +++++++ .../qtconsole/qtconsole/console_widget.py | 20 ++++--- .../qtconsole/qtconsole/frontend_widget.py | 6 ++- .../qtconsole/qtconsole/mainwindow.py | 9 ++-- .../qtconsole/tests/test_00_console_widget.py | 52 +++++++++++++++++++ .../qtconsole/tests/test_jupyter_widget.py | 24 +++++++-- .../qtconsole/scripts/jupyter-qtconsole | 5 -- external-deps/qtconsole/setup.py | 4 +- 12 files changed, 127 insertions(+), 37 deletions(-) delete mode 100755 external-deps/qtconsole/scripts/jupyter-qtconsole diff --git a/external-deps/qtconsole/.github/workflows/linux-tests.yml b/external-deps/qtconsole/.github/workflows/linux-tests.yml index 2885ef86e1f..5da008d34c4 100644 --- a/external-deps/qtconsole/.github/workflows/linux-tests.yml +++ b/external-deps/qtconsole/.github/workflows/linux-tests.yml @@ -27,6 +27,7 @@ jobs: exclude: - INSTALL_TYPE: 'conda' QT_LIB: 'pyqt6' + timeout-minutes: 15 steps: - name: Checkout branch uses: actions/checkout@v3 @@ -42,11 +43,12 @@ jobs: auto-activate-base: false channels: conda-forge channel-priority: strict + miniforge-variant: Mambaforge python-version: ${{ matrix.PYTHON_VERSION }} - name: Install dependencies with conda if: matrix.INSTALL_TYPE == 'conda' shell: bash -l {0} - run: conda env update --file requirements/environment.yml + run: mamba env update --file requirements/environment.yml - name: Install dependencies with pip if: matrix.INSTALL_TYPE == 'pip' shell: bash -l {0} @@ -61,7 +63,7 @@ jobs: pip list - name: Run tests shell: bash -l {0} - run: xvfb-run --auto-servernum pytest -x -vv -s --full-trace --cov=qtconsole qtconsole + run: xvfb-run --auto-servernum pytest -x -vv -s --full-trace --color=yes --cov=qtconsole qtconsole env: QT_API: ${{ matrix.QT_LIB }} PYTEST_QT_API: ${{ matrix.QT_LIB }} diff --git a/external-deps/qtconsole/.github/workflows/macos-tests.yml b/external-deps/qtconsole/.github/workflows/macos-tests.yml index 4852ce83545..f8a0c51439f 100644 --- a/external-deps/qtconsole/.github/workflows/macos-tests.yml +++ b/external-deps/qtconsole/.github/workflows/macos-tests.yml @@ -20,6 +20,7 @@ jobs: fail-fast: false matrix: PYTHON_VERSION: ['3.7', '3.8', '3.9', '3.10'] + timeout-minutes: 15 steps: - name: Checkout branch uses: actions/checkout@v3 @@ -30,9 +31,12 @@ jobs: auto-update-conda: false auto-activate-base: false python-version: ${{ matrix.PYTHON_VERSION }} + miniforge-variant: Mambaforge + channels: conda-forge + channel-priority: strict - name: Install package dependencies shell: bash -l {0} - run: conda env update --file requirements/environment.yml + run: mamba env update --file requirements/environment.yml - name: Show environment information shell: bash -l {0} run: | @@ -40,4 +44,4 @@ jobs: conda list - name: Run tests shell: bash -l {0} - run: pytest -x -vv --cov=qtconsole qtconsole + run: pytest -x -vv --color=yes --cov=qtconsole qtconsole diff --git a/external-deps/qtconsole/.github/workflows/windows-tests.yml b/external-deps/qtconsole/.github/workflows/windows-tests.yml index 3ddc2b6c481..b58f19875cf 100644 --- a/external-deps/qtconsole/.github/workflows/windows-tests.yml +++ b/external-deps/qtconsole/.github/workflows/windows-tests.yml @@ -20,6 +20,7 @@ jobs: fail-fast: false matrix: PYTHON_VERSION: ['3.7', '3.8', '3.9', '3.10'] + timeout-minutes: 15 steps: - name: Checkout branch uses: actions/checkout@v3 @@ -30,9 +31,12 @@ jobs: auto-update-conda: false auto-activate-base: false python-version: ${{ matrix.PYTHON_VERSION }} + miniforge-variant: Mambaforge + channels: conda-forge + channel-priority: strict - name: Install package dependencies shell: bash -l {0} - run: conda env update --file requirements/environment.yml + run: mamba env update --file requirements/environment.yml - name: Show environment information shell: bash -l {0} run: | @@ -40,4 +44,4 @@ jobs: conda list - name: Run tests shell: bash -l {0} - run: pytest -x -vv --cov=qtconsole qtconsole + run: pytest -x -vv --color=yes --cov=qtconsole qtconsole diff --git a/external-deps/qtconsole/.gitrepo b/external-deps/qtconsole/.gitrepo index 6b702b27d0b..02c69eb3a1b 100644 --- a/external-deps/qtconsole/.gitrepo +++ b/external-deps/qtconsole/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/jupyter/qtconsole.git branch = master - commit = 3d29df8adc23ab8ab6c20b870c369806339ee342 - parent = ba96ec79f4a35e749bd9f6d331898dc2f1748a53 + commit = be40bce4ce01d282a69fe6071e155df66ae4b41b + parent = 4ed1cbe3fcbe0fc224b167e17b4201f61cbdba27 method = merge cmdver = 0.4.3 diff --git a/external-deps/qtconsole/docs/source/changelog.rst b/external-deps/qtconsole/docs/source/changelog.rst index 078ff3ad952..dd81fb5ab89 100644 --- a/external-deps/qtconsole/docs/source/changelog.rst +++ b/external-deps/qtconsole/docs/source/changelog.rst @@ -8,6 +8,24 @@ Changes in Jupyter Qt console 5.3 ~~~ +5.3.2 +----- + +`5.3.2 on GitHub `__ + +* Fix syntax highlighting with multiline inputs. +* Don't call processEvents when showing input prompts on Mac because it's not + necessary. + +5.3.1 +----- + +`5.3.1 on GitHub `__ + +* Fix segfault when performing code completion on Qt6. +* Fix mixed input and print statements. +* Fix switching syntax highlighting styles on PySide2 and PySide6. + 5.3.0 ----- diff --git a/external-deps/qtconsole/qtconsole/console_widget.py b/external-deps/qtconsole/qtconsole/console_widget.py index e2dad3595cb..3652ea76a66 100644 --- a/external-deps/qtconsole/qtconsole/console_widget.py +++ b/external-deps/qtconsole/qtconsole/console_widget.py @@ -1692,15 +1692,6 @@ def _format_as_columns(self, items, separator=' '): return columnize(items, separator, displaywidth) - def _get_block_plain_text(self, block): - """ Given a QTextBlock, return its unformatted text. - """ - cursor = QtGui.QTextCursor(block) - cursor.movePosition(QtGui.QTextCursor.StartOfBlock) - cursor.movePosition(QtGui.QTextCursor.EndOfBlock, - QtGui.QTextCursor.KeepAnchor) - return cursor.selection().toPlainText() - def _get_cursor(self): """ Get a cursor at the current insert position. """ @@ -1768,7 +1759,7 @@ def _get_input_buffer_cursor_line(self): return None else: cursor = self._control.textCursor() - text = self._get_block_plain_text(cursor.block()) + text = cursor.block().text() return text[len(prompt):] def _get_input_buffer_cursor_pos(self): @@ -2428,7 +2419,6 @@ def _readline(self, prompt='', callback=None, password=False): while self._reading: QtCore.QCoreApplication.processEvents() return self._get_input_buffer(force=True).rstrip('\n') - else: self._reading_callback = lambda: \ callback(self._get_input_buffer(force=True).rstrip('\n')) @@ -2489,6 +2479,13 @@ def _show_prompt(self, prompt=None, html=False, newline=True, If set, a separator will be written before the prompt. """ self._flush_pending_stream() + + # This is necessary to solve out-of-order insertion of mixed stdin and + # stdout stream texts. + # Fixes spyder-ide/spyder#17710 + if not sys.platform == 'darwin': + QtCore.QCoreApplication.processEvents() + cursor = self._get_end_cursor() # Save the current position to support _append*(before_prompt=True). @@ -2513,6 +2510,7 @@ def _show_prompt(self, prompt=None, html=False, newline=True, # Write the prompt. if separator: self._append_plain_text(self._prompt_sep) + if prompt is None: if self._prompt_html is None: self._append_plain_text(self._prompt) diff --git a/external-deps/qtconsole/qtconsole/frontend_widget.py b/external-deps/qtconsole/qtconsole/frontend_widget.py index 676022a3ae8..ac6cf575f01 100644 --- a/external-deps/qtconsole/qtconsole/frontend_widget.py +++ b/external-deps/qtconsole/qtconsole/frontend_widget.py @@ -67,7 +67,11 @@ def highlightBlock(self, string): # paragraph break characters, non-breaking spaces, etc. Here we acquire # the string as plain text so we can compare it. current_block = self.currentBlock() - string = self._frontend._get_block_plain_text(current_block) + string = current_block.text() + + # QTextBlock::text() can still return non-breaking spaces + # for the continuation prompt + string = string.replace("\xa0", " ") # Only highlight if we can identify a prompt, but make sure not to # highlight the prompt. diff --git a/external-deps/qtconsole/qtconsole/mainwindow.py b/external-deps/qtconsole/qtconsole/mainwindow.py index 2fcb28ce37f..b5b0476a99c 100644 --- a/external-deps/qtconsole/qtconsole/mainwindow.py +++ b/external-deps/qtconsole/qtconsole/mainwindow.py @@ -8,6 +8,7 @@ # Distributed under the terms of the Modified BSD License. import sys import webbrowser +from functools import partial from threading import Thread from jupyter_core.paths import jupyter_runtime_dir @@ -625,11 +626,9 @@ def init_view_menu(self): self.syntax_style_menu = self.view_menu.addMenu("&Syntax Style") style_group = QtWidgets.QActionGroup(self) for style in available_syntax_styles: - action = QtWidgets.QAction("{}".format(style), self, - triggered=lambda v, - syntax_style=style: - self.set_syntax_style( - syntax_style=syntax_style)) + action = QtWidgets.QAction("{}".format(style), self) + action.triggered.connect(partial(self.set_syntax_style, + style)) action.setCheckable(True) style_group.addAction(action) self.syntax_style_menu.addAction(action) diff --git a/external-deps/qtconsole/qtconsole/tests/test_00_console_widget.py b/external-deps/qtconsole/qtconsole/tests/test_00_console_widget.py index d07588d5306..f98dfb9f53d 100644 --- a/external-deps/qtconsole/qtconsole/tests/test_00_console_widget.py +++ b/external-deps/qtconsole/qtconsole/tests/test_00_console_widget.py @@ -207,6 +207,58 @@ def test_debug(qtconsole, qtbot): assert control.toPlainText().strip().split()[-1] == "abcd" +@flaky(max_runs=15) +def test_input_and_print(qtconsole, qtbot): + """ + Test that we print correctly mixed input and print statements. + + This is a regression test for spyder-ide/spyder#17710. + """ + window = qtconsole.window + shell = window.active_frontend + control = shell._control + + def wait_for_input(): + qtbot.waitUntil( + lambda: control.toPlainText().splitlines()[-1] == 'Write input: ' + ) + + # Wait until the console is fully up + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + + # Run a for loop with mixed input and print statements + code = """ +user_input = None +while user_input != '': + user_input = input('Write input: ') + print('Input was entered!') +""" + shell.execute(code) + wait_for_input() + + # Interact with the 'for' loop for a certain number of repetitions + repetitions = 3 + for _ in range(repetitions): + qtbot.keyClicks(control, '1') + qtbot.keyClick(control, QtCore.Qt.Key_Enter) + wait_for_input() + + # Get out of the for loop + qtbot.keyClick(control, QtCore.Qt.Key_Enter) + qtbot.waitUntil(lambda: not shell._reading) + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + + # Assert that printed correctly the expected output in the console. + output = ( + " ...: \n" + + "Write input: 1\nInput was entered!\n" * repetitions + + "Write input: \nInput was entered!\n" + ) + assert output in control.toPlainText() + + @pytest.mark.skipif(no_display, reason="Doesn't work without a display") class TestConsoleWidget(unittest.TestCase): diff --git a/external-deps/qtconsole/qtconsole/tests/test_jupyter_widget.py b/external-deps/qtconsole/qtconsole/tests/test_jupyter_widget.py index 50a0027701a..f9998ea792f 100644 --- a/external-deps/qtconsole/qtconsole/tests/test_jupyter_widget.py +++ b/external-deps/qtconsole/qtconsole/tests/test_jupyter_widget.py @@ -1,8 +1,9 @@ import unittest import sys +from packaging.version import parse import pytest -from qtpy import QT6 +from qtpy import QT6, QT_VERSION from qtpy import QtWidgets, QtGui from qtpy.QtTest import QTest @@ -52,8 +53,6 @@ def test_other_output(self): w._show_interpreter_prompt(1) w.other_output_prefix = '[other] ' w.syntax_style = 'default' - control = w._control - document = control.document() msg = dict( execution_count=1, @@ -61,6 +60,9 @@ def test_other_output(self): ) w._append_custom(w._insert_other_input, msg, before_prompt=True) + control = w._control + document = control.document() + self.assertEqual(document.blockCount(), 6) self.assertEqual(document.toPlainText(), ( 'Header\n' @@ -72,7 +74,21 @@ def test_other_output(self): )) # Check proper syntax highlighting - if QT6: + if QT6 and parse(QT_VERSION) >= parse('6.3'): + html = ( + '\n' + '\n' + '

Header

\n' + '


\n' + '

[other] In [1]: a = 1 + 1

\n' + '

\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0...: b = range(10)

\n' + '


\n' + '

In [2]:

' + ) + elif QT6 and parse(QT_VERSION) < parse('6.3'): html = ( '\n' '