Skip to content

Commit b4cee82

Browse files
GlobalCompleter returns unicode matches
1 parent b230413 commit b4cee82

File tree

4 files changed

+32
-16
lines changed

4 files changed

+32
-16
lines changed

bpython/_py3compat.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,13 @@ def prepare_for_exec(arg, encoding=None):
4949
else:
5050
def prepare_for_exec(arg, encoding=None):
5151
return arg.encode(encoding)
52+
53+
54+
def try_decode(s, encoding):
55+
"""Try to decode s which is str names. Return None if not decodable"""
56+
if not py3 and not isinstance(s, unicode):
57+
try:
58+
return s.decode(encoding)
59+
except UnicodeDecodeError:
60+
return None
61+
return s

bpython/autocomplete.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from bpython import inspection
3535
from bpython import importcompletion
3636
from bpython import line as lineparts
37-
from bpython._py3compat import py3
37+
from bpython._py3compat import py3, try_decode
3838
from bpython.lazyre import LazyReCompile
3939

4040

@@ -286,11 +286,17 @@ def matches(self, cursor_offset, line, **kwargs):
286286
n = len(text)
287287
for word in keyword.kwlist:
288288
if method_match(word, n, text):
289-
matches.add(word)
289+
word = try_decode(word, 'ascii') # py2 keywords are all ascii
290+
if word is not None:
291+
matches.add(word)
290292
for nspace in [builtins.__dict__, locals_]:
291293
for word, val in nspace.items():
292294
if (method_match(word, len(text), text) and
293295
word != "__builtins__"):
296+
word = try_decode(word, 'ascii')
297+
# if identifier isn't ascii, don't complete (syntax error)
298+
if word is None:
299+
continue
294300
matches.add(_callable_postfix(val, word))
295301
return matches
296302

bpython/importcompletion.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
# THE SOFTWARE.
2222

23-
from bpython._py3compat import py3
23+
from bpython._py3compat import py3, try_decode
2424
from bpython.line import current_word, current_import, \
2525
current_from_import_from, current_from_import_import
2626

@@ -42,17 +42,6 @@
4242
fully_loaded = False
4343

4444

45-
def try_decode_module(module, encoding):
46-
"""Try to decode module names."""
47-
if not py3 and not isinstance(module, unicode):
48-
try:
49-
return module.decode(encoding)
50-
except UnicodeDecodeError:
51-
# Not importable anyway, ignore it
52-
return None
53-
return module
54-
55-
5645
def module_matches(cw, prefix=''):
5746
"""Modules names to replace cw with"""
5847
full = '%s.%s' % (prefix, cw) if prefix else cw
@@ -83,7 +72,7 @@ def attr_matches(cw, prefix='', only_modules=False):
8372
if module_part:
8473
matches = ('%s.%s' % (module_part, m) for m in matches)
8574

86-
generator = (try_decode_module(match, 'ascii') for match in matches)
75+
generator = (try_decode(match, 'ascii') for match in matches)
8776
return set(filter(lambda x: x is not None, generator))
8877

8978

@@ -184,7 +173,7 @@ def find_all_modules(path=None):
184173
if not p:
185174
p = os.curdir
186175
for module in find_modules(p):
187-
module = try_decode_module(module, sys.getfilesystemencoding())
176+
module = try_decode(module, sys.getfilesystemencoding())
188177
if module is None:
189178
continue
190179
modules.add(module)

bpython/test/test_autocomplete.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# encoding: utf-8
2+
13
from collections import namedtuple
24
import inspect
35
from bpython._py3compat import py3
@@ -273,6 +275,15 @@ def function():
273275
locals_={'function': function}),
274276
set(('function(', )))
275277

278+
def test_completions_are_unicode(self):
279+
for m in self.com.matches(1, 'a', locals_={'abc': 10}):
280+
self.assertIsInstance(m, type(u''))
281+
282+
@unittest.skipIf(py3, "in Python 3 invalid identifiers are passed through")
283+
def test_ignores_nonascii_encodable(self):
284+
self.assertSetEqual(self.com.matches(1, 'abc', locals_={'abcß': 10}),
285+
set())
286+
276287

277288
class TestParameterNameCompletion(unittest.TestCase):
278289
def test_set_of_params_returns_when_matches_found(self):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy