[Kimchi-devel] [PATCH] [Wok] Isolate string utils in order to avoid cyclic import
Daniel Henrique Barboza
dhbarboza82 at gmail.com
Thu Aug 4 18:40:43 UTC 2016
This patch breaks Kimchi and Ginger because you moved functions
from wok.utils and those plug-ins were referencing them:
Failed to import plugin plugins.kimchi.Kimchi, error: Class
plugins.kimchi.Kimchi can not be imported, error: cannot import name
encode_value
Failed to import plugin plugins.ginger.Ginger, error: Class
plugins.ginger.Ginger can not be imported, error: cannot import name
encode_value
The unit tests of all 3 plug-ins breaks too.
On 08/04/2016 02:42 PM, Lucio Correia wrote:
> These functions are basic ones but were not able to be
> imported from message.py since other functions in utils
> were causing cyclic imports. Isolate it to avoid that
> problem.
>
> Signed-off-by: Lucio Correia <luciojhc at linux.vnet.ibm.com>
> ---
> src/wok/control/base.py | 3 +-
> src/wok/reqlogger.py | 3 +-
> src/wok/stringutils.py | 154 ++++++++++++++++++++++++++++++++++++++++++++++++
> src/wok/utils.py | 136 +-----------------------------------------
> 4 files changed, 159 insertions(+), 137 deletions(-)
> create mode 100644 src/wok/stringutils.py
>
> IMPORTANT: apply this along with ginger and gingerbase patches.
>
> diff --git a/src/wok/control/base.py b/src/wok/control/base.py
> index 69541b1..6dfc977 100644
> --- a/src/wok/control/base.py
> +++ b/src/wok/control/base.py
> @@ -33,7 +33,8 @@ from wok.control.utils import validate_params
> from wok.exception import InvalidOperation, UnauthorizedError, WokException
> from wok.message import WokMessage
> from wok.reqlogger import RequestRecord
> -from wok.utils import get_plugin_from_request, utf8_dict, wok_log, encode_value
> +from wok.stringutils import encode_value, utf8_dict
> +from wok.utils import get_plugin_from_request, wok_log
>
>
> # Default request log messages
> diff --git a/src/wok/reqlogger.py b/src/wok/reqlogger.py
> index 8fadbcf..fd02382 100644
> --- a/src/wok/reqlogger.py
> +++ b/src/wok/reqlogger.py
> @@ -30,7 +30,8 @@ from tempfile import NamedTemporaryFile
>
> from wok.config import config, get_log_download_path
> from wok.exception import InvalidParameter, OperationFailed
> -from wok.utils import ascii_dict, remove_old_files
> +from wok.stringutils import ascii_dict
> +from wok.utils import remove_old_files
>
>
> # Log search setup
> diff --git a/src/wok/stringutils.py b/src/wok/stringutils.py
> new file mode 100644
> index 0000000..8f0160b
> --- /dev/null
> +++ b/src/wok/stringutils.py
> @@ -0,0 +1,154 @@
> +#
> +# Project Wok
> +#
> +# Copyright IBM Corp, 2016
> +#
> +# This library is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU Lesser General Public
> +# License as published by the Free Software Foundation; either
> +# version 2.1 of the License, or (at your option) any later version.
> +#
> +# This library is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public
> +# License along with this library; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> +
> +import copy
> +import locale
> +
> +
> +def ascii_dict(base, overlay=None):
> + result = copy.deepcopy(base)
> + result.update(overlay or {})
> +
> + for key, value in result.iteritems():
> + if isinstance(value, unicode):
> + result[key] = str(value.decode('utf-8'))
> +
> + return result
> +
> +
> +def utf8_dict(base, overlay=None):
> + result = copy.deepcopy(base)
> + result.update(overlay or {})
> +
> + for key, value in result.iteritems():
> + if isinstance(value, unicode):
> + result[key] = value.encode('utf-8')
> +
> + return result
> +
> +
> +def encode_value(val):
> + """
> + Convert the value to string.
> + If its unicode, use encode otherwise str.
> + """
> + if isinstance(val, unicode):
> + return val.encode('utf-8')
> + return str(val)
> +
> +
> +def decode_value(val):
> + """
> + Converts value to unicode,
> + if its not an instance of unicode.
> + For doing so convert the val to string,
> + if its not instance of basestring.
> + """
> + if not isinstance(val, basestring):
> + val = str(val)
> + if not isinstance(val, unicode):
> + val = val.decode('utf-8')
> + return val
> +
> +
> +def formatMeasurement(number, settings):
> + '''
> + Refer to "Units of information" (
> + http://en.wikipedia.org/wiki/Units_of_information
> + ) for more information about measurement units.
> +
> + @param number The number to be normalized.
> + @param settings
> + base Measurement base, accepts 2 or 10. defaults to 2.
> + unit The unit of the measurement, e.g., B, Bytes/s, bps, etc.
> + fixed The number of digits after the decimal point.
> + locale The locale for formating the number if not passed
> + format is done as per current locale.
> + @returns [object]
> + v The number part of the measurement.
> + s The suffix part of the measurement including multiple and unit.
> + e.g., kB/s means 1000B/s, KiB/s for 1024B/s.
> + '''
> + unitBaseMapping = {2: [{"us": 'Ki', "v": 1024},
> + {"us": 'Mi', "v": 1048576},
> + {"us": 'Gi', "v": 1073741824},
> + {"us": 'Ti', "v": 1099511627776},
> + {"us": 'Pi', "v": 1125899906842624}],
> + 10: [{"us": 'k', "v": 1000},
> + {"us": 'M', "v": 1000000},
> + {"us": 'G', "v": 1000000000},
> + {"us": 'T', "v": 1000000000000},
> + {"us": 'P', "v": 1000000000000000}]}
> +
> + if(not number):
> + return number
> + settings = settings or {}
> + unit = settings['unit'] if 'unit' in settings else 'B'
> + base = settings['base'] if 'base' in settings else 2
> +
> + new_locale = settings['locale'] if 'locale' in settings else ''
> +
> + if(base != 2 and base != 10):
> + return encode_value(number) + unit
> +
> + fixed = settings['fixed']
> +
> + unitMapping = unitBaseMapping[base]
> + for mapping in reversed(unitMapping):
> + suffix = mapping['us']
> + startingValue = mapping['v']
> + if(number < startingValue):
> + continue
> +
> + formatted = float(number) / startingValue
> + formatted = formatNumber(formatted, fixed, new_locale)
> + return formatted + suffix + unit
> +
> + formatted_number = formatNumber(number, fixed, new_locale)
> + return formatted_number+unit
> +
> +
> +def formatNumber(number, fixed, format_locale):
> + '''
> + Format the number based on format_locale passed.
> + '''
> +
> + # get the current locale
> + current_locale = locale.getlocale()
> + new_locale = ''
> + # set passed locale and set new_locale to same value.
> + if format_locale:
> + new_locale = locale.setlocale(locale.LC_ALL, format_locale)
> +
> + # Based on type of number use the correct formatter
> + if isinstance(number, float):
> + if fixed:
> + formatted = locale.format('%' + '.%df' % fixed, number, True)
> + else:
> + formatted = locale.format('%f', number, True)
> + if isinstance(number, int):
> + formatted = locale.format('%d', number, True)
> + # After formatting is done as per locale, reset the locale if changed.
> + if (new_locale and not current_locale[0] and not current_locale[1]):
> + locale.setlocale(locale.LC_ALL, 'C')
> + elif (new_locale):
> + locale.setlocale(locale.LC_ALL, current_locale[0] + "." +
> + current_locale[1])
> +
> + return formatted
> diff --git a/src/wok/utils.py b/src/wok/utils.py
> index c78a77a..d6bdf0a 100644
> --- a/src/wok/utils.py
> +++ b/src/wok/utils.py
> @@ -21,7 +21,6 @@
> #
>
> import cherrypy
> -import copy
> import glob
> import grp
> import os
> @@ -33,7 +32,6 @@ import subprocess
> import sys
> import traceback
> import xml.etree.ElementTree as ET
> -import locale
>
> from cherrypy.lib.reprconf import Parser
> from datetime import datetime, timedelta
> @@ -43,6 +41,7 @@ from threading import Timer
> from wok.asynctask import AsyncTask
> from wok.config import paths, PluginPaths
> from wok.exception import InvalidParameter, TimeoutExpired
> +from wok.stringutils import decode_value
>
>
> wok_log = cherrypy.log.error_log
> @@ -137,28 +136,6 @@ def get_plugin_from_request():
> return 'wok'
>
>
> -def ascii_dict(base, overlay=None):
> - result = copy.deepcopy(base)
> - result.update(overlay or {})
> -
> - for key, value in result.iteritems():
> - if isinstance(value, unicode):
> - result[key] = str(value.decode('utf-8'))
> -
> - return result
> -
> -
> -def utf8_dict(base, overlay=None):
> - result = copy.deepcopy(base)
> - result.update(overlay or {})
> -
> - for key, value in result.iteritems():
> - if isinstance(value, unicode):
> - result[key] = value.encode('utf-8')
> -
> - return result
> -
> -
> def import_class(class_path):
> module_name, class_name = class_path.rsplit('.', 1)
> try:
> @@ -610,114 +587,3 @@ def upgrade_objectstore_schema(objstore=None, field=None):
> wok_log.error("Cannot upgrade objectstore schema: %s" % e.args[0])
> return False
> return True
> -
> -
> -def encode_value(val):
> - """
> - Convert the value to string.
> - If its unicode, use encode otherwise str.
> - """
> - if isinstance(val, unicode):
> - return val.encode('utf-8')
> - return str(val)
> -
> -
> -def decode_value(val):
> - """
> - Converts value to unicode,
> - if its not an instance of unicode.
> - For doing so convert the val to string,
> - if its not instance of basestring.
> - """
> - if not isinstance(val, basestring):
> - val = str(val)
> - if not isinstance(val, unicode):
> - val = val.decode('utf-8')
> - return val
> -
> -
> -def formatMeasurement(number, settings):
> - '''
> - Refer to "Units of information" (
> - http://en.wikipedia.org/wiki/Units_of_information
> - ) for more information about measurement units.
> -
> - @param number The number to be normalized.
> - @param settings
> - base Measurement base, accepts 2 or 10. defaults to 2.
> - unit The unit of the measurement, e.g., B, Bytes/s, bps, etc.
> - fixed The number of digits after the decimal point.
> - locale The locale for formating the number if not passed
> - format is done as per current locale.
> - @returns [object]
> - v The number part of the measurement.
> - s The suffix part of the measurement including multiple and unit.
> - e.g., kB/s means 1000B/s, KiB/s for 1024B/s.
> - '''
> - unitBaseMapping = {2: [{"us": 'Ki', "v": 1024},
> - {"us": 'Mi', "v": 1048576},
> - {"us": 'Gi', "v": 1073741824},
> - {"us": 'Ti', "v": 1099511627776},
> - {"us": 'Pi', "v": 1125899906842624}],
> - 10: [{"us": 'k', "v": 1000},
> - {"us": 'M', "v": 1000000},
> - {"us": 'G', "v": 1000000000},
> - {"us": 'T', "v": 1000000000000},
> - {"us": 'P', "v": 1000000000000000}]}
> -
> - if(not number):
> - return number
> - settings = settings or {}
> - unit = settings['unit'] if 'unit' in settings else 'B'
> - base = settings['base'] if 'base' in settings else 2
> -
> - new_locale = settings['locale'] if 'locale' in settings else ''
> -
> - if(base != 2 and base != 10):
> - return encode_value(number) + unit
> -
> - fixed = settings['fixed']
> -
> - unitMapping = unitBaseMapping[base]
> - for mapping in reversed(unitMapping):
> - suffix = mapping['us']
> - startingValue = mapping['v']
> - if(number < startingValue):
> - continue
> -
> - formatted = float(number) / startingValue
> - formatted = formatNumber(formatted, fixed, new_locale)
> - return formatted + suffix + unit
> -
> - formatted_number = formatNumber(number, fixed, new_locale)
> - return formatted_number+unit
> -
> -
> -def formatNumber(number, fixed, format_locale):
> - '''
> - Format the number based on format_locale passed.
> - '''
> -
> - # get the current locale
> - current_locale = locale.getlocale()
> - new_locale = ''
> - # set passed locale and set new_locale to same value.
> - if format_locale:
> - new_locale = locale.setlocale(locale.LC_ALL, format_locale)
> -
> - # Based on type of number use the correct formatter
> - if isinstance(number, float):
> - if fixed:
> - formatted = locale.format('%' + '.%df' % fixed, number, True)
> - else:
> - formatted = locale.format('%f', number, True)
> - if isinstance(number, int):
> - formatted = locale.format('%d', number, True)
> - # After formatting is done as per locale, reset the locale if changed.
> - if (new_locale and not current_locale[0] and not current_locale[1]):
> - locale.setlocale(locale.LC_ALL, 'C')
> - elif (new_locale):
> - locale.setlocale(locale.LC_ALL, current_locale[0] + "." +
> - current_locale[1])
> -
> - return formatted
More information about the Kimchi-devel
mailing list