Hello community,

here is the log from the commit of package python-ipaddr for openSUSE:Factory 
checked in at 2012-01-31 10:21:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ipaddr (Old)
 and      /work/SRC/openSUSE:Factory/.python-ipaddr.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-ipaddr", Maintainer is ""

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-ipaddr/python-ipaddr.changes      
2011-11-25 10:13:43.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.python-ipaddr.new/python-ipaddr.changes 
2012-01-31 10:22:03.000000000 +0100
@@ -1,0 +2,12 @@
+Sun Jan 22 05:37:07 UTC 2012 - klaussfre...@gmail.com
+
+Update to upstream ipaddr 2.1.10
+
+- i84, fix iterhosts for /31's or /127's
+- private method arg cleanup.
+- i83, docstring issue.
+- i87, new ipv4/ipv6 parser. patch from pmarks
+- i90, fix copyright.
+- bytes fix. patch from pmarks.- 
+
+-------------------------------------------------------------------

Old:
----
  ipaddr-2.1.9.tar.gz
  license-fix-i90.patch

New:
----
  ipaddr-2.1.10.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-ipaddr.spec ++++++
--- /var/tmp/diff_new_pack.aG7F4n/_old  2012-01-31 10:22:04.000000000 +0100
+++ /var/tmp/diff_new_pack.aG7F4n/_new  2012-01-31 10:22:04.000000000 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-ipaddr
 #
-# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -11,20 +11,20 @@
 # case the license is the MIT License). An "Open Source License" is a
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
-#
+
 # Please submit bugfixes or comments via http://bugs.opensuse.org/
 #
 
+
+
 Name:           python-ipaddr
-Version:        2.1.9
+Version:        2.1.10
 Release:        0
 Url:            http://code.google.com/p/ipaddr-py/
 Summary:        Google's IP address manipulation library
 License:        Apache-2.0
 Group:          Development/Languages/Python
 Source:         ipaddr-%{version}.tar.gz
-# PATCH-FIX-UPSTREAM license-fix-i90.patch [#90]
-Patch0:         license-fix-i90.patch
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildRequires:  python-devel
 BuildRequires:  python-distribute
@@ -44,7 +44,6 @@
 
 %prep
 %setup -q -n ipaddr-%{version}
-%patch0 -p0
 sed -i "1d" ipaddr.py # Fix non-executable script
 
 %build

++++++ ipaddr-2.1.9.tar.gz -> ipaddr-2.1.10.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipaddr-2.1.9/PKG-INFO new/ipaddr-2.1.10/PKG-INFO
--- old/ipaddr-2.1.9/PKG-INFO   2011-02-23 06:43:19.000000000 +0100
+++ new/ipaddr-2.1.10/PKG-INFO  2012-01-21 04:05:52.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: ipaddr
-Version: 2.1.9
+Version: 2.1.10
 Summary: UNKNOWN
 Home-page: http://code.google.com/p/ipaddr-py/
 Author: Google
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipaddr-2.1.9/RELEASENOTES 
new/ipaddr-2.1.10/RELEASENOTES
--- old/ipaddr-2.1.9/RELEASENOTES       2011-02-23 06:31:56.000000000 +0100
+++ new/ipaddr-2.1.10/RELEASENOTES      2012-01-21 04:02:42.000000000 +0100
@@ -4,11 +4,24 @@
 
 Here are the visible changes for each release.
 
+== 2.1.10 ==
+
+(2012-01-20)
+
+Friday night, LAUNCH LAUNCH LAUNCH!
+
+  * i84, fix iterhosts for /31's or /127's
+  * private method arg cleanup.
+  * i83, docstring issue.
+  * i87, new ipv4/ipv6 parser. patch from pmarks
+  * i90, fix copyright.
+  * bytes fix. patch from pmarks.
+           
 == 2.1.9 ==
 
 (2011-02-22)
 
-The last outstanding issue.
+The last outstanding issues.
 
   * fix warnings from python3.2
   * fix bug in _is_shorthand_ip resulting in bad teredo addresses.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipaddr-2.1.9/ipaddr.py new/ipaddr-2.1.10/ipaddr.py
--- old/ipaddr-2.1.9/ipaddr.py  2011-02-23 06:31:56.000000000 +0100
+++ new/ipaddr-2.1.10/ipaddr.py 2012-01-21 04:03:17.000000000 +0100
@@ -22,7 +22,7 @@
 
 """
 
-__version__ = '2.1.9'
+__version__ = '2.1.10'
 
 import struct
 
@@ -134,7 +134,7 @@
     """
     if address > _BaseV4._ALL_ONES:
         raise ValueError('Address too large for IPv4')
-    return struct.pack('!I', address)
+    return Bytes(struct.pack('!I', address))
 
 
 def v6_int_to_packed(address):
