Repository: spyder-ide/spyder

Issue:
Autocomplete does not work properly if the file starts with a number
## Description

### What steps will reproduce the problem?

<!--- You can use Markdown here --->

Hello.

I typed "00".
And I tried to automatically complete a filename that starts with "00_" as in the example below.
But The auto-completion result was "0000_".


![Exp](https://user-images.githubusercontent.com/22970578/205675195-c910c091-9884-4978-be16-08c92ce24bdc.gif)

This problem has been around for a long time.

Thank you.

## Versions

* Spyder version: 5.4.0  (conda)
* Python version: 3.9.12 64-bit
* Qt version: 5.12.9
* PyQt5 version: 5.12.3
* Operating System: Linux 5.15.0-56-generic

### Dependencies

```
# 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.1.0 (OK)
IPython >=7.31.1;<8.0.0               :  7.31.1 (OK)
jedi >=0.17.2;<0.19.0                 :  0.18.1 (OK)
jellyfish >=0.7                       :  0.9.0 (OK)
jsonschema >=3.2.0                    :  4.16.0 (OK)
keyring >=17.0.0                      :  23.9.3 (OK)
nbconvert >=4.0                       :  6.5.4 (OK)
numpydoc >=0.6.0                      :  1.5.0 (OK)
parso >=0.7.0;<0.9.0                  :  0.8.3 (OK)
pexpect >=4.4.0                       :  4.8.0 (OK)
pickleshare >=0.4                     :  0.7.5 (OK)
psutil >=5.3                          :  5.9.0 (OK)
pygments >=2.0                        :  2.11.2 (OK)
pylint >=2.5.0;<3.0                   :  2.14.5 (OK)
pylint_venv >=2.1.1                   :  2.3.0 (OK)
pyls_spyder >=0.4.0                   :  0.4.0 (OK)
pylsp >=1.6.0;<1.7.0                  :  1.6.0 (OK)
pylsp_black >=1.2.0                   :  1.2.1 (OK)
qdarkstyle >=3.0.2;<3.1.0             :  3.0.2 (OK)
qstylizer >=0.2.2                     :  0.2.2 (OK)
qtawesome >=1.2.1                     :  1.2.1 (OK)
qtconsole >=5.4.0;<5.5.0              :  5.4.0 (OK)
qtpy >=2.1.0                          :  2.2.0 (OK)
rtree >=0.9.7                         :  0.9.7 (OK)
setuptools >=49.6.0                   :  65.5.0 (OK)
sphinx >=0.6.6                        :  5.0.2 (OK)
spyder_kernels >=2.4.0;<2.5.0         :  2.4.0 (OK)
textdistance >=4.2.0                  :  4.2.1 (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 >=22.1.0                          :  23.2.0 (OK)

# Optional:
cython >=0.21                         :  0.29.32 (OK)
matplotlib >=3.0.0                    :  3.5.3 (OK)
numpy >=1.7                           :  1.21.5 (OK)
pandas >=1.1.1                        :  1.5.1 (OK)
scipy >=0.17.0                        :  1.7.3 (OK)
sympy >=0.7.3                         :  1.11.1 (OK)

```



Discussion:
Hi @ok97465 thanks for the feedback! I was able to reproduce this :+1: Let us know if you want to help us fixing this!
I like Spyder-ide very much and it's worth spending my time on Spyder. But these days, I can't have time alone at home. So I don't know when I'll see the Spyder code. ㅜㅜ;;

No problem! I will try to give it a check for the next release :+1:

Resolving patch:
diff --git a/spyder/widgets/mixins.py b/spyder/widgets/mixins.py
--- a/spyder/widgets/mixins.py
+++ b/spyder/widgets/mixins.py
@@ -1083,7 +1083,7 @@ def is_special_character(move):
         startpos = cursor.selectionStart()
 
         # Find a valid Python variable name
-        if valid_python_variable:
+        if valid_python_variable and not completion:
             match = re.findall(r'([^\d\W]\w*)', text, re.UNICODE)
             if not match:
                 # This is assumed in several places of our codebase,


Test patch:
diff --git a/spyder/plugins/editor/widgets/tests/test_introspection.py b/spyder/plugins/editor/widgets/tests/test_introspection.py
--- a/spyder/plugins/editor/widgets/tests/test_introspection.py
+++ b/spyder/plugins/editor/widgets/tests/test_introspection.py
@@ -23,10 +23,6 @@
 # Local imports
 from spyder.config.base import running_in_ci, running_in_ci_with_conda
 from spyder.config.utils import is_anaconda
-from spyder.plugins.completion.api import (
-    CompletionRequestTypes, CompletionItemKind)
-from spyder.plugins.completion.providers.kite.providers.document import (
-    KITE_COMPLETION)
 from spyder.plugins.completion.providers.kite.utils.status import (
     check_if_kite_installed, check_if_kite_running)
 from spyder.py3compat import PY2
@@ -1068,55 +1064,6 @@ def test_text_snippet_completions(completions_codeeditor, qtbot):
     code_editor.toggle_code_snippets(True)
 
 
-@pytest.mark.slow
-@pytest.mark.order(1)
-@flaky(max_runs=5)
-def test_kite_textEdit_completions(mock_completions_codeeditor, qtbot):
-    """Test textEdit completions such as those returned by the Kite provider.
-
-    This mocks out the completions response, and does not test the Kite
-    provider directly.
-    """
-    code_editor, mock_response = mock_completions_codeeditor
-    completion = code_editor.completion_widget
-
-    code_editor.toggle_automatic_completions(False)
-    code_editor.toggle_code_snippets(False)
-
-    # Set cursor to start
-    code_editor.go_to_line(1)
-
-    qtbot.keyClicks(code_editor, 'my_dict.')
-
-    # Complete my_dict. -> my_dict["dict-key"]
-    mock_response.side_effect = lambda lang, method, params: {'params': [{
-        'kind': CompletionItemKind.TEXT,
-        'label': '["dict-key"]',
-        'textEdit': {
-            'newText': '["dict-key"]',
-            'range': {
-                'start': 7,
-                'end': 8,
-            },
-        },
-        'filterText': '',
-        'sortText': '',
-        'documentation': '',
-        'provider': KITE_COMPLETION,
-    }]} if method == CompletionRequestTypes.DOCUMENT_COMPLETION else None
-    with qtbot.waitSignal(completion.sig_show_completions,
-                          timeout=10000) as sig:
-        qtbot.keyPress(code_editor, Qt.Key_Tab, delay=300)
-    mock_response.side_effect = None
-
-    assert '["dict-key"]' in [x['label'] for x in sig.args[0]]
-    qtbot.keyPress(code_editor, Qt.Key_Enter, delay=300)
-    assert code_editor.toPlainText() == 'my_dict["dict-key"]\n'
-
-    code_editor.toggle_automatic_completions(True)
-    code_editor.toggle_code_snippets(True)
-
-
 @pytest.mark.slow
 @pytest.mark.order(1)
 @flaky(max_runs=5)