"Fossies" - the Fresh Open Source Software Archive

Member "salt-3002.2/salt/_compat.py" (18 Nov 2020, 7368 Bytes) of package /linux/misc/salt-3002.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "_compat.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3002.1_vs_3002.2.

    1 """
    2 Salt compatibility code
    3 """
    4 # pylint: disable=import-error,unused-import,invalid-name,W0231,W0233
    5 
    6 
    7 import binascii
    8 import logging
    9 import sys
   10 
   11 from salt.exceptions import SaltException
   12 from salt.ext.six import binary_type, integer_types, string_types, text_type
   13 from salt.ext.six.moves import StringIO, cStringIO
   14 
   15 log = logging.getLogger(__name__)
   16 
   17 try:
   18     # Python >2.5
   19     import xml.etree.cElementTree as ElementTree
   20 except Exception:  # pylint: disable=broad-except
   21     try:
   22         # Python >2.5
   23         import xml.etree.ElementTree as ElementTree
   24     except Exception:  # pylint: disable=broad-except
   25         try:
   26             # normal cElementTree install
   27             import elementtree.cElementTree as ElementTree
   28         except Exception:  # pylint: disable=broad-except
   29             try:
   30                 # normal ElementTree install
   31                 import elementtree.ElementTree as ElementTree
   32             except Exception:  # pylint: disable=broad-except
   33                 ElementTree = None
   34 
   35 
   36 # True if we are running on Python 3.
   37 PY3 = sys.version_info.major == 3
   38 
   39 
   40 if PY3:
   41     import builtins
   42 
   43     exceptions = builtins
   44 else:
   45     import exceptions
   46 
   47 
   48 if ElementTree is not None:
   49     if not hasattr(ElementTree, "ParseError"):
   50 
   51         class ParseError(Exception):
   52             """
   53             older versions of ElementTree do not have ParseError
   54             """
   55 
   56         ElementTree.ParseError = ParseError
   57 
   58 
   59 def text_(s, encoding="latin-1", errors="strict"):
   60     """
   61     If ``s`` is an instance of ``binary_type``, return
   62     ``s.decode(encoding, errors)``, otherwise return ``s``
   63     """
   64     return s.decode(encoding, errors) if isinstance(s, binary_type) else s
   65 
   66 
   67 def bytes_(s, encoding="latin-1", errors="strict"):
   68     """
   69     If ``s`` is an instance of ``text_type``, return
   70     ``s.encode(encoding, errors)``, otherwise return ``s``
   71     """
   72     return s.encode(encoding, errors) if isinstance(s, text_type) else s
   73 
   74 
   75 def ascii_native_(s):
   76     """
   77     Python 3: If ``s`` is an instance of ``text_type``, return
   78     ``s.encode('ascii')``, otherwise return ``str(s, 'ascii', 'strict')``
   79 
   80     Python 2: If ``s`` is an instance of ``text_type``, return
   81     ``s.encode('ascii')``, otherwise return ``str(s)``
   82     """
   83     if isinstance(s, text_type):
   84         s = s.encode("ascii")
   85 
   86     return str(s, "ascii", "strict") if PY3 else s
   87 
   88 
   89 def native_(s, encoding="latin-1", errors="strict"):
   90     """
   91     Python 3: If ``s`` is an instance of ``text_type``, return ``s``, otherwise
   92     return ``str(s, encoding, errors)``
   93 
   94     Python 2: If ``s`` is an instance of ``text_type``, return
   95     ``s.encode(encoding, errors)``, otherwise return ``str(s)``
   96     """
   97     if PY3:
   98         out = s if isinstance(s, text_type) else str(s, encoding, errors)
   99     else:
  100         out = s.encode(encoding, errors) if isinstance(s, text_type) else str(s)
  101 
  102     return out
  103 
  104 
  105 def string_io(data=None):  # cStringIO can't handle unicode
  106     """
  107     Pass data through to stringIO module and return result
  108     """
  109     try:
  110         return cStringIO(bytes(data))
  111     except (UnicodeEncodeError, TypeError):
  112         return StringIO(data)
  113 
  114 
  115 try:
  116     if PY3:
  117         import ipaddress
  118     else:
  119         import salt.ext.ipaddress as ipaddress
  120 except ImportError:
  121     ipaddress = None
  122 
  123 
  124 class IPv6AddressScoped(ipaddress.IPv6Address):
  125     """
  126     Represent and manipulate single IPv6 Addresses.
  127     Scope-aware version
  128     """
  129 
  130     def __init__(self, address):
  131         """
  132         Instantiate a new IPv6 address object. Scope is moved to an attribute 'scope'.
  133 
  134         Args:
  135             address: A string or integer representing the IP
  136 
  137               Additionally, an integer can be passed, so
  138               IPv6Address('2001:db8::') == IPv6Address(42540766411282592856903984951653826560)
  139               or, more generally
  140               IPv6Address(int(IPv6Address('2001:db8::'))) == IPv6Address('2001:db8::')
  141 
  142         Raises:
  143             AddressValueError: If address isn't a valid IPv6 address.
  144 
  145         :param address:
  146         """
  147         # pylint: disable-all
  148         if not hasattr(self, "_is_packed_binary"):
  149             # This method (below) won't be around for some Python 3 versions
  150             # and we need check this differently anyway
  151             self._is_packed_binary = lambda p: isinstance(p, bytes)
  152         # pylint: enable-all
  153         if isinstance(address, string_types) and "%" in address:
  154             buff = address.split("%")
  155             if len(buff) != 2:
  156                 raise SaltException('Invalid IPv6 address: "{}"'.format(address))
  157             address, self.__scope = buff
  158         else:
  159             self.__scope = None
  160 
  161         # For compatibility with python3.9 ipaddress
  162         self._scope_id = self.__scope
  163 
  164         if sys.version_info.major == 2:
  165             ipaddress._BaseAddress.__init__(self, address)
  166             ipaddress._BaseV6.__init__(self, address)
  167         else:
  168             # Python 3.4 fix. Versions higher are simply not affected
  169             # https://github.com/python/cpython/blob/3.4/Lib/ipaddress.py#L543-L544
  170             self._version = 6
  171             self._max_prefixlen = ipaddress.IPV6LENGTH
  172 
  173         # Efficient constructor from integer.
  174         if isinstance(address, integer_types):
  175             self._check_int_address(address)
  176             self._ip = address
  177         elif self._is_packed_binary(address):
  178             self._check_packed_address(address, 16)
  179             self._ip = int(binascii.hexlify(address), 16)
  180         else:
  181             address = str(address)
  182             if "/" in address:
  183                 raise ipaddress.AddressValueError(
  184                     "Unexpected '/' in {}".format(address)
  185                 )
  186             self._ip = self._ip_int_from_string(address)
  187 
  188     def _is_packed_binary(self, data):
  189         """
  190         Check if data is hexadecimal packed
  191 
  192         :param data:
  193         :return:
  194         """
  195         packed = False
  196         if isinstance(data, bytes) and len(data) == 16 and b":" not in data:
  197             try:
  198                 packed = bool(int(binascii.hexlify(data), 16))
  199             except ValueError:
  200                 pass
  201 
  202         return packed
  203 
  204     @property
  205     def scope(self):
  206         """
  207         Return scope of IPv6 address.
  208 
  209         :return:
  210         """
  211         return self.__scope
  212 
  213     def __str__(self):
  214         return text_type(
  215             self._string_from_ip_int(self._ip)
  216             + ("%" + self.scope if self.scope is not None else "")
  217         )
  218 
  219 
  220 class IPv6InterfaceScoped(ipaddress.IPv6Interface, IPv6AddressScoped):
  221     """
  222     Update
  223     """
  224 
  225     def __init__(self, address):
  226         if (
  227             PY3
  228             and isinstance(address, (bytes, int))
  229             or not PY3
  230             and isinstance(address, int)
  231         ):
  232             IPv6AddressScoped.__init__(self, address)
  233             self.network = ipaddress.IPv6Network(self._ip)
  234             self._prefixlen = self._max_prefixlen
  235             return
  236 
  237         addr = ipaddress._split_optional_netmask(address)
  238         IPv6AddressScoped.__init__(self, addr[0])
  239         self.network = ipaddress.IPv6Network(address, strict=False)
  240         self.netmask = self.network.netmask
  241         self._prefixlen = self.network._prefixlen
  242         self.hostmask = self.network.hostmask
  243 
  244 
  245 if ipaddress:
  246     ipaddress.IPv6Address = IPv6AddressScoped
  247     if sys.version_info.major == 2:
  248         ipaddress.IPv6Interface = IPv6InterfaceScoped