Replace utils.ensure_(str|unicode) with strutils.safe(decode|encode)

Glanceclient implemented both functions before they landed into oslo.
Since both functions are already in oslo, it is now possible to pull
them in.

There's a small difference between glance's implementation and oslo's,
that is the later does not convert non-str objects - int, bool - to str
before trying to decode / encode them. This patch takes care of that
where necessary, more precisely, while encoding headers before doing a
new request.

Fixes bug: #1172253

Change-Id: I9a0dca31140bae28d8ec6aede515c5bb852b701b
This commit is contained in:
Flaper Fesp
2013-05-22 11:31:25 +02:00
parent 7daa976d14
commit 7818387d4a
10 changed files with 224 additions and 122 deletions
+5 -4
View File
@@ -36,6 +36,7 @@ import OpenSSL
from glanceclient import exc
from glanceclient.common import utils
from glanceclient.openstack.common import strutils
try:
from eventlet import patcher
@@ -130,7 +131,7 @@ class HTTPClient(object):
curl.append('-d \'%s\'' % kwargs['body'])
curl.append('%s%s' % (self.endpoint, url))
LOG.debug(utils.ensure_str(' '.join(curl)))
LOG.debug(strutils.safe_encode(' '.join(curl)))
@staticmethod
def log_http_response(resp, body=None):
@@ -140,7 +141,7 @@ class HTTPClient(object):
dump.append('')
if body:
dump.extend([body, ''])
LOG.debug(utils.ensure_str('\n'.join(dump)))
LOG.debug(strutils.safe_encode('\n'.join(dump)))
@staticmethod
def encode_headers(headers):
@@ -154,7 +155,7 @@ class HTTPClient(object):
:returns: Dictionary with encoded headers'
names and values
"""
to_str = utils.ensure_str
to_str = strutils.safe_encode
return dict([(to_str(h), to_str(v)) for h, v in headers.iteritems()])
def _http_request(self, url, method, **kwargs):
@@ -182,7 +183,7 @@ class HTTPClient(object):
conn_url = posixpath.normpath('%s/%s' % (self.endpoint_path, url))
# Note(flaper87): Ditto, headers / url
# encoding to make httplib happy.
conn_url = utils.ensure_str(conn_url)
conn_url = strutils.safe_encode(conn_url)
if kwargs['headers'].get('Transfer-Encoding') == 'chunked':
conn.putrequest(method, conn_url)
for header, value in kwargs['headers'].items():
+5 -77
View File
@@ -23,6 +23,7 @@ import prettytable
from glanceclient import exc
from glanceclient.openstack.common import importutils
from glanceclient.openstack.common import strutils
# Decorator for cli-args
@@ -54,14 +55,14 @@ def print_list(objs, fields, formatters={}):
row.append(data)
pt.add_row(row)
print ensure_str(pt.get_string())
print strutils.safe_encode(pt.get_string())
def print_dict(d):
pt = prettytable.PrettyTable(['Property', 'Value'], caching=False)
pt.align = 'l'
[pt.add_row(list(r)) for r in d.iteritems()]
print ensure_str(pt.get_string(sortby='Property'))
print strutils.safe_encode(pt.get_string(sortby='Property'))
def find_resource(manager, name_or_id):
@@ -75,7 +76,7 @@ def find_resource(manager, name_or_id):
# now try to get entity as uuid
try:
uuid.UUID(ensure_str(name_or_id))
uuid.UUID(strutils.safe_encode(name_or_id))
return manager.get(name_or_id)
except (ValueError, exc.NotFound):
pass
@@ -137,7 +138,7 @@ def import_versioned_module(version, submodule=None):
def exit(msg=''):
if msg:
print >> sys.stderr, ensure_str(msg)
print >> sys.stderr, strutils.safe_encode(msg)
sys.exit(1)
@@ -192,79 +193,6 @@ def make_size_human_readable(size):
return '%s%s' % (stripped, suffix[index])
def ensure_unicode(text, incoming=None, errors='strict'):
"""
Decodes incoming objects using `incoming` if they're
not already unicode.
:param incoming: Text's current encoding
:param errors: Errors handling policy.
:returns: text or a unicode `incoming` encoded
representation of it.
"""
if isinstance(text, unicode):
return text
if not incoming:
incoming = sys.stdin.encoding or \
sys.getdefaultencoding()
# Calling `str` in case text is a non str
# object.
text = str(text)
try:
return text.decode(incoming, errors)
except UnicodeDecodeError:
# Note(flaper87) If we get here, it means that
# sys.stdin.encoding / sys.getdefaultencoding
# didn't return a suitable encoding to decode
# text. This happens mostly when global LANG
# var is not set correctly and there's no
# default encoding. In this case, most likely
# python will use ASCII or ANSI encoders as
# default encodings but they won't be capable
# of decoding non-ASCII characters.
#
# Also, UTF-8 is being used since it's an ASCII
# extension.
return text.decode('utf-8', errors)
def ensure_str(text, incoming=None,
encoding='utf-8', errors='strict'):
"""
Encodes incoming objects using `encoding`. If
incoming is not specified, text is expected to
be encoded with current python's default encoding.
(`sys.getdefaultencoding`)
:param incoming: Text's current encoding
:param encoding: Expected encoding for text (Default UTF-8)
:param errors: Errors handling policy.
:returns: text or a bytestring `encoding` encoded
representation of it.
"""
if not incoming:
incoming = sys.stdin.encoding or \
sys.getdefaultencoding()
if not isinstance(text, basestring):
# try to convert `text` to string
# This allows this method for receiving
# objs that can be converted to string
text = str(text)
if isinstance(text, unicode):
return text.encode(encoding, errors)
elif text and encoding != incoming:
# Decode text before encoding it with `encoding`
text = ensure_unicode(text, incoming, errors)
return text.encode(encoding, errors)
return text
def getsockopt(self, *args, **kwargs):
"""
A function which allows us to monkey patch eventlet's