@@ -146,7 +146,7 @@
     Returns:
         The binary representation of this address.
     """
-    return struct.pack('!QQ', address >> 64, address & (2**64 - 1))
+    return Bytes(struct.pack('!QQ', address >> 64, address & (2**64 - 1)))
 
 
 def _find_address_range(addresses):
@@ -270,12 +270,12 @@
 
     Example:
 
-        ip1 = IPv4Network'1.1.0.0/24')
-        ip2 = IPv4Network'1.1.1.0/24')
-        ip3 = IPv4Network'1.1.2.0/24')
-        ip4 = IPv4Network'1.1.3.0/24')
-        ip5 = IPv4Network'1.1.4.0/24')
-        ip6 = IPv4Network'1.1.0.1/22')
+        ip1 = IPv4Network('1.1.0.0/24')
+        ip2 = IPv4Network('1.1.1.0/24')
+        ip3 = IPv4Network('1.1.2.0/24')
+        ip4 = IPv4Network('1.1.3.0/24')
+        ip5 = IPv4Network('1.1.4.0/24')
+        ip6 = IPv4Network('1.1.0.1/22')
 
         _collapse_address_list_recursive([ip1, ip2, ip3, ip4, ip5, ip6]) ->
           [IPv4Network('1.1.0.0/22'), IPv4Network('1.1.4.0/24')]
@@ -368,15 +368,27 @@
 # backwards compatibility
 CollapseAddrList = collapse_address_list
 
-# Test whether this Python implementation supports byte objects that
-# are not identical to str ones.
-# We need to exclude platforms where bytes == str so that we can
-# distinguish between packed representations and strings, for example
-# b'12::' (the IPv4 address 49.50.58.58) and '12::' (an IPv6 address).
+# We need to distinguish between the string and packed-bytes representations
+# of an IP address.  For example, b'0::1' is the IPv4 address 48.58.58.49,
+# while '0::1' is an IPv6 address.
+#
+# In Python 3, the native 'bytes' type already provides this functionality,
+# so we use it directly.  For earlier implementations where bytes is not a
+# distinct type, we create a subclass of str to serve as a tag.
+#
+# Usage example (Python 2):
+#   ip = ipaddr.IPAddress(ipaddr.Bytes('xxxx'))
+#
+# Usage example (Python 3):
+#   ip = ipaddr.IPAddress(b'xxxx')
 try:
-    _compat_has_real_bytes = bytes is not str
-except NameError: # <Python2.6
-    _compat_has_real_bytes = False
+    if bytes is str:
+        raise TypeError("bytes is not a distinct type")
+    Bytes = bytes
+except (NameError, TypeError):
+    class Bytes(str):
+        def __repr__(self):
+            return 'Bytes(%s)' % str.__repr__(self)
 
 def get_mixed_type_key(obj):
     """Return a key suitable for sorting between networks and addresses.
@@ -435,11 +447,6 @@
 
     """
 
-    def __init__(self, address):
-        if (not (_compat_has_real_bytes and isinstance(address, bytes))
-            and '/' in str(address)):
-            raise AddressValueError(address)
-
     def __eq__(self, other):
         try:
             return (self._ip == other._ip
@@ -1009,15 +1016,14 @@
 
     # Equivalent to 255.255.255.255 or 32 bits of 1's.
     _ALL_ONES = (2**IPV4LENGTH) - 1
+    _DECIMAL_DIGITS = frozenset('0123456789')
 
     def __init__(self, address):
         self._version = 4
         self._max_prefixlen = IPV4LENGTH
 
-    def _explode_shorthand_ip_string(self, ip_str=None):
-        if not ip_str:
-            ip_str = str(self)
-        return ip_str
+    def _explode_shorthand_ip_string(self):
+        return str(self)
 
     def _ip_int_from_string(self, ip_str):
         """Turn the given IP string into an integer for comparison.
@@ -1029,20 +1035,44 @@
             The IP ip_str as an integer.
 
         Raises:
-            AddressValueError: if the string isn't a valid IP string.
+            AddressValueError: if ip_str isn't a valid IPv4 Address.
 
         """
-        packed_ip = 0
         octets = ip_str.split('.')
         if len(octets) != 4:
             raise AddressValueError(ip_str)
+
+        packed_ip = 0
         for oc in octets:
             try:
-                packed_ip = (packed_ip << 8) | int(oc)
+                packed_ip = (packed_ip << 8) | self._parse_octet(oc)
             except ValueError:
                 raise AddressValueError(ip_str)
         return packed_ip
 
+    def _parse_octet(self, octet_str):
+        """Convert a decimal octet into an integer.
+
+        Args:
+            octet_str: A string, the number to parse.
+
+        Returns:
+            The octet as an integer.
+
+        Raises:
+            ValueError: if the octet isn't strictly a decimal from [0..255].
+
+        """
+        # Whitelist the characters, since int() allows a lot of bizarre stuff.
+        if not self._DECIMAL_DIGITS.issuperset(octet_str):
+            raise ValueError
+        octet_int = int(octet_str, 10)
+        # Disallow leading zeroes, because no clear standard exists on
+        # whether these should be interpreted as decimal or octal.
+        if octet_int > 255 or (octet_str[0] == '0' and len(octet_str) > 1):
+            raise ValueError
+        return octet_int
+
     def _string_from_ip_int(self, ip_int):
         """Turns a 32-bit integer into dotted decimal notation.
 
@@ -1059,37 +1089,6 @@
             ip_int >>= 8
         return '.'.join(octets)
 
-    def _is_valid_ip(self, address):
-        """Validate the dotted decimal notation IP/netmask string.
-
-        Args:
-            address: A string, either representing a quad-dotted ip
-                or an integer which is a valid IPv4 IP address.
-
-        Returns:
-            A boolean, True if the string is a valid dotted decimal IP
-            string.
-
-        """
-        octets = address.split('.')
-        if len(octets) == 1:
-            # We have an integer rather than a dotted decimal IP.
-            try:
-                return int(address) >= 0 and int(address) <= self._ALL_ONES
-            except ValueError:
-                return False
-
-        if len(octets) != 4:
-            return False
-
-        for octet in octets:
-            try:
-                if not 0 <= int(octet) <= 255:
-                    return False
-            except ValueError:
-                return False
-        return True
-
     @property
     def max_prefixlen(self):
         return self._max_prefixlen
