Repository: spyder-ide/spyder

Issue:
Cannot type further letters or symbols after : in symbol finder dialog
Using Spyder 3.2.6 - PYthon 2.7 - Windows 10 - Spanish Keyboard

Crash inside the Spyder IDE @ finder dialog.

When I delete the @ prewritten and try to write :number, just after pressing ":" this functionality crashes. 


Discussion:
Thanks for reporting. We'll take a look at this problem in future release.
More specifically, testing this on Spyder 3.3.0 - Python 3.6.6 - Windows 8.1 - US English Keyboard, after I type the ``:`` (regardless of what, if anything, is typed before it), I can't type further letter characters or symbol characters, but I can type numbers and it works just fine. Furthermore, I can press Backspace to delete it and then type something else, and everything continues to work. Therefore, it would seem that perhaps something's blocking/handling keypress events for letter/symbol keys, but not numbers or special keys, once ``:`` is typed, and stops doing so once it is removed.
As @CAM-Gerlach described, you can only type numbers after typing `:`.
>  try to write :number 

Perhaps you took ``number`` a little too literally, haha?
Hahahah that would be something I'd do haha, but this is not the case. I experience the crash right after I type `:` so I don't have the chance to even write number or character. 

# Crash info:
> 
>   File "C:\Users\Eduardo\Anaconda2\lib\site-packages\spyder\widgets\fileswitcher.py", line 794, in setup
>     self.setup_file_list(filter_text, current_path)
>   File "C:\Users\Eduardo\Anaconda2\lib\site-packages\spyder\widgets\fileswitcher.py", line 663, in setup_file_list
>     _("lines"))
> UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 1: ordinal not in range(128)

It seems to be about the ascii coding of my keyboard or something similar.

Okay, thanks for the information. First, update to Spyder 3.3.0 when it comes out on conda in a few days and try again, to ensure the bug hasn't already been fixed, since it has been quite a few months and 3 releases since 32.6. If not, this indeed a real issue @ccordoba12 .

Do any of the files you have open have non-ASCII characters in their names, full paths or contents? That seems to be the issue here, which the Python 2 version Spyder is running under is not designed to natively handle it (and thus the real solution is to upgrade to Python 3; Python 2 is EoLed in less than a year and a half and the scientific Python community has already moved overwhelmingly to Python 3 with Py2 support already dropped by a number of major libraries).
@dalthviz is this still relevant? could you check :-)
@goanpeca checking this with Spyder 3.3.6 and Python 3 I think the behavior is that when typing `:` you enter the 'go to line mode' and after `:` the only valid characters to type are numbers. In Spyder 4, when typing `:` you also enter to the 'go to line mode' but in this case the input isn't limited to numbers.

However, testing with Python 2 an exception is raised when trying to open the Switcher (an `UnicodeEncodeError`) when a file has characters like `í`:

```
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\editor\utils\switcher.py", line 142, in handle_switcher_modes
    self.create_editor_switcher()
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\plugins\editor\utils\switcher.py", line 172, in create_editor_switcher
    last_item=last_item)
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\widgets\switcher.py", line 655, in add_item
    styles=self._item_styles
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\widgets\switcher.py", line 315, in __init__
    self._set_rendered_text()
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\widgets\switcher.py", line 122, in _set_rendered_text
    self.setText(self._render_text())
  File "C:\Users\Daniel\Documents\Spyder\spyder\spyder\widgets\switcher.py", line 343, in _render_text
    **self._styles)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 5: ordinal not in range(128)

```

So we need to check the handling of unicode characters yep
@goanpeca should I only fix the issue for Spyder 4? this issue is also present in Spyder 3.3.6 with Python 2
>@goanpeca should I only fix the issue for Spyder 4? 

Yes, only 4

Resolving patch:
diff --git a/spyder/plugins/editor/utils/switcher.py b/spyder/plugins/editor/utils/switcher.py
--- a/spyder/plugins/editor/utils/switcher.py
+++ b/spyder/plugins/editor/utils/switcher.py
@@ -183,7 +183,7 @@ def create_line_switcher(self):
         title = osp.basename(path)
         lines = data.editor.get_line_count()
         icon = get_file_icon(path)
-        line_template_title = "{title} [{lines} {text}]"
+        line_template_title = u"{title} [{lines} {text}]"
         title = line_template_title.format(title=title, lines=lines,
                                            text=_("lines"))
         description = _('Go to line')
diff --git a/spyder/utils/stringmatching.py b/spyder/utils/stringmatching.py
--- a/spyder/utils/stringmatching.py
+++ b/spyder/utils/stringmatching.py
@@ -10,6 +10,7 @@
 
 import re
 
+from spyder.py3compat import to_text_string
 
 NOT_FOUND_SCORE = -1
 NO_SCORE = 0
