Repository: spyder-ide/spyder

Issue:
UnicodeDecodeError when truncating results in Find in files
## Description

**What steps will reproduce the problem?**

1. 
2. 
3. 

**What is the expected output? What do you see instead?**


**Please provide any additional information below**

  File "D:\Anaconda3\envs\py27\lib\site-packages\spyder\widgets\findinfiles.py", line 770, in append_result
    line = self.truncate_result(line, colno, match_end)
  File "D:\Anaconda3\envs\py27\lib\site-packages\spyder\widgets\findinfiles.py", line 695, in truncate_result
    line = to_text_string(line)
  File "D:\Anaconda3\envs\py27\lib\site-packages\spyder\py3compat.py", line 123, in to_text_string
    return unicode(obj)
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 4504: ordinal not in range(128)
  File "D:\Anaconda3\envs\py27\lib\site-packages\spyder\widgets\findinfiles.py", line 770, in append_result
    line = self.truncate_result(line, colno, match_end)
  File "D:\Anaconda3\envs\py27\lib\site-packages\spyder\widgets\findinfiles.py", line 695, in truncate_result
    line = to_text_string(line)
  File "D:\Anaconda3\envs\py27\lib\site-packages\spyder\py3compat.py", line 123, in to_text_string
    return unicode(obj)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xb3 in position 11: ordinal not in range(128)
  File "D:\Anaconda3\envs\py27\lib\site-packages\spyder\widgets\findinfiles.py", line 770, in append_result
    line = self.truncate_result(line, colno, m


Discussion:
Thanks for reporting. We'll fix this in a future release. In the meantime, you could have better luck by working with Python 3 instead of Python 2.

Resolving patch:
diff --git a/spyder/py3compat.py b/spyder/py3compat.py
--- a/spyder/py3compat.py
+++ b/spyder/py3compat.py
@@ -130,6 +130,8 @@ def is_unicode(obj):
 def to_text_string(obj, encoding=None):
     """Convert `obj` to (unicode) text string"""
     if PY2:
+        if isinstance(obj, unicode):
+            return obj
         # Python 2
         if encoding is None:
             return unicode(obj)
diff --git a/spyder/widgets/findinfiles.py b/spyder/widgets/findinfiles.py
--- a/spyder/widgets/findinfiles.py
+++ b/spyder/widgets/findinfiles.py
@@ -33,7 +33,7 @@
 
 # Local imports
 from spyder.config.base import _
-from spyder.py3compat import to_text_string
+from spyder.py3compat import to_text_string, PY2
 from spyder.utils import icon_manager as ima
 from spyder.utils.encoding import is_text_file, to_unicode_from_fs
 from spyder.utils.misc import getcwd_or_home
@@ -777,7 +777,7 @@ def clear_title(self, search_text):
         self.set_title(title + text)
 
     def truncate_result(self, line, start, end):
-        ellipsis = '...'
+        ellipsis = u'...'
         max_line_length = 80
         max_num_char_fragment = 40
 
@@ -793,7 +793,8 @@ def html_escape(text):
             """Produce entities within text."""
             return "".join(html_escape_table.get(c, c) for c in text)
 
-        line = to_text_string(line)
+        if PY2:
+            line = to_text_string(line, encoding='utf8')
         left, match, right = line[:start], line[start:end], line[end:]
 
         if len(line) > max_line_length:


Test patch:
diff --git a/spyder/widgets/tests/test_findinfiles.py b/spyder/widgets/tests/test_findinfiles.py
--- a/spyder/widgets/tests/test_findinfiles.py
+++ b/spyder/widgets/tests/test_findinfiles.py
@@ -22,6 +22,7 @@
                                         EXTERNAL_PATHS, SELECT_OTHER, CWD,
                                         CLEAR_LIST, PROJECT, FILE_PATH,
                                         QMessageBox)
+from spyder.py3compat import PY2
 
 LOCATION = osp.realpath(osp.join(os.getcwd(), osp.dirname(__file__)))
 NONASCII_DIR = osp.join(LOCATION, u"èáïü Øαôå 字分误")
@@ -165,6 +166,35 @@ def test_exclude_extension_multiple_string(qtbot):
     assert files_filtered
 
 
+@pytest.mark.parametrize("line_input", ['nnnnn', 'ñandú'])
+def test_truncate_result_with_different_input(qtbot, line_input):
+    """
+    Issue: 6218 - checking if truncate_result raise UnicodeDecodeError
+    """
+
+    # with
+    find_in_files = setup_findinfiles(qtbot)
+    slice_start = 1
+    slice_end = 2
+
+    if PY2:
+        line_input_expected = line_input.decode('utf-8')
+    else:
+        line_input_expected = line_input
+
+    expected_result = u'%s<b>%s</b>%s' % (
+        line_input_expected[:slice_start],
+        line_input_expected[slice_start:slice_end],
+        line_input_expected[slice_end:])
+
+    # when
+    truncated_line = find_in_files.result_browser.truncate_result(
+        line_input, slice_start, slice_end)
+
+    # then
+    assert truncated_line == expected_result
+
+
 def test_case_unsensitive_search(qtbot):
     find_in_files = setup_findinfiles(qtbot, case_sensitive=False)
     find_in_files.set_search_text('ham')