@@ -1190,7 +1189,6 @@
             AddressValueError: If ipaddr isn't a valid IPv4 address.
 
         """
-        _BaseIP.__init__(self, address)
         _BaseV4.__init__(self, address)
 
         # Efficient constructor from integer.
@@ -1201,17 +1199,16 @@
             return
 
         # Constructing from a packed address
-        if _compat_has_real_bytes:
-            if isinstance(address, bytes) and len(address) == 4:
-                self._ip = struct.unpack('!I', address)[0]
-                return
+        if isinstance(address, Bytes):
+            try:
+                self._ip, = struct.unpack('!I', address)
+            except struct.error:
+                raise AddressValueError(address)  # Wrong length.
+            return
 
         # Assume input argument to be string or any object representation
         # which converts into a formatted IP string.
         addr_str = str(address)
-        if not self._is_valid_ip(addr_str):
-            raise AddressValueError(addr_str)
-
         self._ip = self._ip_int_from_string(addr_str)
 
 
@@ -1276,25 +1273,14 @@
         _BaseNet.__init__(self, address)
         _BaseV4.__init__(self, address)
 
-        # Efficient constructor from integer.
-        if isinstance(address, (int, long)):
-            self._ip = address
-            self.ip = IPv4Address(self._ip)
+        # Constructing from an integer or packed bytes.
+        if isinstance(address, (int, long, Bytes)):
+            self.ip = IPv4Address(address)
+            self._ip = self.ip._ip
             self._prefixlen = self._max_prefixlen
             self.netmask = IPv4Address(self._ALL_ONES)
-            if address < 0 or address > self._ALL_ONES:
-                raise AddressValueError(address)
             return
 
-        # Constructing from a packed address
-        if _compat_has_real_bytes:
-            if isinstance(address, bytes) and len(address) == 4:
-                self._ip = struct.unpack('!I', address)[0]
-                self.ip = IPv4Address(self._ip)
-                self._prefixlen = self._max_prefixlen
-                self.netmask = IPv4Address(self._ALL_ONES)
-                return
-
         # Assume input argument to be string or any object representation
         # which converts into a formatted IP prefix string.
         addr = str(address).split('/')
@@ -1302,9 +1288,6 @@
         if len(addr) > 2:
             raise AddressValueError(address)
 
-        if not self._is_valid_ip(addr[0]):
-            raise AddressValueError(addr[0])
-
         self._ip = self._ip_int_from_string(addr[0])
         self.ip = IPv4Address(self._ip)
 
@@ -1338,6 +1321,8 @@
             if self.ip != self.network:
                 raise ValueError('%s has host bits set' %
                                  self.ip)
+        if self._prefixlen == (self._max_prefixlen - 1):
+            self.iterhosts = self.__iter__
 
     def _is_hostmask(self, ip_str):
         """Test if the IP string is a hostmask (rather than a netmask).
@@ -1403,12 +1388,14 @@
     """
 
     _ALL_ONES = (2**IPV6LENGTH) - 1
+    _HEXTET_COUNT = 8
+    _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef')
 
     def __init__(self, address):
         self._version = 6
         self._max_prefixlen = IPV6LENGTH
 
-    def _ip_int_from_string(self, ip_str=None):
+    def _ip_int_from_string(self, ip_str):
         """Turn an IPv6 ip_str into an integer.
 
         Args:
@@ -1418,35 +1405,95 @@
             A long, the IPv6 ip_str.
 
         Raises:
-           AddressValueError: if ip_str isn't a valid IP Address.
+            AddressValueError: if ip_str isn't a valid IPv6 Address.
 
         """
-        if not ip_str:
-            ip_str = str(self.ip)
+        parts = ip_str.split(':')
 
-        ip_int = 0
+        # An IPv6 address needs at least 2 colons (3 parts).
+        if len(parts) < 3:
+            raise AddressValueError(ip_str)
 
-        # Do we have an IPv4 mapped (::ffff:a.b.c.d) or compact (::a.b.c.d)
-        # ip_str?
-        fields = ip_str.split(':')
-        if fields[-1].count('.') == 3:
-            ipv4_string = fields.pop()
-            ipv4_int = IPv4Network(ipv4_string)._ip
-            octets = []
-            for _ in xrange(2):
-                octets.append(hex(ipv4_int & 0xFFFF).lstrip('0x').rstrip('L'))
-                ipv4_int >>= 16
-            fields.extend(reversed(octets))
-            ip_str = ':'.join(fields)
+        # If the address has an IPv4-style suffix, convert it to hexadecimal.
+        if '.' in parts[-1]:
+            ipv4_int = IPv4Address(parts.pop())._ip
+            parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF))
+            parts.append('%x' % (ipv4_int & 0xFFFF))
 
-        fields = self._explode_shorthand_ip_string(ip_str).split(':')
-        for field in fields:
-            try:
-                ip_int = (ip_int << 16) + int(field or '0', 16)
-            except ValueError:
+        # An IPv6 address can't have more than 8 colons (9 parts).
+        if len(parts) > self._HEXTET_COUNT + 1:
+            raise AddressValueError(ip_str)
+
+        # Disregarding the endpoints, find '::' with nothing in between.
+        # This indicates that a run of zeroes has been skipped.
+        try:
+            skip_index, = (
+                [i for i in xrange(1, len(parts) - 1) if not parts[i]] or
+                [None])
+        except ValueError:
+            # Can't have more than one '::'
+            raise AddressValueError(ip_str)
+
+        # parts_hi is the number of parts to copy from above/before the '::'
+        # parts_lo is the number of parts to copy from below/after the '::'
+        if skip_index is not None:
+            # If we found a '::', then check if it also covers the endpoints.
+            parts_hi = skip_index
+            parts_lo = len(parts) - skip_index - 1
+            if not parts[0]:
+                parts_hi -= 1
+                if parts_hi:
+                    raise AddressValueError(ip_str)  # ^: requires ^::
+            if not parts[-1]:
+                parts_lo -= 1
+                if parts_lo:
+                    raise AddressValueError(ip_str)  # :$ requires ::$
+            parts_skipped = self._HEXTET_COUNT - (parts_hi + parts_lo)
+            if parts_skipped < 1:
+                raise AddressValueError(ip_str)
+        else:
+            # Otherwise, allocate the entire address to parts_hi.  The 
endpoints
+            # could still be empty, but _parse_hextet() will check for that.
+            if len(parts) != self._HEXTET_COUNT:
                 raise AddressValueError(ip_str)
+            parts_hi = len(parts)
+            parts_lo = 0
+            parts_skipped = 0
+
+        try:
+            # Now, parse the hextets into a 128-bit integer.
+            ip_int = 0L
+            for i in xrange(parts_hi):
+                ip_int <<= 16
+                ip_int |= self._parse_hextet(parts[i])
+            ip_int <<= 16 * parts_skipped
+            for i in xrange(-parts_lo, 0):
+                ip_int <<= 16
+                ip_int |= self._parse_hextet(parts[i])
+            return ip_int
+        except ValueError:
+            raise AddressValueError(ip_str)
 
-        return ip_int
+    def _parse_hextet(self, hextet_str):
+        """Convert an IPv6 hextet string into an integer.
+
+        Args:
+            hextet_str: A string, the number to parse.
+
+        Returns:
+            The hextet as an integer.
+
+        Raises:
+            ValueError: if the input isn't strictly a hex number from 
[0..FFFF].
+
+        """
+        # Whitelist the characters, since int() allows a lot of bizarre stuff.
+        if not self._HEX_DIGITS.issuperset(hextet_str):
+            raise ValueError
+        hextet_int = int(hextet_str, 16)
+        if hextet_int > 0xFFFF:
+            raise ValueError
+        return hextet_int
 
     def _compress_hextets(self, hextets):
         """Compresses a list of hextets.
@@ -1522,7 +1569,7 @@
         hextets = self._compress_hextets(hextets)
         return ':'.join(hextets)
 
-    def _explode_shorthand_ip_string(self, ip_str=None):
+    def _explode_shorthand_ip_string(self):
         """Expand a shortened IPv6 address.
 
         Args:
@@ -1532,108 +1579,20 @@
             A string, the expanded IPv6 address.
 
         """
-        if not ip_str:
+        if isinstance(self, _BaseNet):
+            ip_str = str(self.ip)
+        else:
             ip_str = str(self)
-            if isinstance(self, _BaseNet):
-                ip_str = str(self.ip)
-
-        if self._is_shorthand_ip(ip_str):
-            new_ip = []
-            hextet = ip_str.split('::')
-
-            if len(hextet) > 1:
-                sep = len(hextet[0].split(':')) + len(hextet[1].split(':'))
-                new_ip = hextet[0].split(':')
-
-                for _ in xrange(8 - sep):
-                    new_ip.append('0000')
-                new_ip += hextet[1].split(':')
-
-            else:
-                new_ip = ip_str.split(':')
-            # Now need to make sure every hextet is 4 lower case characters.
-            # If a hextet is < 4 characters, we've got missing leading 0's.
-            ret_ip = []
-            for hextet in new_ip:
-                ret_ip.append(('0' * (4 - len(hextet)) + hextet).lower())
-            return ':'.join(ret_ip)
-        # We've already got a longhand ip_str.
-        return ip_str
-
-    def _is_valid_ip(self, ip_str):
-        """Ensure we have a valid IPv6 address.
-
-        Probably not as exhaustive as it should be.
-
-        Args:
-            ip_str: A string, the IPv6 address.
-
-        Returns:
-            A boolean, True if this is a valid IPv6 address.
-
-        """
-        # We need to have at least one ':'.
-        if ':' not in ip_str:
-            return False
-
-        # We can only have one '::' shortener.
-        if ip_str.count('::') > 1:
-            return False
-
-        # '::' should be encompassed by start, digits or end.
-        if ':::' in ip_str:
-            return False
-
-        # A single colon can neither start nor end an address.
-        if ((ip_str.startswith(':') and not ip_str.startswith('::')) or
-                (ip_str.endswith(':') and not ip_str.endswith('::'))):
-            return False
-
-        # If we have no concatenation, we need to have 8 fields with 7 ':'.
-        if '::' not in ip_str and ip_str.count(':') != 7:
-            # We might have an IPv4 mapped address.
-            if ip_str.count('.') != 3:
-                return False
 
-        ip_str = self._explode_shorthand_ip_string(ip_str)
-
-        # Now that we have that all squared away, let's check that each of the
-        # hextets are between 0x0 and 0xFFFF.
-        for hextet in ip_str.split(':'):
-            if hextet.count('.') == 3:
-                # If we have an IPv4 mapped address, the IPv4 portion has to
-                # be at the end of the IPv6 portion.
-                if not ip_str.split(':')[-1] == hextet:
-                    return False
-                try:
-                    IPv4Network(hextet)
-                except AddressValueError:
-                    return False
-            else:
-                try:
-                    # a value error here means that we got a bad hextet,
-                    # something like 0xzzzz
-                    if int(hextet, 16) < 0x0 or int(hextet, 16) > 0xFFFF:
-                        return False
-                except ValueError:
-                    return False
-        return True
-
-    def _is_shorthand_ip(self, ip_str=None):
-        """Determine if the address is shortened.
-
-        Args:
-            ip_str: A string, the IPv6 address.
-
-        Returns:
-            A boolean, True if the address is shortened.
-
-        """
-        if ip_str.count('::') == 1:
-            return True
-        if filter(lambda x: len(x) < 4, ip_str.split(':')):
-            return True
-        return False
+        ip_int = self._ip_int_from_string(ip_str)
+        parts = []
+        for i in xrange(self._HEXTET_COUNT):
+            parts.append('%04x' % (ip_int & 0xFFFF))
+            ip_int >>= 16
+        parts.reverse()
+        if isinstance(self, _BaseNet):
+            return '%s/%d' % (':'.join(parts), self.prefixlen)
+        return ':'.join(parts)
 
     @property
     def max_prefixlen(self):
@@ -1749,13 +1708,9 @@
             IPv4 mapped address. Return None otherwise.
 
         """
-        hextets = self._explode_shorthand_ip_string().split(':')
-        if hextets[-3] != 'ffff':
-            return None
-        try:
-            return IPv4Address(int('%s%s' % (hextets[-2], hextets[-1]), 16))
-        except AddressValueError:
+        if (self._ip >> 32) != 0xFFFF:
             return None
+        return IPv4Address(self._ip & 0xFFFFFFFF)
 
     @property
     def teredo(self):
@@ -1764,14 +1719,13 @@
         Returns:
             Tuple of the (server, client) IPs or None if the address
             doesn't appear to be a teredo address (doesn't start with
-            2001)
+            2001::/32)
 
         """
-        bits = self._explode_shorthand_ip_string().split(':')
-        if not bits[0] == '2001':
+        if (self._ip >> 96) != 0x20010000:
             return None
-        return (IPv4Address(int(''.join(bits[2:4]), 16)),
-                IPv4Address(int(''.join(bits[6:]), 16) ^ 0xFFFFFFFF))
+        return (IPv4Address((self._ip >> 64) & 0xFFFFFFFF),
+                IPv4Address(~self._ip & 0xFFFFFFFF))
 
     @property
     def sixtofour(self):
@@ -1782,10 +1736,9 @@
             address doesn't appear to contain a 6to4 embedded address.
 
         """
-        bits = self._explode_shorthand_ip_string().split(':')
-        if not bits[0] == '2002':
+        if (self._ip >> 112) != 0x2002:
             return None
-        return IPv4Address(int(''.join(bits[1:3]), 16))
+        return IPv4Address((self._ip >> 80) & 0xFFFFFFFF)
 
 
 class IPv6Address(_BaseV6, _BaseIP):
@@ -1810,7 +1763,6 @@
             AddressValueError: If address isn't a valid IPv6 address.
 
         """
-        _BaseIP.__init__(self, address)
         _BaseV6.__init__(self, address)
 
         # Efficient constructor from integer.
@@ -1821,11 +1773,13 @@
             return
 
         # Constructing from a packed address
-        if _compat_has_real_bytes:
-            if isinstance(address, bytes) and len(address) == 16:
-                tmp = struct.unpack('!QQ', address)
-                self._ip = (tmp[0] << 64) | tmp[1]
-                return
+        if isinstance(address, Bytes):
+            try:
+                hi, lo = struct.unpack('!QQ', address)
+            except struct.error:
+                raise AddressValueError(address)  # Wrong length.
+            self._ip = (hi << 64) | lo
+            return
 
         # Assume input argument to be string or any object representation
         # which converts into a formatted IP string.
@@ -1833,9 +1787,6 @@
         if not addr_str:
             raise AddressValueError('')
 
-        if not self._is_valid_ip(addr_str):
-            raise AddressValueError(addr_str)
-
         self._ip = self._ip_int_from_string(addr_str)
 
 
@@ -1889,26 +1840,14 @@
         _BaseNet.__init__(self, address)
         _BaseV6.__init__(self, address)
 
-        # Efficient constructor from integer.
-        if isinstance(address, (int, long)):
-            self._ip = address
-            self.ip = IPv6Address(self._ip)
+        # Constructing from an integer or packed bytes.
+        if isinstance(address, (int, long, Bytes)):
+            self.ip = IPv6Address(address)
+            self._ip = self.ip._ip
             self._prefixlen = self._max_prefixlen
             self.netmask = IPv6Address(self._ALL_ONES)
-            if address < 0 or address > self._ALL_ONES:
-                raise AddressValueError(address)
             return
 
-        # Constructing from a packed address
-        if _compat_has_real_bytes:
-            if isinstance(address, bytes) and len(address) == 16:
-                tmp = struct.unpack('!QQ', address)
-                self._ip = (tmp[0] << 64) | tmp[1]
-                self.ip = IPv6Address(self._ip)
-                self._prefixlen = self._max_prefixlen
-                self.netmask = IPv6Address(self._ALL_ONES)
-                return
-
         # Assume input argument to be string or any object representation
         # which converts into a formatted IP prefix string.
         addr = str(address).split('/')
@@ -1916,8 +1855,8 @@
         if len(addr) > 2:
             raise AddressValueError(address)
 
-        if not self._is_valid_ip(addr[0]):
-            raise AddressValueError(addr[0])
+        self._ip = self._ip_int_from_string(addr[0])
+        self.ip = IPv6Address(self._ip)
 
         if len(addr) == 2:
             if self._is_valid_netmask(addr[1]):
@@ -1929,13 +1868,12 @@
 
         self.netmask = IPv6Address(self._ip_int_from_prefix(self._prefixlen))
 
-        self._ip = self._ip_int_from_string(addr[0])
-        self.ip = IPv6Address(self._ip)
-
         if strict:
             if self.ip != self.network:
                 raise ValueError('%s has host bits set' %
                                  self.ip)
+        if self._prefixlen == (self._max_prefixlen - 1):
+            self.iterhosts = self.__iter__
 
     def _is_valid_netmask(self, prefixlen):
         """Verify that the netmask/prefixlen is valid.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipaddr-2.1.9/ipaddr_test.py 
new/ipaddr-2.1.10/ipaddr_test.py
--- old/ipaddr-2.1.9/ipaddr_test.py     2011-02-23 06:31:56.000000000 +0100
+++ new/ipaddr-2.1.10/ipaddr_test.py    2012-01-21 04:03:02.000000000 +0100
@@ -23,10 +23,10 @@
 import ipaddr
 
 # Compatibility function to cast str to bytes objects
-if ipaddr._compat_has_real_bytes:
-    _cb = lambda bytestr: bytes(bytestr, 'charmap')
+if issubclass(ipaddr.Bytes, str):
+    _cb = ipaddr.Bytes
 else:
-    _cb = str
+    _cb = lambda bytestr: bytes(bytestr, 'charmap')
 
 class IpaddrUnitTest(unittest.TestCase):
 
@@ -68,25 +68,72 @@
                          ipaddr.IPv6Address('::1'))
 
     def testInvalidStrings(self):
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, 'www.google.com')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '1.2.3')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '1.2.3.4.5')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '301.2.2.2')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '1:2:3:4:5:6:7')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '1:2:3:4:5:6:7:')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, ':2:3:4:5:6:7:8')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '1:2:3:4:5:6:7:8:9')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '1:2:3:4:5:6:7:8:')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '1::3:4:5:6::8')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, 'a:')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, ':')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, ':::')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '::a:')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '1ffff::')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '0xa::')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '1:2:3:4:5:6:1a.2.3.4')
-        self.assertRaises(ValueError, ipaddr.IPNetwork, '1:2:3:4:5:1.2.3.4:8')
+        def AssertInvalidIP(ip_str):
+            self.assertRaises(ValueError, ipaddr.IPAddress, ip_str)
+        AssertInvalidIP("")
+        AssertInvalidIP("016.016.016.016")
+        AssertInvalidIP("016.016.016")
+        AssertInvalidIP("016.016")
+        AssertInvalidIP("016")
+        AssertInvalidIP("000.000.000.000")
+        AssertInvalidIP("000")
+        AssertInvalidIP("0x0a.0x0a.0x0a.0x0a")
+        AssertInvalidIP("0x0a.0x0a.0x0a")
+        AssertInvalidIP("0x0a.0x0a")
+        AssertInvalidIP("0x0a")
+        AssertInvalidIP("42.42.42.42.42")
+        AssertInvalidIP("42.42.42")
+        AssertInvalidIP("42.42")
+        AssertInvalidIP("42")
+        AssertInvalidIP("42..42.42")
+        AssertInvalidIP("42..42.42.42")
+        AssertInvalidIP("42.42.42.42.")
+        AssertInvalidIP("42.42.42.42...")
+        AssertInvalidIP(".42.42.42.42")
+        AssertInvalidIP("...42.42.42.42")
+        AssertInvalidIP("42.42.42.-0")
+        AssertInvalidIP("42.42.42.+0")
+        AssertInvalidIP(".")
+        AssertInvalidIP("...")
+        AssertInvalidIP("bogus")
+        AssertInvalidIP("bogus.com")
+        AssertInvalidIP("192.168.0.1.com")
+        AssertInvalidIP("12345.67899.-54321.-98765")
+        AssertInvalidIP("257.0.0.0")
+        AssertInvalidIP("42.42.42.-42")
+        AssertInvalidIP("3ffe::1.net")
+        AssertInvalidIP("3ffe::1::1")
+        AssertInvalidIP("1::2::3::4:5")
+        AssertInvalidIP("::7:6:5:4:3:2:")
+        AssertInvalidIP(":6:5:4:3:2:1::")
+        AssertInvalidIP("2001::db:::1")
+        AssertInvalidIP("FEDC:9878")
+        AssertInvalidIP("+1.+2.+3.4")
+        AssertInvalidIP("1.2.3.4e0")
+        AssertInvalidIP("::7:6:5:4:3:2:1:0")
+        AssertInvalidIP("7:6:5:4:3:2:1:0::")
+        AssertInvalidIP("9:8:7:6:5:4:3::2:1")
+        AssertInvalidIP("0:1:2:3::4:5:6:7")
+        AssertInvalidIP("3ffe:0:0:0:0:0:0:0:1")
+        AssertInvalidIP("3ffe::10000")
+        AssertInvalidIP("3ffe::goog")
+        AssertInvalidIP("3ffe::-0")
+        AssertInvalidIP("3ffe::+0")
+        AssertInvalidIP("3ffe::-1")
+        AssertInvalidIP(":")
+        AssertInvalidIP(":::")
+        AssertInvalidIP("::1.2.3")
+        AssertInvalidIP("::1.2.3.4.5")
+        AssertInvalidIP("::1.2.3.4:")
+        AssertInvalidIP("1.2.3.4::")
+        AssertInvalidIP("2001:db8::1:")
+        AssertInvalidIP(":2001:db8::1")
+        AssertInvalidIP(":1:2:3:4:5:6:7")
+        AssertInvalidIP("1:2:3:4:5:6:7:")
+        AssertInvalidIP(":1:2:3:4:5:6:")
+        AssertInvalidIP("192.0.2.1/32")
+        AssertInvalidIP("2001:db8::1/128")
+
         self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv4Network, '')
         self.assertRaises(ipaddr.AddressValueError, ipaddr.IPv4Network,
                           'google.com')
@@ -188,26 +235,25 @@
         self.assertEqual(ipaddr.IPNetwork(self.ipv4.ip).version, 4)
         self.assertEqual(ipaddr.IPNetwork(self.ipv6.ip).version, 6)
 
-    if ipaddr._compat_has_real_bytes: # on python3+
-        def testIpFromPacked(self):
-            ip = ipaddr.IPNetwork
-
-            self.assertEqual(self.ipv4.ip,
-                             ip(_cb('\x01\x02\x03\x04')).ip)
-            self.assertEqual(ip('255.254.253.252'),
-                             ip(_cb('\xff\xfe\xfd\xfc')))
-            self.assertRaises(ValueError, ipaddr.IPNetwork, _cb('\x00' * 3))
-            self.assertRaises(ValueError, ipaddr.IPNetwork, _cb('\x00' * 5))
-            self.assertEqual(self.ipv6.ip,
-                             ip(_cb('\x20\x01\x06\x58\x02\x2a\xca\xfe'
-                               '\x02\x00\x00\x00\x00\x00\x00\x01')).ip)
-            self.assertEqual(ip('ffff:2:3:4:ffff::'),
-                             ip(_cb('\xff\xff\x00\x02\x00\x03\x00\x04' +
-                                   '\xff\xff' + '\x00' * 6)))
-            self.assertEqual(ip('::'),
-                             ip(_cb('\x00' * 16)))
-            self.assertRaises(ValueError, ip, _cb('\x00' * 15))
-            self.assertRaises(ValueError, ip, _cb('\x00' * 17))
+    def testIpFromPacked(self):
+        ip = ipaddr.IPNetwork
+
+        self.assertEqual(self.ipv4.ip,
+                         ip(_cb('\x01\x02\x03\x04')).ip)
+        self.assertEqual(ip('255.254.253.252'),
+                         ip(_cb('\xff\xfe\xfd\xfc')))
+        self.assertRaises(ValueError, ipaddr.IPNetwork, _cb('\x00' * 3))
+        self.assertRaises(ValueError, ipaddr.IPNetwork, _cb('\x00' * 5))
+        self.assertEqual(self.ipv6.ip,
+                         ip(_cb('\x20\x01\x06\x58\x02\x2a\xca\xfe'
+                           '\x02\x00\x00\x00\x00\x00\x00\x01')).ip)
+        self.assertEqual(ip('ffff:2:3:4:ffff::'),
+                         ip(_cb('\xff\xff\x00\x02\x00\x03\x00\x04' +
+                               '\xff\xff' + '\x00' * 6)))
+        self.assertEqual(ip('::'),
+                         ip(_cb('\x00' * 16)))
+        self.assertRaises(ValueError, ip, _cb('\x00' * 15))
+        self.assertRaises(ValueError, ip, _cb('\x00' * 17))
 
     def testGetIp(self):
         self.assertEqual(int(self.ipv4.ip), 16909060)
@@ -287,6 +333,11 @@
         self.assertEqual(self.ipv4.subnet(), list(self.ipv4.iter_subnets()))
         self.assertEqual(self.ipv6.subnet(), list(self.ipv6.iter_subnets()))
 
+    def testIterHosts(self):
+        self.assertEqual([ipaddr.IPv4Address('2.0.0.0'),
+                          ipaddr.IPv4Address('2.0.0.1')],
+                         list(ipaddr.IPNetwork('2.0.0.0/31').iterhosts()))
+
     def testFancySubnetting(self):
         self.assertEqual(sorted(self.ipv4.subnet(prefixlen_diff=3)),
                          sorted(self.ipv4.subnet(new_prefix=27)))
@@ -893,7 +944,7 @@
             '2001:0:0:4:0:0:0:8': '2001:0:0:4::8/128',
             '2001:0:0:4:5:6:7:8': '2001::4:5:6:7:8/128',
             '2001:0:3:4:5:6:7:8': '2001:0:3:4:5:6:7:8/128',
-            '2001:0::3:4:5:6:7:8': '2001:0:3:4:5:6:7:8/128',
+            '2001:0:3:4:5:6:7:8': '2001:0:3:4:5:6:7:8/128',
             '0:0:3:0:0:0:0:ffff': '0:0:3::ffff/128',
             '0:0:0:4:0:0:0:ffff': '::4:0:0:0:ffff/128',
             '0:0:0:0:5:0:0:ffff': '::5:0:0:ffff/128',
@@ -903,6 +954,12 @@
             '0:0:0:0:0:0:0:1': '::1/128',
             '2001:0658:022a:cafe:0000:0000:0000:0000/66':
             '2001:658:22a:cafe::/66',
+            '::1.2.3.4': '::102:304/128',
+            '1:2:3:4:5:ffff:1.2.3.4': '1:2:3:4:5:ffff:102:304/128',
+            '::7:6:5:4:3:2:1': '0:7:6:5:4:3:2:1/128',
+            '::7:6:5:4:3:2:0': '0:7:6:5:4:3:2:0/128',
+            '7:6:5:4:3:2:1::': '7:6:5:4:3:2:1:0/128',
+            '0:6:5:4:3:2:1::': '0:6:5:4:3:2:1:0/128',
             }
         for uncompressed, compressed in test_addresses.items():
             self.assertEqual(compressed, str(ipaddr.IPv6Network(uncompressed)))
@@ -910,9 +967,9 @@
     def testExplodeShortHandIpStr(self):
         addr1 = ipaddr.IPv6Network('2001::1')
         addr2 = ipaddr.IPv6Address('2001:0:5ef5:79fd:0:59d:a0e5:ba1')
-        self.assertEqual('2001:0000:0000:0000:0000:0000:0000:0001',
-                         addr1._explode_shorthand_ip_string(str(addr1.ip)))
-        self.assertEqual('0000:0000:0000:0000:0000:0000:0000:0001',
+        self.assertEqual('2001:0000:0000:0000:0000:0000:0000:0001/128',
+                         addr1.exploded)
+        self.assertEqual('0000:0000:0000:0000:0000:0000:0000:0001/128',
                          ipaddr.IPv6Network('::1/128').exploded)
         # issue 77
         self.assertEqual('2001:0000:5ef5:79fd:0000:059d:a0e5:0ba1',
@@ -957,7 +1014,7 @@
         self.assertEqual(ipaddr.IPNetwork('::/121').Supernet(),
                          ipaddr.IPNetwork('::/120'))
 
-        self.assertEqual(ipaddr.IPNetwork('10.0.0.02').IsRFC1918(), True)
+        self.assertEqual(ipaddr.IPNetwork('10.0.0.2').IsRFC1918(), True)
         self.assertEqual(ipaddr.IPNetwork('10.0.0.0').IsMulticast(), False)
         self.assertEqual(ipaddr.IPNetwork('127.255.255.255').IsLoopback(), 
True)
         self.assertEqual(ipaddr.IPNetwork('169.255.255.255').IsLinkLocal(),
@@ -1017,19 +1074,6 @@
         self.assertTrue(self.ipv6._cache.has_key('broadcast'))
         self.assertTrue(self.ipv6._cache.has_key('hostmask'))
 
-    def testIsValidIp(self):
-        ip = ipaddr.IPv6Address('::')
-        self.assertTrue(ip._is_valid_ip('2001:658:22a:cafe:200::1'))
-        self.assertTrue(ip._is_valid_ip('::ffff:10.10.0.0'))
-        self.assertTrue(ip._is_valid_ip('::ffff:192.168.0.0'))
-        self.assertFalse(ip._is_valid_ip('2001:658:22a::::1'))
-        self.assertFalse(ip._is_valid_ip(':658:22a:cafe:200::1'))
-        self.assertFalse(ip._is_valid_ip('2001:658:22a:cafe:200:'))
-        self.assertFalse(ip._is_valid_ip('2001:658:22a:cafe:200:127.0.0.1::1'))
-        self.assertFalse(ip._is_valid_ip('2001:658:22a:cafe:200::127.0.1'))
-        self.assertFalse(ip._is_valid_ip('2001:658:22a:zzzz:200::1'))
-        self.assertFalse(ip._is_valid_ip('2001:658:22a:cafe1:200::1'))
-
     def testTeredo(self):
         # stolen from wikipedia
         server = ipaddr.IPv4Address('65.54.227.120')
@@ -1039,6 +1083,8 @@
                          ipaddr.IPAddress(teredo_addr).teredo)
         bad_addr = '2000::4136:e378:8000:63bf:3fff:fdd2'
         self.assertFalse(ipaddr.IPAddress(bad_addr).teredo)
+        bad_addr = '2001:0001:4136:e378:8000:63bf:3fff:fdd2'
+        self.assertFalse(ipaddr.IPAddress(bad_addr).teredo)
 
         # i77
         teredo_addr = ipaddr.IPv6Address('2001:0:5ef5:79fd:0:59d:a0e5:ba1')

-- 
To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org
For additional commands, e-mail: opensuse-commit+h...@opensuse.org

Reply via email to