Hello community,

here is the log from the commit of package python-ipy for openSUSE:Factory 
checked in at 2018-11-26 10:29:50
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ipy (Old)
 and      /work/SRC/openSUSE:Factory/.python-ipy.new.19453 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-ipy"

Mon Nov 26 10:29:50 2018 rev:8 rq:651338 version:0.83

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-ipy/python-ipy.changes    2013-12-09 
16:59:44.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.python-ipy.new.19453/python-ipy.changes 
2018-11-26 10:30:27.601017171 +0100
@@ -1,0 +2,12 @@
+Thu Nov 22 14:26:39 UTC 2018 - [email protected]
+
+- Update to version 0.83
+  * Add carrier grade NAT ranges
+  * Unbreak lots of packing systems by not having a letter in the release 
version
+  * Correct x.next() -> next(x) python3 compatability
+  * Add support for array slices
+  * Add __and__ and isdisjoint for IPSet
+  * Fix a bug in IPSet where contains may incorrectly return false
+- Moved to singlespec and added explicit license
+
+-------------------------------------------------------------------

Old:
----
  IPy-0.81.tar.gz

New:
----
  IPy-0.83.tar.gz

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

Other differences:
------------------
++++++ python-ipy.spec ++++++
--- /var/tmp/diff_new_pack.SHcjF4/_old  2018-11-26 10:30:29.861014521 +0100
+++ /var/tmp/diff_new_pack.SHcjF4/_new  2018-11-26 10:30:29.861014521 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-ipy
 #
-# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,23 +16,21 @@
 #
 
 
