summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Gordon <joe.gordon0@gmail.com>2014-02-26 12:11:25 -0800
committerJoe Gordon <joe.gordon0@gmail.com>2014-02-26 17:25:11 -0800
commite0272b0578d2a4f5bd75e68baee1b56f49931266 (patch)
treec9edc5f26b9a5b16d05d4e0bd27782e42758ea39
parentd44e5986925d3129ca0d34599109ad2019295362 (diff)
downloadpython-novaclient-e0272b0578d2a4f5bd75e68baee1b56f49931266.tar.gz
oslo-sync of low hanging fruit
Generated with: ./update.sh --base novaclient --config-file ../python-novaclient/openstack-common.conf --dest-dir ../python-novaclient/ Skipped modules: apiclient and cliutils due to oslo issue in apiclient (cliutils depends on apiclient). https://review.openstack.org/#/c/76718/ Removed non-existent modules from openstack-commit.conf: py3kcompat I06b90f789ae21f2ef8b8071b4298bfc0406482a6 intall_venv_common I84267f3c6726cb2e750f615e107c48b12c6ed353 Synced patches: __init__.py [first sync]: c178e56 Add basic Python 3 tests 12bcdb7 Remove vim header 547ab34 Fix Copyright Headers - Rename LLC to Foundation 96b9a54 Rajaram/Vinkesh|Added nova's serializaiton classes into common c85e1f7 Initial skeleton project gettextutils: 6d55e26 Add support for translating log levels separately afdbc0a Fix E501 in individual openstack projects 6b2d15f Merge "Add support for locales missing from babel" 9d529dd Make Message keep string interpolation args importutils: 885828a Deleted duplicated method in cliutils. strutils: bec3a5e Implements SI/IEC unit system conversion to bytes timeutils: d815087 Merge "Fix spelling errors in comments" 71208fe Fix spelling errors in comments Change-Id: I8f82acb63e61a64eeb6caba9d2d9c81d9cb766d8
-rw-r--r--novaclient/openstack/common/__init__.py2
-rw-r--r--novaclient/openstack/common/gettextutils.py55
-rw-r--r--novaclient/openstack/common/importutils.py7
-rw-r--r--novaclient/openstack/common/strutils.py84
-rw-r--r--novaclient/openstack/common/timeutils.py2
-rw-r--r--openstack-common.conf2
6 files changed, 117 insertions, 35 deletions
diff --git a/novaclient/openstack/common/__init__.py b/novaclient/openstack/common/__init__.py
index e69de29b..2a00f3bc 100644
--- a/novaclient/openstack/common/__init__.py
+++ b/novaclient/openstack/common/__init__.py
@@ -0,0 +1,2 @@
+import six
+six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox'))
diff --git a/novaclient/openstack/common/gettextutils.py b/novaclient/openstack/common/gettextutils.py
index 27f7ec42..98234827 100644
--- a/novaclient/openstack/common/gettextutils.py
+++ b/novaclient/openstack/common/gettextutils.py
@@ -23,6 +23,7 @@ Usual usage in an openstack.common module:
"""
import copy
+import functools
import gettext
import locale
from logging import handlers
@@ -35,6 +36,17 @@ import six
_localedir = os.environ.get('novaclient'.upper() + '_LOCALEDIR')
_t = gettext.translation('novaclient', localedir=_localedir, fallback=True)
+# We use separate translation catalogs for each log level, so set up a
+# mapping between the log level name and the translator. The domain
+# for the log level is project_name + "-log-" + log_level so messages
+# for each level end up in their own catalog.
+_t_log_levels = dict(
+ (level, gettext.translation('novaclient' + '-log-' + level,
+ localedir=_localedir,
+ fallback=True))
+ for level in ['info', 'warning', 'error', 'critical']
+)
+
_AVAILABLE_LANGUAGES = {}
USE_LAZY = False
@@ -60,6 +72,28 @@ def _(msg):
return _t.ugettext(msg)
+def _log_translation(msg, level):
+ """Build a single translation of a log message
+ """
+ if USE_LAZY:
+ return Message(msg, domain='novaclient' + '-log-' + level)
+ else:
+ translator = _t_log_levels[level]
+ if six.PY3:
+ return translator.gettext(msg)
+ return translator.ugettext(msg)
+
+# Translators for log levels.
+#
+# The abbreviated names are meant to reflect the usual use of a short
+# name like '_'. The "L" is for "log" and the other letter comes from
+# the level.
+_LI = functools.partial(_log_translation, level='info')
+_LW = functools.partial(_log_translation, level='warning')
+_LE = functools.partial(_log_translation, level='error')
+_LC = functools.partial(_log_translation, level='critical')
+
+
def install(domain, lazy=False):
"""Install a _() function using the given translation domain.
@@ -118,7 +152,8 @@ class Message(six.text_type):
and can be treated as such.
"""
- def __new__(cls, msgid, msgtext=None, params=None, domain='novaclient', *args):
+ def __new__(cls, msgid, msgtext=None, params=None,
+ domain='novaclient', *args):
"""Create a new Message object.
In order for translation to work gettext requires a message ID, this
@@ -297,9 +332,27 @@ def get_available_languages(domain):
list_identifiers = (getattr(localedata, 'list', None) or
getattr(localedata, 'locale_identifiers'))
locale_identifiers = list_identifiers()
+
for i in locale_identifiers:
if find(i) is not None:
language_list.append(i)
+
+ # NOTE(luisg): Babel>=1.0,<1.3 has a bug where some OpenStack supported
+ # locales (e.g. 'zh_CN', and 'zh_TW') aren't supported even though they
+ # are perfectly legitimate locales:
+ # https://github.com/mitsuhiko/babel/issues/37
+ # In Babel 1.3 they fixed the bug and they support these locales, but
+ # they are still not explicitly "listed" by locale_identifiers().
+ # That is why we add the locales here explicitly if necessary so that
+ # they are listed as supported.
+ aliases = {'zh': 'zh_CN',
+ 'zh_Hant_HK': 'zh_HK',
+ 'zh_Hant': 'zh_TW',
+ 'fil': 'tl_PH'}
+ for (locale, alias) in six.iteritems(aliases):
+ if locale in language_list and alias not in language_list:
+ language_list.append(alias)
+
_AVAILABLE_LANGUAGES[domain] = language_list
return copy.copy(language_list)
diff --git a/novaclient/openstack/common/importutils.py b/novaclient/openstack/common/importutils.py
index 4fd9ae2b..e35b088a 100644
--- a/novaclient/openstack/common/importutils.py
+++ b/novaclient/openstack/common/importutils.py
@@ -58,6 +58,13 @@ def import_module(import_str):
return sys.modules[import_str]
+def import_versioned_module(version, submodule=None):
+ module = 'novaclient.v%s' % version
+ if submodule:
+ module = '.'.join((module, submodule))
+ return import_module(module)
+
+
def try_import(import_str, default=None):
"""Try to import a module and if it fails return default."""
try:
diff --git a/novaclient/openstack/common/strutils.py b/novaclient/openstack/common/strutils.py
index c01de557..1383fbb7 100644
--- a/novaclient/openstack/common/strutils.py
+++ b/novaclient/openstack/common/strutils.py
@@ -17,6 +17,7 @@
System-level utilities and helper functions.
"""
+import math
import re
import sys
import unicodedata
@@ -26,16 +27,21 @@ import six
from novaclient.openstack.common.gettextutils import _
-# Used for looking up extensions of text
-# to their 'multiplied' byte amount
-BYTE_MULTIPLIERS = {
- '': 1,
- 't': 1024 ** 4,
- 'g': 1024 ** 3,
- 'm': 1024 ** 2,
- 'k': 1024,
+UNIT_PREFIX_EXPONENT = {
+ 'k': 1,
+ 'K': 1,
+ 'Ki': 1,
+ 'M': 2,
+ 'Mi': 2,
+ 'G': 3,
+ 'Gi': 3,
+ 'T': 4,
+ 'Ti': 4,
+}
+UNIT_SYSTEM_INFO = {
+ 'IEC': (1024, re.compile(r'(^[-+]?\d*\.?\d+)([KMGT]i?)?(b|bit|B)$')),
+ 'SI': (1000, re.compile(r'(^[-+]?\d*\.?\d+)([kMGT])?(b|bit|B)$')),
}
-BYTE_REGEX = re.compile(r'(^-?\d+)(\D*)')
TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes')
FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no')
@@ -102,7 +108,7 @@ def safe_decode(text, incoming=None, errors='strict'):
:raises TypeError: If text is not an instance of str
"""
if not isinstance(text, six.string_types):
- raise TypeError(_("%s can't be decoded") % type(text))
+ raise TypeError("%s can't be decoded" % type(text))
if isinstance(text, six.text_type):
return text
@@ -145,7 +151,7 @@ def safe_encode(text, incoming=None,
:raises TypeError: If text is not an instance of str
"""
if not isinstance(text, six.string_types):
- raise TypeError(_("%s can't be encoded") % type(text))
+ raise TypeError("%s can't be encoded" % type(text))
if not incoming:
incoming = (sys.stdin.encoding or
@@ -167,34 +173,50 @@ def safe_encode(text, incoming=None,
return text
-def to_bytes(text, default=0):
- """Converts a string into an integer of bytes.
+def string_to_bytes(text, unit_system='IEC', return_int=False):
+ """Converts a string into an float representation of bytes.
+
+ The units supported for IEC ::
+
+ Kb(it), Kib(it), Mb(it), Mib(it), Gb(it), Gib(it), Tb(it), Tib(it)
+ KB, KiB, MB, MiB, GB, GiB, TB, TiB
+
+ The units supported for SI ::
+
+ kb(it), Mb(it), Gb(it), Tb(it)
+ kB, MB, GB, TB
- Looks at the last characters of the text to determine
- what conversion is needed to turn the input text into a byte number.
- Supports "B, K(B), M(B), G(B), and T(B)". (case insensitive)
+ Note that the SI unit system does not support capital letter 'K'
:param text: String input for bytes size conversion.
- :param default: Default return value when text is blank.
+ :param unit_system: Unit system for byte size conversion.
+ :param return_int: If True, returns integer representation of text
+ in bytes. (default: decimal)
+ :returns: Numerical representation of text in bytes.
+ :raises ValueError: If text has an invalid value.
"""
- match = BYTE_REGEX.search(text)
+ try:
+ base, reg_ex = UNIT_SYSTEM_INFO[unit_system]
+ except KeyError:
+ msg = _('Invalid unit system: "%s"') % unit_system
+ raise ValueError(msg)
+ match = reg_ex.match(text)
if match:
- magnitude = int(match.group(1))
- mult_key_org = match.group(2)
- if not mult_key_org:
- return magnitude
- elif text:
+ magnitude = float(match.group(1))
+ unit_prefix = match.group(2)
+ if match.group(3) in ['b', 'bit']:
+ magnitude /= 8
+ else:
msg = _('Invalid string format: %s') % text
- raise TypeError(msg)
+ raise ValueError(msg)
+ if not unit_prefix:
+ res = magnitude
else:
- return default
- mult_key = mult_key_org.lower().replace('b', '', 1)
- multiplier = BYTE_MULTIPLIERS.get(mult_key)
- if multiplier is None:
- msg = _('Unknown byte multiplier: %s') % mult_key_org
- raise TypeError(msg)
- return magnitude * multiplier
+ res = magnitude * pow(base, UNIT_PREFIX_EXPONENT[unit_prefix])
+ if return_int:
+ return int(math.ceil(res))
+ return res
def to_slug(value, incoming=None, errors="strict"):
diff --git a/novaclient/openstack/common/timeutils.py b/novaclient/openstack/common/timeutils.py
index d5ed81d3..52688a02 100644
--- a/novaclient/openstack/common/timeutils.py
+++ b/novaclient/openstack/common/timeutils.py
@@ -114,7 +114,7 @@ def utcnow():
def iso8601_from_timestamp(timestamp):
- """Returns a iso8601 formated date from timestamp."""
+ """Returns a iso8601 formatted date from timestamp."""
return isotime(datetime.datetime.utcfromtimestamp(timestamp))
diff --git a/openstack-common.conf b/openstack-common.conf
index 15081471..e6543063 100644
--- a/openstack-common.conf
+++ b/openstack-common.conf
@@ -1,12 +1,10 @@
[DEFAULT]
# The list of modules to copy from openstack-common
-module=install_venv_common
module=jsonutils
module=strutils
module=timeutils
module=uuidutils
-module=py3kcompat
module=apiclient
module=importutils
module=cliutils