From cae27fba5c37e11dc0789bd3cb1c1fe7a02bf9d2 Mon Sep 17 00:00:00 2001 From: Andrew Ruder Date: Wed, 9 Apr 2014 09:51:19 -0500 Subject: [PATCH] Ensure that _vim_{dec,enc} always succeeds on py3 In py2 we could get by with attempting to encode/decode a string and if it failed just ignore and return. Unfortunately on py3 a string decodes to a bytearray and a bytearray encodes to a string. We can't simply return the original object when we fail. We choose replace for handling bytes we don't understand. Test case (using python3 for UltiSnips): open a new file :set encoding=utf-8 qaq "ap Warning: this test case makes it very difficult to exit vim cleanly and save files! Signed-off-by: Andrew Ruder --- doc/UltiSnips.txt | 1 + pythonx/UltiSnips/compatibility.py | 45 ++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/doc/UltiSnips.txt b/doc/UltiSnips.txt index f0a12e2..7a9e671 100644 --- a/doc/UltiSnips.txt +++ b/doc/UltiSnips.txt @@ -1384,6 +1384,7 @@ individuals have contributed to UltiSnips (in chronological order): Pedro Ferrari - petobens Ches Martin - ches Christian - Oberon00 + Andrew Ruder - aeruder Thank you for your support. diff --git a/pythonx/UltiSnips/compatibility.py b/pythonx/UltiSnips/compatibility.py index 1a05f13..c8c975e 100644 --- a/pythonx/UltiSnips/compatibility.py +++ b/pythonx/UltiSnips/compatibility.py @@ -10,22 +10,21 @@ import sys import vim # pylint:disable=import-error -def _vim_dec(string): - """Decode 'string' using &encoding.""" - try: - return string.decode(vim.eval("&encoding")) - except UnicodeDecodeError: - # At least we tried. There might be some problems down the road now - return string - -def _vim_enc(string): - """Encode 'string' using &encoding.""" - try: - return string.encode(vim.eval("&encoding")) - except UnicodeEncodeError: - return string - if sys.version_info >= (3, 0): + def _vim_dec(string): + """Decode 'string' using &encoding.""" + # We don't have the luxury here of failing, everything + # falls apart if we don't return a bytearray from the + # passed in string + return string.decode(vim.eval("&encoding"), "replace") + + def _vim_enc(bytearray): + """Encode 'string' using &encoding.""" + # We don't have the luxury here of failing, everything + # falls apart if we don't return a string from the passed + # in bytearray + return bytearray.encode(vim.eval("&encoding"), "replace") + def open_ascii_file(filename, mode): """Opens a file in "r" mode.""" return open(filename, mode, encoding="utf-8") @@ -60,6 +59,22 @@ if sys.version_info >= (3, 0): else: import warnings warnings.filterwarnings("ignore", category=DeprecationWarning) + + def _vim_dec(string): + """Decode 'string' using &encoding.""" + try: + return string.decode(vim.eval("&encoding")) + except UnicodeDecodeError: + # At least we tried. There might be some problems down the road now + return string + + def _vim_enc(string): + """Encode 'string' using &encoding.""" + try: + return string.encode(vim.eval("&encoding")) + except UnicodeEncodeError: + return string + def open_ascii_file(filename, mode): """Opens a file in "r" mode.""" return open(filename, mode)