-%define modname IPy
-
+%{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-ipy
-Version:        0.81
+Version:        0.83
 Release:        0
+Summary:        Class and tools for handling of IPv4 and IPv6 addresses and 
networks
 License:        BSD-3-Clause
-Summary:        Class and Tools for Handling of IPv4 and IPv6 Addresses and 
Networks
-Url:            http://software.inl.fr/trac/wiki/IPy
 Group:          Development/Languages/Python
-Source:         
https://pypi.python.org/packages/source/I/IPy/IPy-%{version}.tar.gz
-BuildRequires:  python-devel
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-%if 0%{?suse_version} && 0%{?suse_version} <= 1110
-%{!?python_sitelib: %global python_sitelib %(python -c "from 
distutils.sysconfig import get_python_lib; print get_python_lib()")}
-%else
+Url:            https://github.com/autocracy/python-ipy
+Source:         
https://files.pythonhosted.org/packages/source/I/IPy/IPy-%{version}.tar.gz
+BuildRequires:  %{python_module setuptools}
+BuildRequires:  fdupes
+BuildRequires:  python-rpm-macros
 BuildArch:      noarch
-%endif
+
+%python_subpackages
 
 %description
 The IP class allows a comfortable parsing and handling for most
@@ -42,17 +40,18 @@
 so funky stuff like a netmask of 0xffffff0f can't be done here.
 
 %prep
-%setup -q -n %{modname}-%{version}
+%setup -q -n IPy-%{version}
 
 %build
-python setup.py build
+%python_build
 
 %install
-python setup.py install --prefix=%{_prefix} --root=%{buildroot}
-
-%files
-%defattr(-,root,root)
-%doc AUTHORS COPYING ChangeLog README
-%{python_sitelib}
+%python_install
+%python_expand %fdupes %{buildroot}%{$python_sitelib}
+#install COPYING %{buildroot}
+
+%files %{python_files}
+%{python_sitelib}/*
+%license COPYING
 
 %changelog

++++++ IPy-0.81.tar.gz -> IPy-0.83.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/IPy-0.81/.gitignore new/IPy-0.83/.gitignore
--- old/IPy-0.81/.gitignore     1970-01-01 01:00:00.000000000 +0100
+++ new/IPy-0.83/.gitignore     2015-04-05 02:48:02.000000000 +0200
@@ -0,0 +1,2 @@
+*.pyc
+*.swp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/IPy-0.81/AUTHORS new/IPy-0.83/AUTHORS
--- old/IPy-0.81/AUTHORS        2013-03-27 01:53:18.000000000 +0100
+++ new/IPy-0.83/AUTHORS        2015-04-05 02:48:02.000000000 +0200
@@ -1,12 +1,12 @@
 Authors
 =======
 
+Jeff Ferland <jeff AT storyinmemo.com>
+   > Current maintainer, versions 0.76 through latest
+Victor Stinner <victor.stinner AT gmail.com>
+   > Maintainer, versions 0.5 through 0.75
 Maximillian Dornseif <md AT hudora.de>
    > IPy author and maintainer until the version 0.42
-Victor Stinner <victor.stinner AT haypocalc.com>
-   > new maintainer since the version 0.5
-Jeff Ferland <jeff AT storyinmemo.com>
-   > New maintainer from version 0.76
 
 Contributors
 ============
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/IPy-0.81/ChangeLog new/IPy-0.83/ChangeLog
--- old/IPy-0.81/ChangeLog      2013-04-08 19:25:56.000000000 +0200
+++ new/IPy-0.83/ChangeLog      2015-04-05 02:48:02.000000000 +0200
@@ -1,4 +1,24 @@
+Version 0.83 (2015-04-04)
+------------
+ * Add carrier grade NAT ranges
+ * Unbreak lots of packing systems by not having a letter in the release 
version
+
+Version 0.82a (2014-10-07)
+------------
+ * Fix version numbers in files
+ * Correct x.next() -> next(x) python3 compatability
+
+Version 0.82 (2014-10-06)
+------------
+
+ * Add support for array slices
+ * Add __and__ and isdisjoint for IPSet
+ * Fix a bug in IPSet where contains may incorrectly return false
+ * Added some fuzz testing
+
 Version 0.81 (2013-04-08)
+------------
+
  * Correct reverseName() for IPv6 addresses, so IP('::1').reverseName() 
returns correct.
  * Add network mask awareness to v46map()
  * Fix Python 3 errors in IPSet class
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/IPy-0.81/IPy.py new/IPy-0.83/IPy.py
--- old/IPy-0.81/IPy.py 2013-04-01 23:42:25.000000000 +0200
+++ new/IPy-0.83/IPy.py 2015-04-05 02:48:02.000000000 +0200
@@ -6,7 +6,7 @@
 https://github.com/haypo/python-ipy
 """
 
-__version__ = '0.81'
+__version__ = '0.83'
 
 import bisect
 import collections
@@ -20,6 +20,7 @@
     '0':                'PUBLIC',   # fall back
     '00000000':         'PRIVATE',  # 0/8
     '00001010':         'PRIVATE',  # 10/8
+    '0110010001':       'CARRIER_GRADE_NAT', #100.64/10
     '01111111':         'PRIVATE',  # 127.0/8
     '1':                'PUBLIC',   # fall back
     '1010100111111110': 'PRIVATE',  # 169.254/16
@@ -610,6 +611,8 @@
         IP('127.0.0.3')
         """
 
+        if isinstance(key, slice):
+            return [self.ip + int(x) for x in xrange(*key.indices(len(self)))]
         if not isinstance(key, INT_TYPES):
             raise TypeError
         if key < 0:
@@ -959,6 +962,8 @@
         >>> print(str(ip[-1]))
         127.0.0.3
         """
+        if isinstance(key, slice):
+            return [IP(IPint.__getitem__(self, x), ipversion=self._ipversion) 
for x in xrange(*key.indices(len(self)))]
         return IP(IPint.__getitem__(self, key), ipversion=self._ipversion)
 
     def __repr__(self):
@@ -1012,12 +1017,7 @@
         raise ValueError("%s cannot be converted to an IPv4 address."
                          % repr(self))
 
-try:
-    IPSetBaseClass = collections.MutableSet
-except AttributeError:
-    IPSetBaseClass = object
-
-class IPSet(IPSetBaseClass):
+class IPSet(collections.MutableSet):
     def __init__(self, iterable=[]):
         # Make sure it's iterable, otherwise wrap
         if not isinstance(iterable, collections.Iterable):
@@ -1038,13 +1038,11 @@
             #Don't dig through more-specific ranges
             ip_mask = ip._prefixlen
             valid_masks = [x for x in valid_masks if x <= ip_mask]
-        for mask in valid_masks:
+        for mask in sorted(valid_masks):
             i = bisect.bisect(self.prefixtable[mask], ip)
             # Because of sorting order, a match can only occur in the prefix
             # that comes before the result of the search.
-            if i == 0:
-                return False
-            if ip in self.prefixtable[mask][i - 1]:
+            if i and ip in self.prefixtable[mask][i - 1]:
                 return True
 
     def __iter__(self):
@@ -1063,6 +1061,31 @@
             new.discard(prefix)
         return new
     
+    def __and__(self, other):
+        left = iter(self.prefixes)
+        right = iter(other.prefixes)
+        result = []
+        try:
+            l = next(left)
+            r = next(right)
+            while True:
+                # iterate over prefixes in order, keeping the smaller of the
+                # two if they overlap
+                if l in r:
+                    result.append(l)
+                    l = next(left)
+                    continue
+                elif r in l:
+                    result.append(r)
+                    r = next(right)
+                    continue
+                if l < r:
+                    l = next(left)
+                else:
+                    r = next(right)
+        except StopIteration:
+            return IPSet(result)
+
     def __repr__(self):
         return '%s([' % self.__class__.__name__ + ', '.join(map(repr, 
self.prefixes)) + '])'
     
@@ -1120,6 +1143,22 @@
                 
         self.optimize()
 
+    def isdisjoint(self, other):
+        left = iter(self.prefixes)
+        right = iter(other.prefixes)
+        try:
+            l = next(left)
+            r = next(right)
+            while True:
+                if l in r or r in l:
+                    return False
+                if l < r:
+                    l = next(left)
+                else:
+                    r = next(right)
+        except StopIteration:
+            return True
+
     def optimize(self):
         # The algorithm below *depends* on the sort order
         self.prefixes.sort()
@@ -1597,7 +1636,7 @@
     # Start cutting in half, recursively
     prefixes = [
         IP('%s/%d' % (prefix[0], prefix._prefixlen + 1)),
-        IP('%s/%d' % (prefix[prefix.len() / 2], prefix._prefixlen + 1)),
+        IP('%s/%d' % (prefix[int(prefix.len() / 2)], prefix._prefixlen + 1)),
     ]
     if subprefix in prefixes[0]:
         return _remove_subprefix(prefixes[0], subprefix) + IPSet([prefixes[1]])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/IPy-0.81/Makefile new/IPy-0.83/Makefile
--- old/IPy-0.81/Makefile       1970-01-01 01:00:00.000000000 +0100
+++ new/IPy-0.83/Makefile       2015-04-05 02:48:02.000000000 +0200
@@ -0,0 +1,27 @@
+.PHONY: tests egg install clean
+
+PYTHON=python
+
+tests:
+       @echo "[ run unit tests in python 2 ]"
+       PYTHONPATH=$(PWD) $(PYTHON)2.6 test/test_IPy.py || exit $$?
+       @echo "[ run unit tests in python 3 ]"
+       PYTHONPATH=$(PWD) $(PYTHON)3.4 test/test_IPy.py || exit $$?
+       @echo
+       @echo "[ test README in python 2 ]"
+       $(PYTHON)2.6 test_doc.py || exit $$?
+       @echo "[ test README in python 3 ]"
+       $(PYTHON)3.4 test_doc.py || exit $$?
+
+egg: clean
+       $(PYTHON) setup.py sdist bdist_egg
+
+IPy.html: README
+       rst2html README $@ --stylesheet=rest.css
+
+install:
+       ./setup.py install
+
+clean:
+       rm -rf IPy.html *.pyc build dist IPy.egg-info
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/IPy-0.81/PKG-INFO new/IPy-0.83/PKG-INFO
--- old/IPy-0.81/PKG-INFO       2013-04-08 23:22:31.000000000 +0200
+++ new/IPy-0.83/PKG-INFO       1970-01-01 01:00:00.000000000 +0100
@@ -1,306 +0,0 @@
-Metadata-Version: 1.1
-Name: IPy
-Version: 0.81
-Summary: Class and tools for handling of IPv4 and IPv6 addresses and networks
-Home-page: https://github.com/haypo/python-ipy
-Author: Jeff Ferland
-Author-email: jeff AT storyinmemo.com
-License: BSD License
-Download-URL: https://github.com/haypo/python-ipy
-Description: IPy - class and tools for handling of IPv4 and IPv6 addresses and 
networks.
-        
-        Website: https://github.com/haypo/python-ipy/
-        
-        Presentation of the API
-        =======================
-        
-        The IP class allows a comfortable parsing and handling for most
-        notations in use for IPv4 and IPv6 addresses and networks. It was
-        greatly inspired by RIPE's Perl module NET::IP's interface but
-        doesn't share the implementation. It doesn't share non-CIDR netmasks,
-        so funky stuff like a netmask of 0xffffff0f can't be done here.
-        
-            >>> from IPy import IP
-            >>> ip = IP('127.0.0.0/30')
-            >>> for x in ip:
-            ...  print(x)
-            ...
-            127.0.0.0
-            127.0.0.1
-            127.0.0.2
-            127.0.0.3
-            >>> ip2 = IP('0x7f000000/30')
-            >>> ip == ip2
-            1
-            >>> ip.reverseNames()
-            ['0.0.0.127.in-addr.arpa.', '1.0.0.127.in-addr.arpa.', 
'2.0.0.127.in-addr.arpa.', '3.0.0.127.in-addr.arpa.']
-            >>> ip.reverseName()
-            '0-3.0.0.127.in-addr.arpa.'
-            >>> ip.iptype()
-            'PRIVATE'
-        
-        
-        Supports most IP address formats
-        ================================
-        
-        It can detect about a dozen different ways of expressing IP addresses
-        and networks, parse them and distinguish between IPv4 and IPv6 
addresses:
-        
-            >>> IP('10.0.0.0/8').version()
-            4
-            >>> IP('::1').version()
-            6
-        
-        IPv4 addresses
-        --------------
-        
-            >>> print(IP(0x7f000001))
-            127.0.0.1
-            >>> print(IP('0x7f000001'))
-            127.0.0.1
-            >>> print(IP('127.0.0.1'))
-            127.0.0.1
-            >>> print(IP('10'))
-            10.0.0.0
-        
-        IPv6 addresses
-        --------------
-        
-            >>> print(IP('1080:0:0:0:8:800:200C:417A'))
-            1080::8:800:200c:417a
-            >>> print(IP('1080::8:800:200C:417A'))
-            1080::8:800:200c:417a
-            >>> print(IP('::1'))
-            ::1
-            >>> print(IP('::13.1.68.3'))
-            ::d01:4403
-        
-        Network mask and prefixes
-        -------------------------
-        
-            >>> print(IP('127.0.0.0/8'))
-            127.0.0.0/8
-            >>> print(IP('127.0.0.0/255.0.0.0'))
-            127.0.0.0/8
-            >>> print(IP('127.0.0.0-127.255.255.255'))
-            127.0.0.0/8
-        
-        
-        Derive network address
-        ===========================
-        
-        IPy can transform an IP address into a network address by applying the 
given
-        netmask:
-        >>> print(IP('127.0.0.1/255.0.0.0', make_net=True))
-        127.0.0.0/8
-        
-        This can also be done for existing IP instances:
-        >>> print(IP('127.0.0.1').make_net('255.0.0.0'))
-        127.0.0.0/8
-        
-        
-        Convert address to string
-        =========================
-        
-        Nearly all class methods which return a string have an optional
-        parameter 'wantprefixlen' which controls if the prefixlen or netmask
-        is printed. Per default the prefilen is always shown if the network
-        contains more than one address::
-        
-            wantprefixlen == 0 / None     don't return anything   1.2.3.0
-            wantprefixlen == 1            /prefix                 1.2.3.0/24
-            wantprefixlen == 2            /netmask                
1.2.3.0/255.255.255.0
-            wantprefixlen == 3            -lastip                 
1.2.3.0-1.2.3.255
-        
-        You can also change the defaults on an per-object basis by fiddling 
with
-        the class members:
-        
-         * NoPrefixForSingleIp
-         * WantPrefixLen
-        
-        Examples of string conversions:
-        
-            >>> IP('10.0.0.0/32').strNormal()
-            '10.0.0.0'
-            >>> IP('10.0.0.0/24').strNormal()
-            '10.0.0.0/24'
-            >>> IP('10.0.0.0/24').strNormal(0)
-            '10.0.0.0'
-            >>> IP('10.0.0.0/24').strNormal(1)
-            '10.0.0.0/24'
-            >>> IP('10.0.0.0/24').strNormal(2)
-            '10.0.0.0/255.255.255.0'
-            >>> IP('10.0.0.0/24').strNormal(3)
-            '10.0.0.0-10.0.0.255'
-            >>> ip = IP('10.0.0.0')
-            >>> print(ip)
-            10.0.0.0
-            >>> ip.NoPrefixForSingleIp = None
-            >>> print(ip)
-            10.0.0.0/32
-            >>> ip.WantPrefixLen = 3
-            >>> print(ip)
-            10.0.0.0-10.0.0.0
-        
-        Work with multiple networks
-        ===========================
-        
-        Simple addition of neighboring netblocks that can be aggregated will 
yield
-        a parent network of both, but more complex range mapping and 
aggregation
-        requires is available with the IPSet class which will hold any number 
of
-        unique address ranges and will aggregate overlapping ranges.
-        
-            >>> from IPy import IP, IPSet
-            >>> IP('10.0.0.0/22') - IP('10.0.2.0/24')
-            IPSet([IP('10.0.0.0/23'), IP('10.0.3.0/24')])
-            >>> IPSet([IP('10.0.0.0/23'), IP('10.0.3.0/24'), 
IP('10.0.2.0/24')])
-            IPSet([IP('10.0.0.0/22')])
-            >>> s = IPSet([IP('10.0.0.0/22')])
-            >>> s.add(IP('192.168.1.0/29'))
-            >>> s
-            IPSet([IP('10.0.0.0/22'), IP('192.168.1.0/29')])
-            >>> s.discard(IP('192.168.1.2'))
-            >>> s
-            IPSet([IP('10.0.0.0/22'), IP('192.168.1.0/31'), IP('192.168.1.3'), 
IP('192.168.1.4/30')])
-        
-        Compatibility and links
-        =======================
-        
-        IPy 0.81 works on Python version 2.5 - 3.3.
-        
-        This Python module is under BSD license: see COPYING file.
-        
-        Further Information might be available at:
-        https://github.com/haypo/python-ipy
-        
-        What's new
-        ==========
-        
-        Version 0.81 (2013-04-08)
-         * Correct reverseName() for IPv6 addresses, so 
IP('::1').reverseName() returns correct.
-         * Add network mask awareness to v46map()
-         * Fix Python 3 errors in IPSet class
-         * Make IPSet base class be object when MutableSet isn't available, 
fixing
-           errors in Python 2.5
-        
-        Version 0.80 (2013-03-26)
-        ------------
-        
-         * Drop support of Python older than 2.4
-         * Python 3 does not need 2to3 conversion anymore (same code base)
-         * Fix adding of non-adjacent networks:
-           192.168.0.0/24 + 192.168.255.0/24 made 192.168.0.0/23
-         * Fix adding networks that don't create a valid subnet:
-           192.168.1.0/24 + 192.168.2.0/24 made 192.168.1.0/23
-         * Fix adding with an IPv6 address where .int() was < 32 bits made IPy 
believe it
-          was an IPv4 address:
-          ::ffff:0/112 + ::1:0:0/112 made 255.255.0.0/111
-         * Add support of IPSets
-         * Add support for subtracting a network range
-         * Prevent IPv4 and IPv6 ranges from saying they contain each other
-         * Add a .v46map() method to convert mapped address ranges
-           such as IP('::ffff:192.168.1.1'); RFC 4291
-         * Change sort order to more natural: 
-           IPv4 before IPv6; less-specific prefixes first (/0 before /32)
-        
-        
-        Version 0.76 (2013-03-19)
-        -------------------------
-        
-         * ip == other and ip != other doesn't fail with an exception anymore 
if other
-          is not a IP object
-         * Add IP.get_mac() method: get the 802.3 MAC address from IPv6 RFC 
2464
-          address.
-         * Fix IP('::/0')[0]: return an IPv6 instead of an IPv4 address
-        
-        Version 0.75 (2011-04-12)
-        -------------------------
-        
-         * IP('::/0').netmask() gives IP('::') instead of IP('0.0.0.0')
-        
-        Version 0.74 (2011-02-16)
-        -------------------------
-        
-         * Fix tests for Python 3.1 and 3.2
-         * ip.__nonzero__() and (ipa in ipb) return a bool instead of 0 or 1
-         * IP('0.0.0.0/0') + IP('0.0.0.0/0') raises an error, fix written by 
Arfrever
-        
-        Version 0.73 (2011-02-15)
-        -------------------------
-        
-         * Support Python 3: setup.py runs 2to3
-         * Update the ranges for IPv6 IPs
-         * Fix reverseName() and reverseNames() for IPv4 in IPv6 addresses
-         * Drop support of Python < 2.5
-        
-        Version 0.72 (2010-11-23)
-        -------------------------
-        
-         * Include examples and MANIFEST.in in source build (add them to
-           MANIFEST.in)
-         * Remove __rcsid__ constant from IPy module
-        
-        Version 0.71 (2010-10-01)
-        -------------------------
-        
-         * Use xrange() instead of range()
-         * Use isinstance(x, int) instead of type(x) == types.IntType
-         * Prepare support of Python3 (use integer division: x // y)
-         * Fix IP(long) constructor: ensure that the address is not too large
-         * Constructor raise a TypeError if the type is not int, long,
-           str or unicode
-         * 223.0.0.0/8 is now public (belongs to APNIC)
-        
-        Version 0.70 (2009-10-29)
-        -------------------------
-        
-         * New "major" version because it may break compatibility
-         * Fix __cmp__(): IP('0.0.0.0/0') and IP('0.0.0.0') are not equal
-         * Fix IP.net() of the network "::/0": "::" instead of "0.0.0.0".
-           IPy 0.63 should fix this bug, but it wasn't.
-        
-        Version 0.64 (2009-08-19)
-        -------------------------
-        
-         * Create MANIFEST.in to fix setup.py bdist_rpm, fix by Robert Nickel
-        
-        Version 0.63 (2009-06-23)
-        -------------------------
-        
-         * Fix formatting of "IPv4 in IPv6" network, eg. 
IP('::ffff:192.168.10.0/120'),
-           the netmask ("/120" in the example) was missing!
-        
-        Version 0.62 (2008-07-15)
-        -------------------------
-        
-         * Fix reverse DNS of IPv6 address: use ".ip6.arpa." suffix instead of
-           deprecated ".ip6.int." suffix
-        
-        Version 0.61 (2008-06-12)
-        -------------------------
-        
-         * Patch from Aras Vaichas allowing the [-1] operator
-           to work with an IP object of size 1.
-        
-        Version 0.60 (2008-05-16)
-        -------------------------
-        
-         * strCompressed() formats '::ffff:a.b.c.d' correctly
-         * Use strCompressed() instead of strFullsize() to format IP addresses,
-           ouput is smarter with IPv6 address
-         * Remove check_addr_prefixlen because it generates invalid IP address
-Keywords: ipv4 ipv6 netmask
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: System Administrators
-Classifier: Environment :: Plugins
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: Communications
-Classifier: Topic :: Internet
-Classifier: Topic :: System :: Networking
-Classifier: License :: OSI Approved :: BSD License
-Classifier: Operating System :: OS Independent
-Classifier: Natural Language :: English
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/IPy-0.81/README new/IPy-0.83/README
--- old/IPy-0.81/README 2013-04-08 20:30:02.000000000 +0200
+++ new/IPy-0.83/README 2015-04-05 02:48:02.000000000 +0200
@@ -1,6 +1,6 @@
 IPy - class and tools for handling of IPv4 and IPv6 addresses and networks.
 
-Website: https://github.com/haypo/python-ipy/
+Website: https://github.com/autocracy/python-ipy/
 
 Presentation of the API
 =======================
@@ -154,12 +154,39 @@
     >>> s
     IPSet([IP('10.0.0.0/22'), IP('192.168.1.0/31'), IP('192.168.1.3'), 
IP('192.168.1.4/30')])
 
+IPSet supports the `set` method `isdisjoint`:
+
+    >>> s.isdisjoint(IPSet([IP('192.168.0.0/16')]))
+    False
+    >>> s.isdisjoint(IPSet([IP('172.16.0.0/12')]))
+    True
+
+IPSet supports intersection:
+
+    >>> s & IPSet([IP('10.0.0.0/8')])
+    IPSet([IP('10.0.0.0/22')])
+
 Compatibility and links
 =======================
 
-IPy 0.81 works on Python version 2.5 - 3.3.
+IPy 0.83 works on Python version 2.6 - 3.4.
+
+The IP module should work in Python 2.5 as long as the subtraction operation
+is not used. IPSet requires features of the collecitons class which appear
+in Python 2.6, though they can be backported.
+
+Eratta
+======
+
+When using IPv6 addresses, it is best to compare using IP().len() instead of
+len(IP). Addresses with an integer value > 64 bits can break the 2nd method.
+See http://stackoverflow.com/questions/15650878 for more info.
+
+Fuzz testing for IPSet will throw spurious errors when the IPSet module
+combines two smaller prefixes into a larger prefix that matches the random
+prefix tested against.
 
 This Python module is under BSD license: see COPYING file.
 
 Further Information might be available at:
-https://github.com/haypo/python-ipy
+https://github.com/autocracy/python-ipy
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/IPy-0.81/setup.py new/IPy-0.83/setup.py
--- old/IPy-0.81/setup.py       2013-04-08 20:46:39.000000000 +0200
+++ new/IPy-0.83/setup.py       2015-04-05 02:48:02.000000000 +0200
@@ -24,7 +24,7 @@
 import sys
 from distutils.core import setup
 
-VERSION = '0.81'
+VERSION = '0.83'
 
 options = {}
 
@@ -54,7 +54,7 @@
     'Programming Language :: Python',
     'Programming Language :: Python :: 3',
 ]
-URL = "https://github.com/haypo/python-ipy";
+URL = "https://github.com/autocracy/python-ipy";
 
 setup(
     name="IPy",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/IPy-0.81/test/test_IPy.py 
new/IPy-0.83/test/test_IPy.py
--- old/IPy-0.81/test/test_IPy.py       2013-03-27 01:53:18.000000000 +0100
+++ new/IPy-0.83/test/test_IPy.py       2015-04-05 02:48:02.000000000 +0200
@@ -16,8 +16,6 @@
 import unittest
 import random
 
-testloops = 250
-
 class parseAddress(unittest.TestCase):
     okValues = [('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', 
338770000845734292534325025077361652240),
                 ('FEDCBA9876543210FEDCBA9876543210', 
338770000845734292534325025077361652240),
@@ -202,21 +200,6 @@
         self.assertRaises(ValueError, IPy.intToIp, 1, 7)
         self.assertRaises(ValueError, IPy.intToIp, 1, 8)
 
-class ParseAndBack(unittest.TestCase):
-    def testRandomValuesv4(self):
-        for i in range(testloops):
-            question = random.randrange(0x7fffffff) + 
random.randrange(0x7fffffff)
-            self.assertEqual(IPy.parseAddress(IPy.intToIp(question, 4)), 
(question, 4), hex(question))
-
-    def testRandomValuesv6(self):
-        for i in range(testloops):
-            question = ((random.randrange(0x7fffffff) + 
random.randrange(0x7fffffff)) +
-                        ((random.randrange(0x7fffffff) + 
random.randrange(0x7fffffff)) << 32) +
-                        ((random.randrange(0x7fffffff) + 
random.randrange(0x7fffffff)) << 64) +
-                        ((random.randrange(0x7fffffff) + 
random.randrange(0x7fffffff)) << 96))
-            self.assertEqual(IPy.parseAddress(IPy.intToIp(question, 6)), 
(question, 6), hex(question))
-
-
 class _countXBits(unittest.TestCase):
     def testCount1Bits(self):
         self.assertEqual(IPy._count1Bits(0), 0)
@@ -463,6 +446,7 @@
         self.assertEqual(ip[0], ip.net())
         self.assertEqual(ip[-1], ip.broadcast())
         self.assertTrue(ip[255])
+        self.assertTrue(isinstance(ip[4::4], list))
         self.assertRaises(IndexError, ip.__getitem__, 256)
 
     def testStr(self):
@@ -844,10 +828,53 @@
         self.t.discard(self.sixRange)
         self.assertEqual(self.t, self.c)
 
+    def testAnd(self):
+        ten24s = IPy.IPSet([
+            IPy.IP('10.0.1.0/24'),
+            IPy.IP('10.0.3.0/24'),
+            IPy.IP('10.0.5.0/24'),
+            IPy.IP('10.0.7.0/24'),
+        ])
+
+        self.assertEqual(ten24s & IPy.IPSet([IPy.IP('10.0.1.10')]),
+                         IPy.IPSet([IPy.IP('10.0.1.10')]))
+
+        self.assertEqual(ten24s & IPy.IPSet([
+            IPy.IP('10.0.0.99'),
+            IPy.IP('10.0.1.10'),
+            IPy.IP('10.0.3.40'),
+            IPy.IP('11.1.1.99'),
+        ]), IPy.IPSet([
+            IPy.IP('10.0.1.10'),
+            IPy.IP('10.0.3.40'),
+        ]))
+
     def testContains(self):
         self.assertTrue(IPy.IP('192.168.15.32/28') in self.t)
         self.assertFalse(IPy.IP('192.169.15.32/28') in self.t)
 
+        # test for a regression where __contains__ prematurely returns False
+        # after testing a prefix length where all IP instances are greater than
+        # the query IP.
+        ipset = IPy.IPSet([IPy.IP('10.0.0.0/8'), IPy.IP('128.0.0.0/1')])
+        self.assertTrue(IPy.IP('10.0.0.0') in ipset)
+
+    def testIsdisjoint(self):
+        self.assertTrue(IPy.IPSet([IPy.IP('0.0.0.0/1')])
+                .isdisjoint(IPy.IPSet([IPy.IP('128.0.0.0/1')])))
+        self.assertFalse(IPy.IPSet([IPy.IP('0.0.0.0/1')])
+                .isdisjoint(IPy.IPSet([IPy.IP('0.0.0.0/2')])))
+        self.assertFalse(IPy.IPSet([IPy.IP('0.0.0.0/2')])
+                .isdisjoint(IPy.IPSet([IPy.IP('0.0.0.0/1')])))
+        self.assertFalse(IPy.IPSet([IPy.IP('0.0.0.0/2')])
+                .isdisjoint(IPy.IPSet([IPy.IP('0.1.2.3')])))
+        self.assertFalse(IPy.IPSet([IPy.IP('0.1.2.3')])
+                .isdisjoint(IPy.IPSet([IPy.IP('0.0.0.0/2')])))
+        self.assertTrue(IPy.IPSet([IPy.IP('1.1.1.1'), IPy.IP('1.1.1.3')])
+                .isdisjoint(IPy.IPSet([IPy.IP('1.1.1.2'), IPy.IP('1.1.1.4')])))
+        self.assertFalse(IPy.IPSet([IPy.IP('1.1.1.1'), IPy.IP('1.1.1.3'), 
IPy.IP('1.1.2.0/24')])
+                .isdisjoint(IPy.IPSet([IPy.IP('1.1.2.2'), IPy.IP('1.1.1.4')])))
+
 class RegressionTest(unittest.TestCase):
     def testNulNetmask(self):
         ip = timeout(IPy.IP, ["0.0.0.0/0.0.0.0"], timeout_duration=0.250, 
default=None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/IPy-0.81/test/test_fuzz.py 
new/IPy-0.83/test/test_fuzz.py
--- old/IPy-0.81/test/test_fuzz.py      1970-01-01 01:00:00.000000000 +0100
+++ new/IPy-0.83/test/test_fuzz.py      2015-04-05 02:48:02.000000000 +0200
@@ -0,0 +1,109 @@
+"""Fuzing for IPy.py"""
+
+# TODO: unify assert / FilIf usage
+
+import sys
+import functools
+import itertools
+sys.path.append('.')
+sys.path.append('..')
+
+import IPy
+import unittest
+import random
+
+if sys.version_info >= (3,):
+    xrange = range
+
+# on Python-2.7 and higher, we use load_tests to multiply out the test cases 
so that unittest
+# represents each as an individual test case.
+def iterate_27(n):
+    def wrap(func):
+        func.iterations = n
+        return func
+    return wrap
+
+def load_tests(loader, tests, pattern):
+    def expand(tests):
+        if isinstance(tests, unittest.TestCase):
+            method_name = tests._testMethodName
+            meth = getattr(tests, method_name)
+            if hasattr(meth, 'iterations'):
+                tests = unittest.TestSuite(type(tests)(method_name) for i in 
xrange(meth.iterations))
+        else:
+            tests = unittest.TestSuite(expand(t) for t in tests)
+        return tests
+    return expand(tests)
+
+# On older Pythons, we run the requisite iterations directly, in a single test 
case.
+def iterate_old(n):
+    def wrap(func):
+        @functools.wraps(func)
+        def replacement(*args):
+            for i in xrange(n):
+                func(*args)
+        return replacement
+    return wrap
+
+if sys.version_info >= (2,7):
+    iterate = iterate_27
+else:
+    iterate = iterate_old
+
+# utilities
+
+def random_ipv4_prefix():
+    prefixlen = random.randrange(32)
+    int_ip = random.randrange(IPy.MAX_IPV4_ADDRESS)
+    int_ip &= 0xffffffff << (32-prefixlen)
+    return IPy.IP('.'.join(map(str, (int_ip >> 24,
+                                    (int_ip >> 16) & 0xff,
+                                    (int_ip >> 8) & 0xff,
+                                    int_ip & 0xff)))
+                           + '/%d' % prefixlen)
+
+# tests
+
+class ParseAndBack(unittest.TestCase):
+
+    @iterate(500)
+    def testRandomValuesv4(self):
+        question = random.randrange(0xffffffff)
+        self.assertEqual(IPy.parseAddress(IPy.intToIp(question, 4)), 
(question, 4), hex(question))
+
+    @iterate(500)
+    def testRandomValuesv6(self):
+        question = random.randrange(0xffffffffffffffffffffffffffffffff)
+        self.assertEqual(IPy.parseAddress(IPy.intToIp(question, 6)), 
(question, 6), hex(question))
+
+class TestIPSet(unittest.TestCase):
+
+    @iterate(1000)
+    def testRandomContains(self):
+        prefixes = [random_ipv4_prefix() for i in xrange(random.randrange(50))]
+        question = random_ipv4_prefix()
+        answer = any(question in pfx for pfx in prefixes)
+        ipset = IPy.IPSet(prefixes)
+        self.assertEqual(question in ipset, answer,
+                "%s in %s != %s (made from %s)" % (question, ipset, answer, 
prefixes))
+        
+
+    @iterate(1000)
+    def testRandomDisjoint(self):
+        prefixes1 = [random_ipv4_prefix() for i in 
xrange(random.randrange(50))]
+        prefixes2 = [random_ipv4_prefix() for i in 
xrange(random.randrange(50))]
+        # test disjointnes the stupid way
+        disjoint = True
+        for p1, p2 in itertools.product(prefixes1, prefixes2):
+            if p1 in p2 or p2 in p1:
+                disjoint = False
+                break
+        ipset1 = IPy.IPSet(prefixes1)
+        ipset2 = IPy.IPSet(prefixes2)
+        self.assertEqual(ipset1.isdisjoint(ipset2), disjoint,
+                "%s.isdisjoint(%s) != %s" % (ipset1, ipset2, disjoint))
+        self.assertEqual(ipset2.isdisjoint(ipset1), disjoint,
+                "%s.isdisjoint(%s) != %s" % (ipset2, ipset1, disjoint))
+
+if __name__ == "__main__":
+    unittest.main()


Reply via email to