From d9cf8f3a47f0ba26f713ec04513f75092299572e 2016-04-15 09:10:09 From: Matthias Bussonnier Date: 2016-04-15 09:10:09 Subject: [PATCH] Force completion results to be unicode. Should fix some of #9379 --- diff --git a/IPython/core/completer.py b/IPython/core/completer.py index 86ba87e..486ec4a 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -69,11 +69,10 @@ from IPython.core.error import TryNext from IPython.core.inputsplitter import ESC_MAGIC from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol from IPython.utils import generics -from IPython.utils import io from IPython.utils.decorators import undoc from IPython.utils.dir2 import dir2, get_real_method from IPython.utils.process import arg_split -from IPython.utils.py3compat import builtin_mod, string_types, PY3 +from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2 from traitlets import CBool, Enum #----------------------------------------------------------------------------- @@ -348,7 +347,7 @@ class Completer(Configurable): for word in lst: if word[:n] == text and word != "__builtins__": match_append(word) - return matches + return [cast_unicode_py2(m) for m in matches] def attr_matches(self, text): """Compute matches when text contains a dot. @@ -401,8 +400,7 @@ class Completer(Configurable): pass # Build match list to return n = len(attr) - res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ] - return res + return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ] def get__all__entries(obj): @@ -412,7 +410,7 @@ def get__all__entries(obj): except: return [] - return [w for w in words if isinstance(w, string_types)] + return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)] def match_dict_keys(keys, prefix, delims): @@ -682,9 +680,9 @@ class IPCompleter(Completer): # when escaped with backslash if text.startswith('!'): text = text[1:] - text_prefix = '!' + text_prefix = u'!' else: - text_prefix = '' + text_prefix = u'' text_until_cursor = self.text_until_cursor # track strings with open quotes @@ -715,7 +713,7 @@ class IPCompleter(Completer): text = os.path.expanduser(text) if text == "": - return [text_prefix + protect_filename(f) for f in self.glob("*")] + return [cast_unicode_py2(text_prefix + protect_filename(f)) for f in self.glob("*")] # Compute the matches from the filesystem m0 = self.clean_glob(text.replace('\\','')) @@ -737,11 +735,8 @@ class IPCompleter(Completer): matches = [text_prefix + protect_filename(f) for f in m0] - #io.rprint('mm', matches) # dbg - # Mark directories in input list by appending '/' to their names. - matches = [x+'/' if os.path.isdir(x) else x for x in matches] - return matches + return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches] def magic_matches(self, text): """Match magics""" @@ -763,9 +758,9 @@ class IPCompleter(Completer): comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)] if not text.startswith(pre2): comp += [ pre+m for m in line_magics if m.startswith(bare_text)] - return comp + return [cast_unicode_py2(c) for c in comp] - def python_matches(self,text): + def python_matches(self, text): """Match attributes or global python names""" #io.rprint('Completer->python_matches, txt=%r' % text) # dbg @@ -787,7 +782,6 @@ class IPCompleter(Completer): matches = [] else: matches = self.global_matches(text) - return matches def _default_arguments_from_docstring(self, doc): @@ -916,7 +910,7 @@ class IPCompleter(Completer): for namedArg in namedArgs: if namedArg.startswith(text): - argMatches.append("%s=" %namedArg) + argMatches.append(u"%s=" %namedArg) return argMatches def dict_key_matches(self, text): @@ -1075,7 +1069,6 @@ class IPCompleter(Completer): return u'', [] def dispatch_custom_completer(self, text): - #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg line = self.line_buffer if not line.strip(): return None @@ -1101,17 +1094,16 @@ class IPCompleter(Completer): for c in itertools.chain(self.custom_completers.s_matches(cmd), try_magic, self.custom_completers.flat_matches(self.text_until_cursor)): - #print "try",c # dbg try: res = c(event) if res: # first, try case sensitive match - withcase = [r for r in res if r.startswith(text)] + withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)] if withcase: return withcase # if none, then case insensitive ones are ok too text_low = text.lower() - return [r for r in res if r.lower().startswith(text_low)] + return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)] except TryNext: pass