Repository: spyder-ide/spyder

Issue:
autopep8 formatting tests failing
<!--- **PLEASE READ:** When submitting here, please ensure you've completed the following checklist and checked the boxes to confirm. Issue reports without it may be closed. Thanks! --->

### Issue Report Checklist

* [x] Searched the [issues page](https://github.com/spyder-ide/spyder/issues?q=is%3Aissue) for similar reports
* [x] Read the relevant sections of the [Spyder Troubleshooting Guide](https://github.com/spyder-ide/spyder/wiki/Troubleshooting-Guide-and-FAQ) and followed its advice
* [x] Reproduced the issue after updating with ``conda update spyder`` (or ``pip``, if not using Anaconda)
* [ ] Could not reproduce inside ``jupyter qtconsole`` (if console-related)
* [x] Tried basic troubleshooting (if a bug/error)
    * [ ] Restarted Spyder
    * [ ] Reset preferences with ``spyder --reset``
    * [ ] Reinstalled the latest version of [Anaconda](https://www.anaconda.com/download/)
    * [ ] Tried the other applicable steps from the Troubleshooting Guide
* [x] Completed the **Problem Description**, **Steps to Reproduce** and **Version** sections below

## Problem Description

I forgot to add `--run-slow` to the test run earlier.  Just tried it now, and unfortunately some more tests are failing.  Here's the first report - there will unfortunately be others too :-(

### What steps reproduce the problem?

```
(sid-minimal)jdg@euler:/build/spyder-jdg/build-area/spyder-5.2.1+dfsg1$ debian/tests/pytest --run-slow
Testing with python3.10:
Temporary home directory: /tmp/tmp.52uXeW2cAC
Pytest Arguments: ['-vv', '-rw', '--durations=10', '-W ignore::UserWarning', '-x', '--cov=spyder', '--no-cov-on-fail', '--run-slow', '-k', 'not test_get_pydoc and not test_qtbug35861 and not test_run_python_script_in_terminal and not test_run_python_script_in_terminal_blank_wdir and not test_run_python_script_in_terminal_with_wdir_empty and not test_find_external_plugins and not test_load_time and not test_objectexplorer_collection_types and not test_pylint.py and not test_object_arrays_display and not test_profiler_config_dialog.py and not test_handle_exception']
============================= test session starts ==============================
platform linux -- Python 3.10.1, pytest-6.2.5, py-1.10.0, pluggy-0.13.0 -- /usr/bin/python3.10
cachedir: .pytest_cache
PyQt5 5.15.6 -- Qt runtime 5.15.2 -- Qt compiled 5.15.2
rootdir: /build/spyder-jdg/build-area/spyder-5.2.1+dfsg1, configfile: pytest.ini
plugins: flaky-3.7.0, xvfb-2.0.0, mock-3.6.1, cov-3.0.0, order-1.0.0, qt-4.0.2, lazy-fixture-0.6.3
collected 1193 items / 39 deselected / 2 skipped / 1152 selected               

spyder/app/tests/test_cli_options.py::test_get_options SKIPPED (Don'...) [  0%]
[... snipped ...]
spyder/plugins/editor/widgets/tests/test_formatting.py::test_document_formatting[autopep8] FAILED [  1%]

=================================== FAILURES ===================================
______________________ test_document_formatting[autopep8] ______________________

formatter = 'autopep8'
completions_codeeditor = (<spyder.plugins.editor.widgets.codeeditor.CodeEditor object at 0x7f23a025dcf0>, <spyder.plugins.completion.plugin.CompletionPlugin object at 0x7f23a012d7e0>)
qtbot = <pytestqt.qtbot.QtBot object at 0x7f238418bfa0>

    @pytest.mark.slow
    @pytest.mark.order(1)
    @pytest.mark.parametrize('formatter', [autopep8, 'yapf', 'black'])
    def test_document_formatting(formatter, completions_codeeditor, qtbot):
        """Validate text autoformatting via autopep8, yapf or black."""
        code_editor, completion_plugin = completions_codeeditor
        text, expected = get_formatter_values(formatter)
    
        # After this call the manager needs to be reinitialized
        CONF.set('completions',
                 ('provider_configuration', 'lsp', 'values','formatting'),
                 formatter)
        qtbot.wait(2000)
    
        # Set text in editor
        code_editor.set_text(text)
    
        # Notify changes
        with qtbot.waitSignal(
                code_editor.completions_response_signal, timeout=30000):
            code_editor.document_did_change()
    
        # Perform formatting
        with qtbot.waitSignal(
                code_editor.completions_response_signal, timeout=30000):
            code_editor.format_document()
    
        # Wait to text to be formatted
        qtbot.wait(2000)
    
>       assert code_editor.toPlainText() == expected
E       assert ('# -*- coding: utf-8 -*-\n'\n '"""\n'\n 'Spyder Editor\n'\n '\n'\n 'This is a temporary script file.\n'\n '"""\n'\n '\n'\n 'import os\n'\n 'import sys\n'\n '\n'\n '\n'\n '# %% functions\n'\n 'def d():\n'\n '    def inner():\n'\n '        return 2\n'\n '\n'\n '    return inner\n'\n '\n'\n '\n'\n '# ---- func 1 and 2\n'\n 'def func1():\n'\n '    for i in range(3):\n'\n '        print(i)\n'\n '\n'\n '\n'\n 'def func2():\n'\n '    if True:\n'\n '        pass\n'\n '\n'\n '\n'\n '# ---- other functions\n'\n 'def a():\n'\n '    pass\n'\n '\n'\n '\n'\n 'def b():\n'\n '    pass\n'\n '\n'\n '\n'\n 'def c():\n'\n '    pass\n'\n '\n'\n '\n'\n '# %% classes\n'\n 'class Class1:\n'\n '    def __init__(self):\n'\n '        super(Class1, self).__init__()\n'\n '        self.x = 2\n'\n '\n'\n '    def method3(self):\n'\n '        pass\n'\n '\n'\n '    def method2(self):\n'\n '        pass\n'\n '\n'\n '    def method1(self):\n'\n '        pass\n') == ('# -*- coding: utf-8 -*-\n'\n '"""\n'\n 'Spyder Editor\n'\n '\n'\n 'This is a temporary script file.\n'\n '"""\n'\n '\n'\n 'import os\n'\n 'import sys\n'\n '\n'\n '\n'\n '# %% functions\n'\n 'def d():\n'\n '    def inner(): return 2\n'\n '    return inner\n'\n '# ---- func 1 and 2\n'\n '\n'\n '\n'\n 'def func1():\n'\n '    for i in range(3):\n'\n '        print(i)\n'\n '\n'\n '\n'\n 'def func2():\n'\n '    if True:\n'\n '        pass\n'\n '# ---- other functions\n'\n '\n'\n '\n'\n 'def a():\n'\n '    pass\n'\n '\n'\n '\n'\n 'def b():\n'\n '    pass\n'\n '\n'\n '\n'\n 'def c():\n'\n '    pass\n'\n '\n'\n '\n'\n '# %% classes\n'\n 'class Class1:\n'\n '    def __init__(self):\n'\n '        super(Class1, self).__init__()\n'\n '        self.x = 2\n'\n '\n'\n '    def method3(self):\n'\n '        pass\n'\n '\n'\n '    def method2(self):\n'\n '        pass\n'\n '\n'\n '    def method1(self):\n'\n '        pass\n')
E           # -*- coding: utf-8 -*-
E           """
E           Spyder Editor
E           
E           This is a temporary script file.
E           """
E           
E           import os
E           import sys
E           
E           
E           # %% functions
E           def d():
E         -     def inner(): return 2
E         ?                 ---------
E         +     def inner():
E         +         return 2
E         + 
E               return inner
E         - # ---- func 1 and 2
E           
E           
E         + # ---- func 1 and 2
E           def func1():
E               for i in range(3):
E                   print(i)
E           
E           
E           def func2():
E               if True:
E                   pass
E         - # ---- other functions
E           
E           
E         + # ---- other functions
E           def a():
E               pass
E           
E           
E           def b():
E               pass
E           
E           
E           def c():
E               pass
E           
E           
E           # %% classes
E           class Class1:
E               def __init__(self):
E                   super(Class1, self).__init__()
E                   self.x = 2
E           
E               def method3(self):
E                   pass
E           
E               def method2(self):
E                   pass
E           
E               def method1(self):
E                   pass

/build/spyder-jdg/build-area/spyder-5.2.1+dfsg1/spyder/plugins/editor/widgets/tests/test_formatting.py:79: AssertionError
=============================== warnings summary ===============================
[... rest of output snipped ...]
```
And when I remove `autopep8` from the list of formatters in this test, the following test fails similarly:
```
spyder/plugins/editor/widgets/tests/test_formatting.py::test_document_range_formatting[autopep8] FAILED [  1%]

=================================== FAILURES ===================================
___________________ test_document_range_formatting[autopep8] ___________________

formatter = 'autopep8'
completions_codeeditor = (<spyder.plugins.editor.widgets.codeeditor.CodeEditor object at 0x7fb7ec1591b0>, <spyder.plugins.completion.plugin.CompletionPlugin object at 0x7fb7ec1649d0>)
qtbot = <pytestqt.qtbot.QtBot object at 0x7fb8500f6b90>

    @pytest.mark.slow
    @pytest.mark.order(1)
    @pytest.mark.parametrize(
        'formatter', [autopep8, 'yapf', 'black'])
    def test_document_range_formatting(formatter, completions_codeeditor, qtbot):
        """Validate text range autoformatting."""
        code_editor, completion_plugin = completions_codeeditor
        text, expected = get_formatter_values(formatter, range_fmt=True)
    
        # After this call the manager needs to be reinitialized
        CONF.set('completions',
                 ('provider_configuration', 'lsp', 'values','formatting'),
                 formatter)
        completion_plugin.after_configuration_update([])
        qtbot.wait(2000)
    
        # Set text in editor
        code_editor.set_text(text)
    
        # Notify changes
        with qtbot.waitSignal(
                code_editor.completions_response_signal, timeout=30000):
            code_editor.document_did_change()
    
        # Select region to format
        code_editor.go_to_line(12)
        cursor = code_editor.textCursor()
        start = code_editor.get_position_line_number(11, -1)
        end = code_editor.get_position_line_number(27, 0)
        cursor.setPosition(start)
        cursor.setPosition(end, QTextCursor.KeepAnchor)
        cursor.movePosition(QTextCursor.EndOfBlock,
                            QTextCursor.KeepAnchor)
        code_editor.setTextCursor(cursor)
    
        # Perform formatting
        with qtbot.waitSignal(
                code_editor.completions_response_signal, timeout=30000):
            code_editor.format_document_range()
    
        # Wait to text to be formatted
        qtbot.wait(2000)
>       assert code_editor.toPlainText() == expected
E       assert ('# -*- coding: utf-8 -*-\n'\n '"""\n'\n 'Spyder Editor\n'\n '\n'\n 'This is a temporary script file.\n'\n '"""\n'\n '\n'\n 'import os;import sys\n'\n '\n'\n '\n'\n '# %% functions\n'\n 'def d():\n'\n '    def inner():\n'\n '        return 2\n'\n '\n'\n '    return inner\n'\n '\n'\n '\n'\n '# ---- func 1 and 2\n'\n 'def func1():\n'\n '    for i in range(3):\n'\n '        print(i)\n'\n '\n'\n '\n'\n 'def func2():\n'\n '    if True:\n'\n '        pass\n'\n '\n'\n '\n'\n '# ---- other functions\n'\n 'def a():\n'\n '    pass\n'\n '\n'\n '\n'\n 'def b():\n'\n '    pass\n'\n '\n'\n '\n'\n 'def c():\n'\n '    pass\n'\n '\n'\n '\n'\n '# %% classes\n'\n 'class Class1:\n'\n '    def __init__(self):\n'\n '        super(Class1, self).__init__()\n'\n '        self.x = 2\n'\n '\n'\n '    def method3(self):\n'\n '        pass\n'\n '\n'\n '    def method2(self):\n'\n '        pass\n'\n '\n'\n '    def method1(self):\n'\n '        pass\n') == ('# -*- coding: utf-8 -*-\n'\n '"""\n'\n 'Spyder Editor\n'\n '\n'\n 'This is a temporary script file.\n'\n '"""\n'\n '\n'\n 'import os;import sys\n'\n '\n'\n '\n'\n '# %% functions\n'\n 'def d():\n'\n '    def inner(): return 2\n'\n '    return inner\n'\n '# ---- func 1 and 2\n'\n '\n'\n '\n'\n 'def func1():\n'\n '    for i in range(3):\n'\n '        print(i)\n'\n '\n'\n '\n'\n 'def func2():\n'\n '    if True:\n'\n '        pass\n'\n '# ---- other functions\n'\n '\n'\n '\n'\n 'def a():\n'\n '    pass\n'\n '\n'\n '\n'\n 'def b():\n'\n '    pass\n'\n '\n'\n '\n'\n 'def c():\n'\n '    pass\n'\n '\n'\n '\n'\n '# %% classes\n'\n 'class Class1:\n'\n '    def __init__(self):\n'\n '        super(Class1, self).__init__()\n'\n '        self.x = 2\n'\n '\n'\n '    def method3(self):\n'\n '        pass\n'\n '\n'\n '    def method2(self):\n'\n '        pass\n'\n '\n'\n '    def method1(self):\n'\n '        pass\n')
E           # -*- coding: utf-8 -*-
E           """
E           Spyder Editor
E           
E           This is a temporary script file.
E           """
E           
E           import os;import sys
E           
E           
E           # %% functions
E           def d():
E         -     def inner(): return 2
E         ?                 ---------
E         +     def inner():
E         +         return 2
E         + 
E               return inner
E         - # ---- func 1 and 2
E           
E           
E         + # ---- func 1 and 2
E           def func1():
E               for i in range(3):
E                   print(i)
E           
E           
E           def func2():
E               if True:
E                   pass
E         - # ---- other functions
E           
E           
E         + # ---- other functions
E           def a():
E               pass
E           
E           
E           def b():
E               pass
E           
E           
E           def c():
E               pass
E           
E           
E           # %% classes
E           class Class1:
E               def __init__(self):
E                   super(Class1, self).__init__()
E                   self.x = 2
E           
E               def method3(self):
E                   pass
E           
E               def method2(self):
E                   pass
E           
E               def method1(self):
E                   pass

/build/spyder-jdg/build-area/spyder-5.2.1+dfsg1/spyder/plugins/editor/widgets/tests/test_formatting.py:124: AssertionError
=============================== warnings summary ===============================
```
This is quite bizarre, as running the command-line program `autopep8` on the `assets/original_file.py` produces exactly the output expected in `assets/autopep8_results.py`.  It looks as though there may be some `autopep8` option that is being invoked to produce this new behaviour, or maybe the file is being reformatted somehow as it is being entered into the code editor, but both of those seem quite unlikely.  I'm using `autopep8` version 1.6.0.  It sort of looks as if the formatter being used for this test is not actually `autopep8`; the output appears to be like that of `yapf` or `black`.

## Versions
<!--- You can get this information from Help > About Spyder...
or (if Spyder won't launch) the "conda list" command
from the Anaconda Prompt/Terminal/command line. --->

* Spyder version: 5.2.1
* Python version: 3.9 and 3.10
* Qt version: 5.15.2
* PyQt version: 5.15.6+dfsg-1+b1
* Operating System name/version: Debian testing and unstable

### Dependencies
<!--- Please go to the menu entry Help > Dependencies,
press the Copy to clipboard button and paste below --->

```
# Mandatory:
atomicwrites >=1.2.0          :  1.4.0 (OK)
chardet >=2.0.0               :  4.0.0 (OK)
cloudpickle >=0.5.0           :  2.0.0 (OK)
cookiecutter >=1.6.0          :  1.7.3 (OK)
diff_match_patch >=20181111   :  20200713 (OK)
intervaltree >=3.0.2          :  3.0.2 (OK)
IPython >=7.6.0               :  7.27.0 (OK)
jedi >=0.17.2;<0.19.0         :  0.18.0 (OK)
jellyfish >=0.7               :  0.8.9 (OK)
jsonschema >=3.2.0            :  3.2.0 (OK)
keyring >=17.0.0              :  23.3.0 (OK)
nbconvert >=4.0               :  6.1.0 (OK)
numpydoc >=0.6.0              :  1.1.0 (OK)
parso >=0.7.0;<0.9.0          :  0.8.1 (OK)
pexpect >=4.4.0               :  4.8.0 (OK)
pickleshare >=0.4             :  0.7.5 (OK)
psutil >=5.3                  :  5.8.0 (OK)
pygments >=2.0                :  2.7.1 (OK)
pylint >=2.5.0                :  2.12.2 (OK)
pyls_spyder >=0.4.0           :  0.4.0 (OK)
pylsp >=1.3.2;<1.4.0          :  1.3.3 (OK)
pylsp_black >=1.0.0           :  1.0.1 (OK)
qdarkstyle =3.0.2             :  3.0.2 (OK)
qstylizer >=0.1.10            :  0.2.1 (OK)
qtawesome >=1.0.2             :  1.1.1 (OK)
qtconsole >=5.2.1;<5.3.0      :  5.2.1 (OK)
qtpy >=1.5.0                  :  1.9.0 (OK)
rtree >=0.9.7                 :  0.9.7 (OK)
setuptools >=49.6.0           :  58.2.0 (OK)
sphinx >=0.6.6                :  4.3.2 (OK)
spyder_kernels >=2.2.0;<2.3.0 :  2.2.0 (OK)
textdistance >=4.2.0          :  4.2.2 (OK)
three_merge >=0.1.1           :  0.1.1 (OK)
watchdog >=0.10.3             :  2.1.6 (OK)
xdg >=0.26                    :  0.27 (OK)
zmq >=17                      :  22.3.0 (OK)

# Optional:
cython >=0.21                 :  0.29.24 (OK)
matplotlib >=2.0.0            :  3.3.4 (OK)
numpy >=1.7                   :  1.21.5 (OK)
pandas >=1.1.1                :  1.3.4 (OK)
scipy >=0.17.0                :  1.7.1 (OK)
sympy >=0.7.3                 :  1.7.1 (OK)
```



Discussion:

Resolving patch:
diff --git a/spyder/config/lsp.py b/spyder/config/lsp.py
--- a/spyder/config/lsp.py
+++ b/spyder/config/lsp.py
@@ -47,7 +47,7 @@
                 'autopep8': {
                     'enabled': True
                 },
-                'black': {
+                'pylsp_black': {
                     'enabled': False
                 },
                 'yapf': {
diff --git a/spyder/dependencies.py b/spyder/dependencies.py
--- a/spyder/dependencies.py
+++ b/spyder/dependencies.py
@@ -367,9 +367,14 @@ def add(modname, package_name, features, required_version,
     """Add Spyder dependency"""
     global DEPENDENCIES
     for dependency in DEPENDENCIES:
+        # Avoid showing an unnecessary error when running our tests.
+        if running_in_ci() and 'spyder_boilerplate' in modname:
+            continue
+
         if dependency.modname == modname:
             raise ValueError(
                 f"Dependency has already been registered: {modname}")
+
     DEPENDENCIES += [Dependency(modname, package_name, features,
                                 required_version,
                                 installed_version, kind)]
diff --git a/spyder/plugins/completion/providers/languageserver/provider.py b/spyder/plugins/completion/providers/languageserver/provider.py
--- a/spyder/plugins/completion/providers/languageserver/provider.py
+++ b/spyder/plugins/completion/providers/languageserver/provider.py
@@ -756,8 +756,8 @@ def generate_python_config(self):
 
         # Autoformatting configuration
         formatter = self.get_conf('formatting')
-        formatter = 'pyls_black' if formatter == 'black' else formatter
-        formatters = ['autopep8', 'yapf', 'pyls_black']
+        formatter = 'pylsp_black' if formatter == 'black' else formatter
+        formatters = ['autopep8', 'yapf', 'pylsp_black']
         formatter_options = {
             fmt: {
                 'enabled': fmt == formatter
@@ -765,8 +765,8 @@ def generate_python_config(self):
             for fmt in formatters
         }
 
-        if formatter == 'pyls_black':
-            formatter_options['pyls_black']['line_length'] = cs_max_line_length
+        if formatter == 'pylsp_black':
+            formatter_options['pylsp_black']['line_length'] = cs_max_line_length
 
         # PyLS-Spyder configuration
         group_cells = self.get_conf(


Test patch:
diff --git a/spyder/app/tests/test_mainwindow.py b/spyder/app/tests/test_mainwindow.py
--- a/spyder/app/tests/test_mainwindow.py
+++ b/spyder/app/tests/test_mainwindow.py
@@ -1850,7 +1850,7 @@ def test_change_cwd_dbg(main_window, qtbot):
 
 @pytest.mark.slow
 @flaky(max_runs=3)
-@pytest.mark.skipif(os.name == 'nt' or PY2, reason="It times out sometimes")
+@pytest.mark.skipif(os.name == 'nt', reason="Times out sometimes")
 def test_varexp_magic_dbg(main_window, qtbot):
     """Test that %varexp is working while debugging."""
     nsb = main_window.variableexplorer.current_widget()
@@ -1874,7 +1874,7 @@ def test_varexp_magic_dbg(main_window, qtbot):
         qtbot.mouseClick(debug_button, Qt.LeftButton)
 
     # Get to an object that can be plotted
-    for _ in range(2):
+    for _ in range(3):
         with qtbot.waitSignal(shell.executed):
             qtbot.keyClicks(control, '!n')
             qtbot.keyClick(control, Qt.Key_Enter)
diff --git a/spyder/plugins/editor/widgets/tests/assets/yapf_range.py b/spyder/plugins/editor/widgets/tests/assets/yapf_range.py
--- a/spyder/plugins/editor/widgets/tests/assets/yapf_range.py
+++ b/spyder/plugins/editor/widgets/tests/assets/yapf_range.py
@@ -10,6 +10,7 @@
 
 # %% functions
 def d():
+
     def inner():
         return 2
 
diff --git a/spyder/plugins/editor/widgets/tests/assets/yapf_result.py b/spyder/plugins/editor/widgets/tests/assets/yapf_result.py
--- a/spyder/plugins/editor/widgets/tests/assets/yapf_result.py
+++ b/spyder/plugins/editor/widgets/tests/assets/yapf_result.py
@@ -11,6 +11,7 @@
 
 # %% functions
 def d():
+
     def inner():
         return 2
 
@@ -43,6 +44,7 @@ def c():
 
 # %% classes
 class Class1:
+
     def __init__(self):
         super(Class1, self).__init__()
         self.x = 2
diff --git a/spyder/plugins/editor/widgets/tests/test_formatting.py b/spyder/plugins/editor/widgets/tests/test_formatting.py
--- a/spyder/plugins/editor/widgets/tests/test_formatting.py
+++ b/spyder/plugins/editor/widgets/tests/test_formatting.py
@@ -12,6 +12,7 @@
 
 # Third party imports
 import pytest
+import yapf
 
 # Qt imports
 from qtpy.QtGui import QTextCursor
@@ -31,6 +32,14 @@
     )
 )
 
+yapf = pytest.param(
+    'yapf',
+    marks=pytest.mark.skipif(
+        yapf.__version__ < '0.32.0',
+        reason='Older versions produce different outputs'
+    )
+)
+
 
 def get_formatter_values(formatter, range_fmt=False):
     suffix = 'range' if range_fmt else 'result'
@@ -48,7 +57,7 @@ def get_formatter_values(formatter, range_fmt=False):
 
 @pytest.mark.slow
 @pytest.mark.order(1)
-@pytest.mark.parametrize('formatter', [autopep8, 'yapf', 'black'])
+@pytest.mark.parametrize('formatter', [autopep8, yapf, 'black'])
 def test_document_formatting(formatter, completions_codeeditor, qtbot):
     """Validate text autoformatting via autopep8, yapf or black."""
     code_editor, completion_plugin = completions_codeeditor
@@ -82,7 +91,7 @@ def test_document_formatting(formatter, completions_codeeditor, qtbot):
 @pytest.mark.slow
 @pytest.mark.order(1)
 @pytest.mark.parametrize(
-    'formatter', [autopep8, 'yapf', 'black'])
+    'formatter', [autopep8, yapf, 'black'])
 def test_document_range_formatting(formatter, completions_codeeditor, qtbot):
     """Validate text range autoformatting."""
     code_editor, completion_plugin = completions_codeeditor
diff --git a/spyder/plugins/editor/widgets/tests/test_warnings.py b/spyder/plugins/editor/widgets/tests/test_warnings.py
--- a/spyder/plugins/editor/widgets/tests/test_warnings.py
+++ b/spyder/plugins/editor/widgets/tests/test_warnings.py
@@ -269,7 +269,10 @@ def test_update_warnings_after_closequotes(qtbot, completions_codeeditor_linting
     editor, _ = completions_codeeditor_linting
     editor.textCursor().insertText("print('test)\n")
 
-    expected = [['EOL while scanning string literal', 1]]
+    if sys.version_info >= (3, 10):
+        expected = [['unterminated string literal (detected at line 1)', 1]]
+    else:
+        expected = [['EOL while scanning string literal', 1]]
 
     # Notify changes.
     with qtbot.waitSignal(editor.completions_response_signal, timeout=30000):
@@ -306,8 +309,16 @@ def test_update_warnings_after_closebrackets(qtbot, completions_codeeditor_linti
     editor, _ = completions_codeeditor_linting
     editor.textCursor().insertText("print('test'\n")
 
-    expected = [['unexpected EOF while parsing', 1],
-                ['E901 TokenError: EOF in multi-line statement', 2]]
+    if sys.version_info >= (3, 10):
+        expected = [
+            ["'(' was never closed", 1],
+            ['E901 TokenError: EOF in multi-line statement', 2]
+        ]
+    else:
+        expected = [
+            ['unexpected EOF while parsing', 1],
+            ['E901 TokenError: EOF in multi-line statement', 2]
+        ]
 
     # Notify changes.
     with qtbot.waitSignal(editor.completions_response_signal, timeout=30000):