Repository: spyder-ide/spyder

Issue:
'Show completions on the fly' cannot be turned off
## Problem Description

Completions on the fly kicks in even when the option is unchecked.

![bug_auto_completion](https://user-images.githubusercontent.com/10170372/68405713-99585000-014e-11ea-8406-7a315d597d93.gif)


### What steps reproduce the problem?

1. Uncheck the option `Show completions on the fly`
2. Type some code that includes a '.'
3. Wait for completions to kicks in.

The problem seems to come from the code here :

https://github.com/spyder-ide/spyder/blob/90df471cff7d2713d20ebce900d27ede7b11e6f5/spyder/plugins/editor/widgets/codeeditor.py#L3602-L3610

It results in a call to `self.do_completion` directly even when the option `Show completions on the fly` is unchecked. Adding `and self.automatic_completions` to the condition `elif text in self.auto_completion_characters:` seems to fix the problem.

## 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 4.0.0.dev0 (Commit: 3fd0553b4) 
* Python 3.7.3 64-bit | Qt 5.9.6 | PyQt5 5.9.2 | Windows 10 



Discussion:
@jnsebgosselin thanks for this!

Could you open a PR ? Thanks!
If it is as simple as that, sure.

However, I don't completely understand why calls are made directly to `do_completion`, ignoring the timer. 
True, cause the `'.'` is a special case so yes the timer is being ignored. 

Let me handles this, so I can fix the logic.
Excellent, thanks!

Resolving patch:
diff --git a/spyder/plugins/editor/widgets/codeeditor.py b/spyder/plugins/editor/widgets/codeeditor.py
--- a/spyder/plugins/editor/widgets/codeeditor.py
+++ b/spyder/plugins/editor/widgets/codeeditor.py
@@ -3476,10 +3476,17 @@ def event(self, event):
         else:
             return super(CodeEditor, self).event(event)
 
+    def _start_completion_timer(self):
+        """Helper to start timer or complete."""
+        if self.automatic_completions_after_ms > 0:
+            self._timer_autocomplete.start(
+                self.automatic_completions_after_ms)
+        else:
+            self._handle_completions()
+
     def keyPressEvent(self, event):
         """Reimplement Qt method."""
-        if self.automatic_completions_after_ms > 0:
-            self._timer_autocomplete.start(self.automatic_completions_after_ms)
+        self._start_completion_timer()
 
         if self.completions_hint_after_ms > 0:
             self._completions_hint_idle = False
@@ -3616,7 +3623,7 @@ def insert_text(event):
                     last_obj = getobj(text)
                     prev_char = text[-2] if len(text) > 1 else ''
                     if prev_char in {')', ']', '}'} or (last_obj and not last_obj.isdigit()):
-                        self.do_completion(automatic=True)
+                        self._start_completion_timer()
             else:
                 self.do_completion(automatic=True)
         elif (text != '(' and text in self.signature_completion_characters and
@@ -3675,12 +3682,20 @@ def insert_text(event):
             event.accept()
 
     def _handle_completions(self):
-        """Handle on the fly completions with a delay."""
+        """Handle on the fly completions after delay."""
         cursor = self.textCursor()
         pos = cursor.position()
         cursor.select(QTextCursor.WordUnderCursor)
         text = to_text_string(cursor.selectedText())
 
+        # Text might be after a dot '.'
+        if text == '':
+            cursor.setPosition(pos - 1, QTextCursor.MoveAnchor)
+            cursor.select(QTextCursor.WordUnderCursor)
+            text = to_text_string(cursor.selectedText())
+            if text != '.':
+                text = ''
+
         # WordUnderCursor fails if the cursor is next to a right brace.
         # If the returned text starts with it, we move to the left.
         if text.startswith((')', ']', '}')):
@@ -3695,7 +3710,8 @@ def _handle_completions(self):
             # Perform completion on the fly
             if self.automatic_completions and not self.in_comment_or_string():
                 # Variables can include numbers and underscores
-                if text.isalpha() or text.isalnum() or '_' in text:
+                if (text.isalpha() or text.isalnum() or '_' in text
+                        or '.' in text):
                     self.do_completion(automatic=True)
                     self._last_key_pressed_text = ''
 


Test patch: