From 47d9ca7dadcb7c5333d83eb85e1ad39980486baa Mon Sep 17 00:00:00 2001 From: David Coles Date: Mon, 19 Oct 2015 19:42:18 -0700 Subject: [PATCH] pybind: Don't encode str on Python 2 If you attempt to call encode on a non-ASCII string, then a UnicodeDecodeError will be raised. Since str on Python 2 is an 8-bit string, it's possible that it's already UTF-8 encoded. As such we should just pass it through to the C API unmodified. On Python 3 or if the user explicitly uses unicode, then we'll encode it to UTF-8 for them. Signed-off-by: David Coles --- src/pybind/rados.py | 12 ++++++++++-- src/pybind/rbd.py | 16 ++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/pybind/rados.py b/src/pybind/rados.py index 684fd5e46321b..69431d229a453 100644 --- a/src/pybind/rados.py +++ b/src/pybind/rados.py @@ -29,7 +29,11 @@ LIBRADOS_OP_FLAG_FADVISE_DONTNEED = 0x20 LIBRADOS_OP_FLAG_FADVISE_NOCACHE = 0x40 -if sys.hexversion < 0x03000000: +# Are we running Python 2.x +_python2 = sys.hexversion < 0x03000000 + + +if _python2: str_type = basestring else: str_type = str @@ -279,7 +283,11 @@ def cstr(val, encoding="utf-8"): if val is None: return c_char_p(None) - return c_char_p(val.encode(encoding)) + if _python2 and isinstance(val, str): + # Don't encode str on Python 2, as it's already an 8-bit string + return c_char_p(val) + else: + return c_char_p(val.encode(encoding)) class Rados(object): diff --git a/src/pybind/rbd.py b/src/pybind/rbd.py index f8c66cd1f5618..c15a943be769d 100644 --- a/src/pybind/rbd.py +++ b/src/pybind/rbd.py @@ -9,10 +9,6 @@ Error codes from librbd are turned into exceptions that subclass (the base class of all rbd exceptions), :class:`PermissionError` and :class:`IOError`, in addition to those documented for the method. - -A number of methods have string arguments, which must not be unicode -to interact correctly with librbd. If unicode is passed to these -methods, a :class:`TypeError` will be raised. """ # Copyright 2011 Josh Durgin from collections import Iterable @@ -68,7 +64,11 @@ RBD_FEATURES_SINGLE_CLIENT = (RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FLAG_OBJECT_MAP_INVALID = 1 -if sys.hexversion < 0x03000000: +# Are we running Python 2.x +_python2 = sys.hexversion < 0x03000000 + + +if _python2: str_type = basestring else: str_type = str @@ -212,7 +212,11 @@ def cstr(val, encoding="utf-8"): if val is None: return c_char_p(None) - return c_char_p(val.encode(encoding)) + if _python2 and isinstance(val, str): + # Don't encode str on Python 2, as it's already an 8-bit string + return c_char_p(val) + else: + return c_char_p(val.encode(encoding)) class RBD(object): -- 2.39.5