From: Frank Brehm Date: Tue, 20 Mar 2018 13:38:01 +0000 (+0100) Subject: Adding lib/cr_vmware_tpl/common.py X-Git-Tag: 0.1.1~111 X-Git-Url: https://git.uhu-banane.net/?a=commitdiff_plain;h=6946ab8e67ff0d859af76e5822342a50ffd2bf7d;p=pixelpark%2Fcreate-vmware-tpl.git Adding lib/cr_vmware_tpl/common.py --- diff --git a/lib/cr_vmware_tpl/common.py b/lib/cr_vmware_tpl/common.py new file mode 100644 index 0000000..e0d7729 --- /dev/null +++ b/lib/cr_vmware_tpl/common.py @@ -0,0 +1,387 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +@author: Frank Brehm +@contact: frank.brehm@pixelpark.com +@copyright: © 2018 by Frank Brehm, Berlin +@summary: The module for common used functions. +""" + +# Standard modules +import sys +import os +import logging +import re +import pprint +import platform +import locale + +# Third party modules +import six + +# Own modules + +__version__ = '0.5.3' + +LOG = logging.getLogger(__name__) + +RE_YES = re.compile(r'^\s*(?:y(?:es)?|true)\s*$', re.IGNORECASE) +RE_NO = re.compile(r'^\s*(?:no?|false|off)\s*$', re.IGNORECASE) +PAT_TO_BOOL_TRUE = locale.nl_langinfo(locale.YESEXPR) +RE_TO_BOOL_TRUE = re.compile(PAT_TO_BOOL_TRUE) +PAT_TO_BOOL_FALSE = locale.nl_langinfo(locale.NOEXPR) +RE_TO_BOOL_FALSE = re.compile(PAT_TO_BOOL_FALSE) + +RE_DOT = re.compile(r'\.') +RE_DOT_AT_END = re.compile(r'(\.)*$') +RE_DECIMAL = re.compile(r'^\d+$') +RE_IPV4_PTR = re.compile(r'\.in-addr\.arpa\.$', re.IGNORECASE) +RE_IPV6_PTR = re.compile(r'\.ip6\.arpa\.$', re.IGNORECASE) + + +# ============================================================================= +def pp(value, indent=4, width=99, depth=None): + """ + Returns a pretty print string of the given value. + + @return: pretty print string + @rtype: str + """ + + pretty_printer = pprint.PrettyPrinter( + indent=indent, width=width, depth=depth) + return pretty_printer.pformat(value) + + +# ============================================================================= +def terminal_can_colors(debug=False): + """ + Method to detect, whether the current terminal (stdout and stderr) + is able to perform ANSI color sequences. + + @return: both stdout and stderr can perform ANSI color sequences + @rtype: bool + + """ + + cur_term = '' + if 'TERM' in os.environ: + cur_term = os.environ['TERM'].lower().strip() + + colored_term_list = ( + r'ansi', + r'linux.*', + r'screen.*', + r'[xeak]term.*', + r'gnome.*', + r'rxvt.*', + r'interix', + ) + term_pattern = r'^(?:' + r'|'.join(colored_term_list) + r')$' + re_term = re.compile(term_pattern) + + ansi_term = False + env_term_has_colors = False + + if cur_term: + if cur_term == 'ansi': + env_term_has_colors = True + ansi_term = True + elif re_term.search(cur_term): + env_term_has_colors = True + if debug: + sys.stderr.write( + "ansi_term: %r, env_term_has_colors: %r\n" % ( + ansi_term, env_term_has_colors)) + + has_colors = False + if env_term_has_colors: + has_colors = True + for handle in [sys.stdout, sys.stderr]: + if (hasattr(handle, "isatty") and handle.isatty()): + if debug: + sys.stderr.write("%s is a tty.\n" % (handle.name)) + if (platform.system() == 'Windows' and not ansi_term): + if debug: + sys.stderr.write("platform is Windows and not ansi_term.\n") + has_colors = False + else: + if debug: + sys.stderr.write("%s is not a tty.\n" % (handle.name)) + if ansi_term: + pass + else: + has_colors = False + + return has_colors + + +# ============================================================================= +def to_bool(value): + """ + Converter from string to boolean values (e.g. from configurations) + """ + + if not value: + return False + + try: + v_int = int(value) + except ValueError: + pass + except TypeError: + pass + else: + if v_int == 0: + return False + else: + return True + + global PAT_TO_BOOL_TRUE + global RE_TO_BOOL_TRUE + global PAT_TO_BOOL_FALSE + global RE_TO_BOOL_FALSE + + c_yes_expr = locale.nl_langinfo(locale.YESEXPR) + if c_yes_expr != PAT_TO_BOOL_TRUE: + PAT_TO_BOOL_TRUE = c_yes_expr + RE_TO_BOOL_TRUE = re.compile(PAT_TO_BOOL_TRUE) + # LOG.debug("Current pattern for 'yes': %r.", c_yes_expr) + + c_no_expr = locale.nl_langinfo(locale.NOEXPR) + if c_no_expr != PAT_TO_BOOL_FALSE: + PAT_TO_BOOL_FALSE = c_no_expr + RE_TO_BOOL_FALSE = re.compile(PAT_TO_BOOL_FALSE) + # LOG.debug("Current pattern for 'no': %r.", c_no_expr) + + v_str = '' + if isinstance(value, str): + v_str = value + if six.PY2: + if isinstance(value, unicode): # noqa + v_str = value.encode('utf-8') + elif six.PY3 and isinstance(value, bytes): + v_str = value.decode('utf-8') + else: + v_str = str(value) + + match = RE_YES.search(v_str) + if match: + return True + match = RE_TO_BOOL_TRUE.search(v_str) + if match: + return True + + match = RE_NO.search(v_str) + if match: + return False + match = RE_TO_BOOL_FALSE.search(v_str) + if match: + return False + + return bool(value) + + +# ============================================================================= +def to_unicode(obj, encoding='utf-8'): + + do_decode = False + if six.PY2: + if isinstance(obj, str): + do_decode = True + else: + if isinstance(obj, bytes): + do_decode = True + + if do_decode: + obj = obj.decode(encoding) + + return obj + + +# ============================================================================= +def to_utf8(obj): + + return encode_or_bust(obj, 'utf-8') + + +# ============================================================================= +def encode_or_bust(obj, encoding='utf-8'): + + do_encode = False + if six.PY2: + if isinstance(obj, unicode): # noqa + do_encode = True + else: + if isinstance(obj, str): + do_encode = True + + if do_encode: + obj = obj.encode(encoding) + + return obj + + +# ============================================================================= +def to_bytes(obj, encoding='utf-8'): + "Wrapper for encode_or_bust()" + + return encode_or_bust(obj, encoding) + + +# ============================================================================= +def to_str(obj, encoding='utf-8'): + """ + Transformes the given string-like object into the str-type according + to the current Python version. + """ + + if six.PY2: + return encode_or_bust(obj, encoding) + else: + return to_unicode(obj, encoding) + + +# ============================================================================= +def caller_search_path(): + """ + Builds a search path for executables from environment $PATH + including some standard paths. + + @return: all existing search paths + @rtype: list + """ + + path_list = [] + search_path = os.environ['PATH'] + if not search_path: + search_path = os.defpath + + search_path_list = [ + '/opt/PPlocal/bin', + ] + + for d in search_path.split(os.pathsep): + search_path_list.append(d) + + default_path = [ + '/bin', + '/usr/bin', + '/usr/local/bin', + '/sbin', + '/usr/sbin', + '/usr/local/sbin', + '/usr/ucb', + '/usr/sfw/bin', + '/opt/csw/bin', + '/usr/openwin/bin', + '/usr/ccs/bin', + ] + + for d in default_path: + search_path_list.append(d) + + for d in search_path_list: + if not os.path.exists(d): + continue + if not os.path.isdir(d): + continue + d_abs = os.path.realpath(d) + if d_abs not in path_list: + path_list.append(d_abs) + + return path_list + +# ============================================================================= +def compare_fqdn(x, y): + + # LOG.debug("Comparing {!r} <=> {!r}.".format(x, y)) + + # First check for None values + if x is None and y is None: + return 0 + if x is None: + return -1 + if y is None: + return 1 + + # Check for empty FQDNs + xs = str(x).strip().lower() + ys = str(y).strip().lower() + + if xs == '' and ys == '': + return 0 + if xs == '': + return -1 + if ys == '': + return 1 + + # Ensure a dot at end + xs = RE_DOT_AT_END.sub('.', xs) + ys = RE_DOT_AT_END.sub('.', ys) + + if xs == ys: + return 0 + + # Reverse IPv4 zones first, then reverse IPv6 zones + if RE_IPV4_PTR.search(xs): + if not RE_IPV4_PTR.search(ys): + return -1 + elif RE_IPV4_PTR.search(ys): + if not RE_IPV4_PTR.search(xs): + return 1 + elif RE_IPV6_PTR.search(xs): + if not RE_IPV6_PTR.search(ys): + return -1 + elif RE_IPV6_PTR.search(ys): + if not RE_IPV6_PTR.search(xs): + return 1 + + return compare_fqdn_tokens(xs, ys) + +# ============================================================================= +def compare_fqdn_tokens(xs, ys): + + xa = RE_DOT.split(xs) + xa.reverse() + xa.pop(0) + + ya = RE_DOT.split(ys) + ya.reverse() + ya.pop(0) + + # Compare token from the last to the first + nr_tokens = min(len(xa), len(ya)) + while nr_tokens > 0: + token_x = xa.pop(0) + token_y = ya.pop(0) + if RE_DECIMAL.match(token_x) and RE_DECIMAL.match(token_y): + num_x = int(token_x) + num_y = int(token_y) + if num_x < num_y: + return -1 + elif num_x > num_y: + return 1 + else: + if token_x < token_y: + return -1 + elif token_x > token_y: + return 1 + nr_tokens -= 1 + + if len(xa): + return 1 + if len(ya): + return -1 + + return 0 + +# ============================================================================= + +if __name__ == "__main__": + + pass + +# ============================================================================= + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4