Import strutils from oslo, and convert to it.
The only change of behaviour here (according to the former glance unit tests) is that 'T' now means True not False. I suspect that's ok. Change-Id: Icf98f913a3f78a1fe2f38a82a25a071c2da03739
This commit is contained in:
parent
f09c52c8b0
commit
9356ea634d
@ -44,6 +44,7 @@ from glance.common import utils
|
|||||||
from glance.common import wsgi
|
from glance.common import wsgi
|
||||||
from glance import notifier
|
from glance import notifier
|
||||||
import glance.openstack.common.log as logging
|
import glance.openstack.common.log as logging
|
||||||
|
from glance.openstack.common import strutils
|
||||||
import glance.registry.client.v1.api as registry
|
import glance.registry.client.v1.api as registry
|
||||||
from glance.store import (get_from_backend,
|
from glance.store import (get_from_backend,
|
||||||
get_size_from_backend,
|
get_size_from_backend,
|
||||||
@ -634,7 +635,7 @@ class Controller(controller.BaseController):
|
|||||||
# properties NOT to be purged. However we also disable purging of
|
# properties NOT to be purged. However we also disable purging of
|
||||||
# properties if an image file is being uploaded...
|
# properties if an image file is being uploaded...
|
||||||
purge_props = req.headers.get('x-glance-registry-purge-props', True)
|
purge_props = req.headers.get('x-glance-registry-purge-props', True)
|
||||||
purge_props = (utils.bool_from_string(purge_props) and
|
purge_props = (strutils.bool_from_string(purge_props) and
|
||||||
image_data is None)
|
image_data is None)
|
||||||
|
|
||||||
if image_data is not None and orig_status != 'queued':
|
if image_data is not None and orig_status != 'queued':
|
||||||
|
@ -41,6 +41,7 @@ from webob import exc
|
|||||||
|
|
||||||
from glance.common import exception
|
from glance.common import exception
|
||||||
import glance.openstack.common.log as logging
|
import glance.openstack.common.log as logging
|
||||||
|
from glance.openstack.common import strutils
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
@ -245,22 +246,10 @@ def get_image_meta_from_headers(response):
|
|||||||
raise exception.Invalid
|
raise exception.Invalid
|
||||||
for key in ('is_public', 'deleted', 'protected'):
|
for key in ('is_public', 'deleted', 'protected'):
|
||||||
if key in result:
|
if key in result:
|
||||||
result[key] = bool_from_string(result[key])
|
result[key] = strutils.bool_from_string(result[key])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def bool_from_string(subject):
|
|
||||||
"""Interpret a string as a boolean-like value."""
|
|
||||||
if isinstance(subject, bool):
|
|
||||||
return subject
|
|
||||||
elif isinstance(subject, int):
|
|
||||||
return subject == 1
|
|
||||||
if hasattr(subject, 'startswith'): # str or unicode...
|
|
||||||
if subject.strip().lower() in ('true', 'on', '1', 'yes', 'y'):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def safe_mkdirs(path):
|
def safe_mkdirs(path):
|
||||||
try:
|
try:
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
|
150
glance/openstack/common/strutils.py
Normal file
150
glance/openstack/common/strutils.py
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2011 OpenStack Foundation.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
"""
|
||||||
|
System-level utilities and helper functions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from glance.openstack.common.gettextutils import _
|
||||||
|
|
||||||
|
|
||||||
|
TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes')
|
||||||
|
FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no')
|
||||||
|
|
||||||
|
|
||||||
|
def int_from_bool_as_string(subject):
|
||||||
|
"""
|
||||||
|
Interpret a string as a boolean and return either 1 or 0.
|
||||||
|
|
||||||
|
Any string value in:
|
||||||
|
|
||||||
|
('True', 'true', 'On', 'on', '1')
|
||||||
|
|
||||||
|
is interpreted as a boolean True.
|
||||||
|
|
||||||
|
Useful for JSON-decoded stuff and config file parsing
|
||||||
|
"""
|
||||||
|
return bool_from_string(subject) and 1 or 0
|
||||||
|
|
||||||
|
|
||||||
|
def bool_from_string(subject, strict=False):
|
||||||
|
"""
|
||||||
|
Interpret a string as a boolean.
|
||||||
|
|
||||||
|
A case-insensitive match is performed such that strings matching 't',
|
||||||
|
'true', 'on', 'y', 'yes', or '1' are considered True and, when
|
||||||
|
`strict=False`, anything else is considered False.
|
||||||
|
|
||||||
|
Useful for JSON-decoded stuff and config file parsing.
|
||||||
|
|
||||||
|
If `strict=True`, unrecognized values, including None, will raise a
|
||||||
|
ValueError which is useful when parsing values passed in from an API call.
|
||||||
|
Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'.
|
||||||
|
"""
|
||||||
|
if not isinstance(subject, basestring):
|
||||||
|
subject = str(subject)
|
||||||
|
|
||||||
|
lowered = subject.strip().lower()
|
||||||
|
|
||||||
|
if lowered in TRUE_STRINGS:
|
||||||
|
return True
|
||||||
|
elif lowered in FALSE_STRINGS:
|
||||||
|
return False
|
||||||
|
elif strict:
|
||||||
|
acceptable = ', '.join(
|
||||||
|
"'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS))
|
||||||
|
msg = _("Unrecognized value '%(val)s', acceptable values are:"
|
||||||
|
" %(acceptable)s") % {'val': subject,
|
||||||
|
'acceptable': acceptable}
|
||||||
|
raise ValueError(msg)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def safe_decode(text, incoming=None, errors='strict'):
|
||||||
|
"""
|
||||||
|
Decodes incoming str using `incoming` if they're
|
||||||
|
not already unicode.
|
||||||
|
|
||||||
|
:param incoming: Text's current encoding
|
||||||
|
:param errors: Errors handling policy. See here for valid
|
||||||
|
values http://docs.python.org/2/library/codecs.html
|
||||||
|
:returns: text or a unicode `incoming` encoded
|
||||||
|
representation of it.
|
||||||
|
:raises TypeError: If text is not an isntance of basestring
|
||||||
|
"""
|
||||||
|
if not isinstance(text, basestring):
|
||||||
|
raise TypeError("%s can't be decoded" % type(text))
|
||||||
|
|
||||||
|
if isinstance(text, unicode):
|
||||||
|
return text
|
||||||
|
|
||||||
|
if not incoming:
|
||||||
|
incoming = (sys.stdin.encoding or
|
||||||
|
sys.getdefaultencoding())
|
||||||
|
|
||||||
|
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 safe_encode(text, incoming=None,
|
||||||
|
encoding='utf-8', errors='strict'):
|
||||||
|
"""
|
||||||
|
Encodes incoming str/unicode 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. See here for valid
|
||||||
|
values http://docs.python.org/2/library/codecs.html
|
||||||
|
:returns: text or a bytestring `encoding` encoded
|
||||||
|
representation of it.
|
||||||
|
:raises TypeError: If text is not an isntance of basestring
|
||||||
|
"""
|
||||||
|
if not isinstance(text, basestring):
|
||||||
|
raise TypeError("%s can't be encoded" % type(text))
|
||||||
|
|
||||||
|
if not incoming:
|
||||||
|
incoming = (sys.stdin.encoding or
|
||||||
|
sys.getdefaultencoding())
|
||||||
|
|
||||||
|
if isinstance(text, unicode):
|
||||||
|
return text.encode(encoding, errors)
|
||||||
|
elif text and encoding != incoming:
|
||||||
|
# Decode text before encoding it with `encoding`
|
||||||
|
text = safe_decode(text, incoming, errors)
|
||||||
|
return text.encode(encoding, errors)
|
||||||
|
|
||||||
|
return text
|
@ -27,6 +27,7 @@ from glance.common import utils
|
|||||||
from glance.common import wsgi
|
from glance.common import wsgi
|
||||||
import glance.db
|
import glance.db
|
||||||
import glance.openstack.common.log as logging
|
import glance.openstack.common.log as logging
|
||||||
|
from glance.openstack.common import strutils
|
||||||
from glance.openstack.common import timeutils
|
from glance.openstack.common import timeutils
|
||||||
from glance.openstack.common import uuidutils
|
from glance.openstack.common import uuidutils
|
||||||
|
|
||||||
@ -273,7 +274,7 @@ class Controller(object):
|
|||||||
deleted = req.params.get('deleted')
|
deleted = req.params.get('deleted')
|
||||||
if deleted is None:
|
if deleted is None:
|
||||||
return None
|
return None
|
||||||
return utils.bool_from_string(deleted)
|
return strutils.bool_from_string(deleted)
|
||||||
|
|
||||||
def show(self, req, id):
|
def show(self, req, id):
|
||||||
"""Return data about the given image id."""
|
"""Return data about the given image id."""
|
||||||
|
@ -118,13 +118,6 @@ class TestUtils(test_utils.BaseTestCase):
|
|||||||
|
|
||||||
self.assertRaises(exception.ImageSizeLimitExceeded, _consume_all_read)
|
self.assertRaises(exception.ImageSizeLimitExceeded, _consume_all_read)
|
||||||
|
|
||||||
def test_bool_from_string(self):
|
|
||||||
actual = utils.bool_from_string('true')
|
|
||||||
self.assertEqual(True, actual)
|
|
||||||
|
|
||||||
actual = utils.bool_from_string(1)
|
|
||||||
self.assertEqual(True, actual)
|
|
||||||
|
|
||||||
def test_get_meta_from_headers(self):
|
def test_get_meta_from_headers(self):
|
||||||
resp = webob.Response()
|
resp = webob.Response()
|
||||||
resp.headers = {"x-image-meta-*": 'test'}
|
resp.headers = {"x-image-meta-*": 'test'}
|
||||||
|
@ -24,23 +24,6 @@ from glance.tests import utils as test_utils
|
|||||||
|
|
||||||
class UtilsTestCase(test_utils.BaseTestCase):
|
class UtilsTestCase(test_utils.BaseTestCase):
|
||||||
|
|
||||||
def test_bool_from_string(self):
|
|
||||||
true_values = ['True', True, 'true', 'TRUE', '1', 1, 'on',
|
|
||||||
'ON', 'y', 'yes', 'Y', 'YES']
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
for value in true_values:
|
|
||||||
self.assertTrue(utils.bool_from_string(value),
|
|
||||||
"Got False for value: %r (%d)" % (value, i))
|
|
||||||
i = i + 1
|
|
||||||
|
|
||||||
false_values = ['False', False, 'false', 'T', 'F', 'FALSE',
|
|
||||||
'0', 0, 9, 'off', 'OFF', 'no', 'n', 'NO', 'N']
|
|
||||||
|
|
||||||
for value in false_values:
|
|
||||||
self.assertFalse(utils.bool_from_string(value),
|
|
||||||
"Got True for value: %r" % value)
|
|
||||||
|
|
||||||
def test_encryption(self):
|
def test_encryption(self):
|
||||||
# Check that original plaintext and unencrypted ciphertext match
|
# Check that original plaintext and unencrypted ciphertext match
|
||||||
# Check keys of the three allowed lengths
|
# Check keys of the three allowed lengths
|
||||||
|
@ -10,6 +10,7 @@ module=log
|
|||||||
module=notifier
|
module=notifier
|
||||||
module=policy
|
module=policy
|
||||||
module=setup
|
module=setup
|
||||||
|
module=strutils
|
||||||
module=timeutils
|
module=timeutils
|
||||||
module=uuidutils
|
module=uuidutils
|
||||||
module=version
|
module=version
|
||||||
|
Loading…
Reference in New Issue
Block a user