Source code for commonutil.convert

# -*- coding: utf-8 -*-
""" 值轉換輔助函式值 / Value convert functions """

import re
import datetime
from uuid import UUID
from collections import Sequence, Iterable, Mapping

import logging
_log = logging.getLogger(__name__)


[docs]def to_text(v, default_value=None): # type: (Any, Optional[str]) -> Optional[str] """ 將輸入值轉換為字串,當輸入值為 None 或空字串或是無法轉換的物件時傳回 None Convert given variable into string. Return None or given default value when convert failed. Args: v: 要轉換的值或物件 default_value=None: 預設值 Returns: 非空字串,或是 None 當輸入是空字串或是無法轉換的物件 """ if v is None: return default_value # {{{ convert to unicode string r = None if isinstance(v, unicode): r = v elif isinstance(v, str): r = unicode(v, 'utf-8', 'ignore') else: try: r = unicode(str(v), 'utf-8', 'ignore') except Exception: _log.info("cannot convert input (%r) to string @[convert.to_text]", v) r = None # }}} convert to unicode string if r is not None: r = r.strip() if r: return r return default_value
[docs]def to_integer(v, default_value=None): # type: (Any, Optional[int]) -> Optional[int] """ 將輸入值轉換為整數,當輸入值為 None 或是無法轉換的物件時傳回 None Convert given variable into integer. Return None or given default value when convert failed. Args: v: 要轉換的值或物件 default_value=None: 預設值 Returns: 整數,或是 None 當輸入是空字串或是無法轉換的物件 """ if v is None: return default_value try: r = int(v) return r except Exception: _log.info("cannot convert input (%r) to integer @[convert.to_integer]", v) return default_value
[docs]def to_float(v, default_value=None): # type: (Any, Optional[float]) -> Optional[float] """ 將輸入值轉換為浮點數,當輸入值為 None 或是無法轉換的物件時傳回 None Convert given variable into float. Return None or given default value when convert failed. Args: v: 要轉換的值或物件 default_value=None: 預設值 Returns: 非空字串,或是 None 當輸入是空字串或是無法轉換的物件 """ if v is None: return default_value try: r = float(v) return r except Exception: _log.info("cannot convert input (%r) to float @[convert.to_float]", v) return default_value
[docs]def to_bool(v, default_value=None): # type: (Any, Optional[bool]) -> Optional[bool] """ 將輸入值轉換為布林值,當輸入值為 None 或是無法轉換的物件時傳回 None Convert given variable into boolean. Return None or given default value when convert failed. Args: v: 要轉換的值或物件 default_value=None: 預設值 Returns: 布林值,或是 None 當輸入無法轉換 """ if v is None: return default_value try: if isinstance(v, bool): return v if isinstance(v, basestring): if len(v) < 1: return False return True if (str(v[0]) in ('Y', 'y', 'T', 't', '1', '+')) else False elif isinstance(v, (int, float)): return True if (int(v) > 0) else False else: return bool(v) except Exception: _log.info("cannot convert input (%r) to boolean @[convert.to_bool]", v) return default_value
_DATETIME_REGEX_yyyymmddhhmmss = re.compile('([0-9]{4})-?([0-9]{2})-?([0-9]{2})[_T\s\.]?([0-9]{2})?[\:\.\s_]?([0-9]{2})?[\:\.\s_]?([0-9]{2})?') _DATETIME_REGEX_hhmmoffset = re.compile('([-+]?)([0-9]{2})([0-9]{2})?') def _to_datetime_for_basestring(v): v = v.strip() if v in ( "utc-now", "UTC-NOW", "utcnow", "UTCNOW", "now", "NOW", ): return datetime.datetime.utcnow() if v in ( "local-now", "LOCAL-NOW", "localnow", "LOCALNOW", ): return datetime.datetime.now() m = _DATETIME_REGEX_yyyymmddhhmmss.match(v) if m is not None: year = to_integer(m.group(1), 1970) month = to_integer(m.group(2), 1) day = to_integer(m.group(3), 1) hour = to_integer(m.group(4), 0) minute = to_integer(m.group(5), 0) second = to_integer(m.group(6), 0) return datetime.datetime(year, month, day, hour, minute, second) m = _DATETIME_REGEX_hhmmoffset.match(v) if m is not None: direction = m.group(1) hour_offset = to_integer(m.group(2), 0) minute_offset = to_integer(m.group(3), 0) # when not +/- mode, replace given hour and minute into current time as result current_tstamp = datetime.datetime.now() if (direction is None) or (direction == ""): return current_tstamp.replace(hour=hour_offset, minute=minute_offset, second=0) # when not offset to any time point if (hour_offset == 0) and (minute_offset == 0): return current_tstamp # when offset symbol (+/-) is given d = datetime.timedelta(hours=hour_offset, minutes=minute_offset) return (current_tstamp - d) if (direction == '-') else (current_tstamp + d) return None def _to_datetime_for_sequence(v): year = None month = 1 day = 1 hour = 0 minute = 0 second = 0 if len(v) >= 3: year = to_integer(v[0], 1970) month = to_integer(v[1], 1) day = to_integer(v[2], 1) if len(v) >= 4: hour = to_integer(v[3], 0) if len(v) >= 5: minute = to_integer(v[4], 0) if len(v) >= 6: second = to_integer(v[5], 0) # return result if valid return None if (year is None) else datetime.datetime(year, month, day, hour, minute, second)
[docs]def to_datetime(v, default_value=None): # type: (Any, Optional[datetime.datetime]) -> Optional[datetime.datetime] """ 將輸入值轉換為時間格式,當輸入值為 None 或是無法轉換的物件時傳回 None Convert given variable into datetime.datetime object. Return None or given default value when convert failed. 輸入範例 / Input Examples: 整數/浮點數 (視為 UNIX time-stamp) / Integer or Float (will treat as UNIT time-stamp): 1352454146.387523 字串 / String: '2012-11-10 10:10:10', '+01' (加 1 小時), '+0123' (加 1 小時 23 分鐘) 串列或數對 / List or Tuple): (2012, 11, 10, 10, 10, 10, 0, 0, 0,) Args: v: 要轉換的值或物件 default_value=None: 預設值 Returns: 時間格式,或是 None 當輸入無法轉換 """ if v is None: return default_value if isinstance(v, datetime.datetime): return v elif isinstance(v, (int, float)): return datetime.datetime.fromtimestamp(v) elif isinstance(v, basestring): r = _to_datetime_for_basestring(v) elif isinstance(v, Sequence): r = _to_datetime_for_sequence(v) if r is not None: return r _log.info("cannot convert input (%r) to datetime @[convert.to_datetime]", v) return default_value
[docs]def to_uuid(v, default_value=None): # type: (Any, Optional[uuid.UUID]) -> Optional[uuid.UUID] """ 將輸入值轉換為 UUID 物件 Convert given variable into UUID object. Return None or given default value when convert failed. Args: v: 要轉換的值或物件 default_value=None: 預設值 Returns: uuid.UUID 物件實體,或是 None 當輸入無法轉換 """ if v is None: return default_value if isinstance(v, UUID): return v try: aux = UUID(v) return aux except Exception: pass return default_value
[docs]def to_list(v, element_converter, default_value=None): # type: (Any, Callable[[Any], Any], Optional[Any]) -> Optional[List[Any]] """ 將輸入值轉換為串列,各輸入值透過傳入的轉換函式進行轉換 Convert given variable into list object with given element convert function. Return None or given default value when convert failed or result into empty list. Args: v: 要轉換的值或物件 element_converter (callable): 單一個元素的轉換函式,當轉換結果為 None 時此元素會被丟棄 default_value=None: 預設值 Returns: 串列,或是 None 當輸入無法轉換 """ if v is None: return default_value result = [] if (not isinstance(v, basestring)) and (not isinstance(v, Mapping)) and isinstance(v, Iterable): for e in v: item = element_converter(e) if item is not None: result.append(item) else: item = element_converter(v) if item is not None: result.append(item) return result if result else default_value
[docs]def to_dict(v, element_converter, key_converter=None, default_value=None): # type: (Any, Callable[[Any], Any], Optional[Callable[[Any], Any]], Optional[Any]) -> Optional[Dict[Any, Any]] """ 將輸入值轉換為字典,各輸入值透過傳入的轉換函式進行轉換 Convert given variable into dict object with given key and value convert function. Return None or given default value when convert failed or result into empty dict. Args: v: 要轉換的值或物件 element_converter (callable): 單一個元素的轉換函式,當轉換結果為 None 時此元素會被丟棄 key_converter=None (callable): 單一元素對應之鍵值的轉換函式,當轉換結果為 None 時此元素會被丟棄 default_value=None: 預設值 Return: 字典,或是 None 當輸入無法轉換 """ if v is None: return default_value if key_converter is None: key_converter = to_text result = {} try: for k, e in v.iteritems(): kidx = key_converter(k) if kidx is None: continue item = element_converter(e) if item is not None: result[kidx] = item except Exception as e: _log.exception("failed on convert dictionary: %r", e) return result if result else default_value
_HOSTPORT_ADDR_REGEX = re.compile("(.+)\\:([0-9]+)$")
[docs]def parse_hostport_location(loc, default_value=None): # type: (str, Optional[Tuple[str, int]]) -> Tuple[str, int] """ 解析 Host:Port 型式的字串為 (Host, Port,) 型式的 tuple 物件 Parse string in "Host:Port" form into tuple object in (Host, Port,) form. Args: loc (str): 要轉換的位址字串 default_value=None: 當無法轉換時的預設值 Returns: 轉換結果,或是當失敗時為預設值 """ m = _HOSTPORT_ADDR_REGEX.match(str(loc)) if m is not None: addr = m.group(1) port = int(m.group(2)) return (addr, port) return default_value
[docs]def parse_hostport_location_list(location_list): # type: (List[str]) -> List[Tuple[str, int]] """ 解析 Host:Port 型式的字串 list 為 (Host, Port,) 型式的 tuple 物件所構成的 list Parse list of strings in "Host:Port" form into list of tuple objects in (Host, Port,) form. Args: location_list (list of str): 要轉換的位址字串串列 Returns: 轉換結果,或是當失敗時為空的 tuple 物件 """ return to_list(location_list, parse_hostport_location, ())
# vim: ts=4 sw=4 ai nowrap