@@ -37,7 +38,7 @@ def get_search_regex(query, ignore_case=True):
     regex_text = [char for char in query if char != ' ']
     regex_text = '.*'.join(regex_text)
 
-    regex = r'({0})'.format(regex_text)
+    regex = u'({0})'.format(regex_text)
 
     if ignore_case:
         pattern = re.compile(regex, re.IGNORECASE)
@@ -87,13 +88,16 @@ def get_search_score(query, choice, ignore_case=True, apply_regex=True,
     - Letters in two or more words
       Example: 'cls' in 'car lost'
     """
-    original_choice = choice
+    original_choice = to_text_string(choice, encoding='utf-8')
     result = (original_choice, NOT_FOUND_SCORE)
 
     # Handle empty string case
     if not query:
         return result
 
+    query = to_text_string(query, encoding='utf-8')
+    choice = to_text_string(choice, encoding='utf-8')
+
     if ignore_case:
         query = query.lower()
         choice = choice.lower()
@@ -108,7 +112,8 @@ def get_search_score(query, choice, ignore_case=True, apply_regex=True,
         let = u'x'  # Nonmatches (except spaed) will be replaced by this
         score = 0
 
-        exact_words = [query == word for word in choice.split(u' ')]
+        exact_words = [query == to_text_string(word, encoding='utf-8')
+                       for word in choice.split(u' ')]
         partial_words = [query in word for word in choice.split(u' ')]
 
         if any(exact_words) or any(partial_words):
diff --git a/spyder/widgets/switcher.py b/spyder/widgets/switcher.py
--- a/spyder/widgets/switcher.py
+++ b/spyder/widgets/switcher.py
@@ -183,7 +183,7 @@ class SwitcherSeparatorItem(SwitcherBaseItem):
         'font_size': 10,
     }
     _TEMPLATE = \
-        '''<table cellpadding="{padding}" cellspacing="0" width="{width}"
+        u'''<table cellpadding="{padding}" cellspacing="0" width="{width}"
                   height="{height}" border="0">
   <tr><td valign="top" align="center"><hr></td></tr>
 </table>'''
@@ -260,7 +260,8 @@ class SwitcherItem(SwitcherBaseItem):
         'section_font_size': _FONT_SIZE,
         'shortcut_font_size': _FONT_SIZE,
     }
-    _TEMPLATE = '''<table width="{width}" max_width="{width}" height="{height}"
+    _TEMPLATE = u'''
+<table width="{width}" max_width="{width}" height="{height}"
                           cellpadding="{padding}">
   <tr>
     <td valign="middle">
@@ -337,6 +338,11 @@ def _render_text(self, title=None, description=None, section=None):
 
         shortcut = '&lt;' + self._shortcut + '&gt;' if self._shortcut else ''
 
+        title = to_text_string(title, encoding='utf-8')
+        section = to_text_string(section, encoding='utf-8')
+        description = to_text_string(description, encoding='utf-8')
+        shortcut = to_text_string(shortcut, encoding='utf-8')
+
         text = self._TEMPLATE.format(width=width, height=height, title=title,
                                      section=section, description=description,
                                      padding=padding, shortcut=shortcut,
@@ -907,6 +913,7 @@ def create_vcs_example_switcher(sw):
                 icon=ima.icon('MessageBoxInformation'))
     sw.add_item(title='master', description='123123')
     sw.add_item(title='develop', description='1231232a')
+    sw.add_item(title=u'test-试', description='1231232ab')
     sw.add_separator()
     sw.add_item(title='other', description='q2211231232a')
 


Test patch:
diff --git a/spyder/widgets/tests/test_switcher.py b/spyder/widgets/tests/test_switcher.py
--- a/spyder/widgets/tests/test_switcher.py
+++ b/spyder/widgets/tests/test_switcher.py
@@ -12,6 +12,7 @@
 from qtpy.QtCore import Qt
 
 from spyder.config.base import _
+from spyder.py3compat import to_text_string
 
 
 @pytest.fixture
@@ -72,7 +73,7 @@ def test_switcher_filter_and_mode(dlg_switcher, qtbot):
     edit = dlg_switcher.edit
 
     # Initially cvs mode with five rows
-    assert dlg_switcher.count() == 5
+    assert dlg_switcher.count() == 6
 
     # Match one row by name
     edit.setText("master")
@@ -102,3 +103,16 @@ def test_switcher_filter_and_mode(dlg_switcher, qtbot):
     edit.setText(":")
     qtbot.wait(1000)
     assert dlg_switcher.count() == 1
+
+
+def test_switcher_filter_unicode(dlg_switcher, qtbot):
+    """Test filter with unicode."""
+    edit = dlg_switcher.edit
+
+    # Initially cvs mode with five rows
+    assert dlg_switcher.count() == 6
+    dlg_switcher.show()
+    # Match one row by name
+    edit.setText('试')
+    qtbot.wait(1000)
+    assert dlg_switcher.count() == 2