commit python-ipy for openSUSE:Factory
Hello community, here is the log from the commit of package python-ipy for openSUSE:Factory checked in at 2019-05-25 13:17:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-ipy (Old) and /work/SRC/openSUSE:Factory/.python-ipy.new.5148 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-ipy" Sat May 25 13:17:41 2019 rev:9 rq:704422 version:1.00 Changes: -------- --- /work/SRC/openSUSE:Factory/python-ipy/python-ipy.changes 2018-11-26 10:30:27.601017171 +0100 +++ /work/SRC/openSUSE:Factory/.python-ipy.new.5148/python-ipy.changes 2019-05-25 13:17:42.760392831 +0200 @@ -1,0 +2,8 @@ +Tue May 21 10:06:13 UTC 2019 - pgajdos@suse.com + +- version update to 1.00 + * Fix IPv6 string interpretation for small ints + * Various Python3 language fixes + * consider 127.0 range LOOPBACK not PRIVATE + +------------------------------------------------------------------- Old: ---- IPy-0.83.tar.gz New: ---- IPy-1.00.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-ipy.spec ++++++ --- /var/tmp/diff_new_pack.jIq7uG/_old 2019-05-25 13:17:44.160392311 +0200 +++ /var/tmp/diff_new_pack.jIq7uG/_new 2019-05-25 13:17:44.180392303 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-ipy # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 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 @@ -12,13 +12,13 @@ # 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/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-ipy -Version: 0.83 +Version: 1.00 Release: 0 Summary: Class and tools for handling of IPv4 and IPv6 addresses and networks License: BSD-3-Clause @@ -48,10 +48,14 @@ %install %python_install %python_expand %fdupes %{buildroot}%{$python_sitelib} -#install COPYING %{buildroot} %files %{python_files} %{python_sitelib}/* %license COPYING +%check +%python_exec test/test_IPy.py +# one of 3000 subtest fails, probably https://github.com/autocracy/python-ipy/issues/27 +# %%python_exec test/test_fuzz.py + %changelog ++++++ IPy-0.83.tar.gz -> IPy-1.00.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/.gitignore new/IPy-1.00/.gitignore --- old/IPy-0.83/.gitignore 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/.gitignore 1970-01-01 01:00:00.000000000 +0100 @@ -1,2 +0,0 @@ -*.pyc -*.swp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/COPYING new/IPy-1.00/COPYING --- old/IPy-0.83/COPYING 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/COPYING 2018-02-01 09:32:18.000000000 +0100 @@ -1,3 +1,4 @@ +"BSD 3-clause" License Copyright (c) 2006, INL Copyright (c) 2001-2005, Maximillian Dornseif All rights reserved. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/ChangeLog new/IPy-1.00/ChangeLog --- old/IPy-0.83/ChangeLog 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/ChangeLog 2019-02-28 00:46:40.000000000 +0100 @@ -1,3 +1,8 @@ +Version 1.00 (2019-02-27) + * Fix IPv6 string interpretation for small ints + * Various Python3 language fixes + * consider 127.0 range LOOPBACK not PRIVATE + Version 0.83 (2015-04-04) ------------ * Add carrier grade NAT ranges diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/IPy.py new/IPy-1.00/IPy.py --- old/IPy-0.83/IPy.py 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/IPy.py 2019-02-28 01:00:55.000000000 +0100 @@ -6,7 +6,7 @@ https://github.com/haypo/python-ipy """ -__version__ = '0.83' +__version__ = '1.00' import bisect import collections @@ -21,7 +21,7 @@ '00000000': 'PRIVATE', # 0/8 '00001010': 'PRIVATE', # 10/8 '0110010001': 'CARRIER_GRADE_NAT', #100.64/10 - '01111111': 'PRIVATE', # 127.0/8 + '01111111': 'LOOPBACK', # 127.0/8 '1': 'PUBLIC', # fall back '1010100111111110': 'PRIVATE', # 169.254/16 '101011000001': 'PRIVATE', # 172.16/12 @@ -243,7 +243,7 @@ else: raise ValueError("can't parse") - (self.ip, parsedVersion) = parseAddress(ip) + (self.ip, parsedVersion) = parseAddress(ip, ipversion) if ipversion == 0: ipversion = parsedVersion if prefixlen == -1: @@ -475,7 +475,7 @@ """Return a description of the IP type ('PRIVATE', 'RESERVED', etc). >>> print(IP('127.0.0.1').iptype()) - PRIVATE + LOOPBACK >>> print(IP('192.168.1.1').iptype()) PRIVATE >>> print(IP('195.185.1.2').iptype()) @@ -558,6 +558,8 @@ """ return True + def __bool__(self): + return self.__nonzero__() def __len__(self): """ @@ -769,6 +771,9 @@ def __lt__(self, other): return self.__cmp__(other) < 0 + def __le__(self, other): + return self.__cmp__(other) <= 0 + def __hash__(self): """Called for the key object for dictionary operations, and by the built-in function hash(). Should return a 32-bit integer @@ -1336,7 +1341,7 @@ index += 1 return value -def parseAddress(ipstr): +def parseAddress(ipstr, ipversion=0): """ Parse a string and return the corresponding IP address (as integer) and a guess of the IP version. @@ -1405,7 +1410,7 @@ # assume IPv6 in pure hexadecimal notation return (hexval, 6) - elif ipstr.find('.') != -1 or (intval is not None and intval < 256): + elif ipstr.find('.') != -1 or (intval is not None and intval < 256 and ipversion != 6): # assume IPv4 ('127' gets interpreted as '127.0.0.0') bytes = ipstr.split('.') if len(bytes) > 4: @@ -1423,7 +1428,7 @@ # will be interpreted as IPv4 first byte if intval > MAX_IPV6_ADDRESS: raise ValueError("IP Address can't be larger than %x: %x" % (MAX_IPV6_ADDRESS, intval)) - if intval <= MAX_IPV4_ADDRESS: + if intval <= MAX_IPV4_ADDRESS and ipversion != 6: return (intval, 4) else: return (intval, 6) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/MANIFEST.in new/IPy-1.00/MANIFEST.in --- old/IPy-0.83/MANIFEST.in 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/MANIFEST.in 2018-02-01 09:32:18.000000000 +0100 @@ -1,4 +1,5 @@ include AUTHORS +include README.rst include ChangeLog include COPYING include MANIFEST.in diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/Makefile new/IPy-1.00/Makefile --- old/IPy-0.83/Makefile 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,27 +0,0 @@ -.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.83/PKG-INFO new/IPy-1.00/PKG-INFO --- old/IPy-0.83/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 +++ new/IPy-1.00/PKG-INFO 2019-02-28 01:20:19.000000000 +0100 @@ -0,0 +1,367 @@ +Metadata-Version: 1.1 +Name: IPy +Version: 1.00 +Summary: Class and tools for handling of IPv4 and IPv6 addresses and networks +Home-page: https://github.com/autocracy/python-ipy +Author: Jeff Ferland +Author-email: jeff@storyinmemo.com +License: BSD License +Download-URL: https://github.com/autocracy/python-ipy +Description: IPy - class and tools for handling of IPv4 and IPv6 addresses and networks. + + Website: https://github.com/autocracy/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() + 'LOOPBACK' + + + 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')]) + + ``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 1.00 works on Python version 2.6 - 3.7. + + 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/autocracy/python-ipy + + What's new + ========== + + Version 1.00 (2019-02-27) + * Fix IPv6 string interpretation for small ints + * Various Python3 language fixes + * consider 127.0 range LOOPBACK not PRIVATE + + 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 + * 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.83/README new/IPy-1.00/README --- old/IPy-0.83/README 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/README 1970-01-01 01:00:00.000000000 +0100 @@ -1,192 +0,0 @@ -IPy - class and tools for handling of IPv4 and IPv6 addresses and networks. - -Website: https://github.com/autocracy/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')]) - -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.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/autocracy/python-ipy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/README.rst new/IPy-1.00/README.rst --- old/IPy-0.83/README.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/IPy-1.00/README.rst 2019-02-28 00:55:17.000000000 +0100 @@ -0,0 +1,201 @@ +IPy - class and tools for handling of IPv4 and IPv6 addresses and networks. + +Website: https://github.com/autocracy/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() + 'LOOPBACK' + + +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')]) + +``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 1.00 works on Python version 2.6 - 3.7. + +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/autocracy/python-ipy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/setup.py new/IPy-1.00/setup.py --- old/IPy-0.83/setup.py 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/setup.py 2019-02-28 01:20:06.000000000 +0100 @@ -4,15 +4,14 @@ # # - set version in IPy.py # - set version in setup.py +# - set version in README.rst # - run unit test: make -# - run unit test: make PYTHON=python3 # - set release date in ChangeLog # - git commit -a # - git tag -a IPy-x.y -m "tag IPy x.y" # - git push # - git push --tags # - python setup.py register sdist upload -# - update the website # # After the release: # - set version to n+1 (IPy.py and setup.py) @@ -24,11 +23,11 @@ import sys from distutils.core import setup -VERSION = '0.83' +VERSION = '1.00' options = {} -with open('README') as fp: +with open('README.rst') as fp: README = fp.read().strip() + "\n\n" ChangeLog = ( @@ -63,7 +62,7 @@ long_description=LONG_DESCRIPTION, author="Maximillian Dornseif", maintainer="Jeff Ferland", - maintainer_email="jeff AT storyinmemo.com", + maintainer_email="jeff@storyinmemo.com", license="BSD License", keywords="ipv4 ipv6 netmask", url=URL, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/test/test.rst new/IPy-1.00/test/test.rst --- old/IPy-0.83/test/test.rst 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/test/test.rst 2019-02-28 00:45:37.000000000 +0100 @@ -29,8 +29,8 @@
d={} d[IP('0.0.0.0/0')] = 1 d[IP('::/0')] = 2 ->>> d -{IP('::/0'): 2, IP('0.0.0.0/0'): 1} +>>> sorted(d.items()) +[(IP('0.0.0.0/0'), 1), (IP('::/0'), 2)]
addresses = [IP('0.0.0.0/16'), IP('::7'), IP('::3'), IP('::0'), ... IP('0.0.0.0'), IP('0.0.0.3'), IP('0.0.0.0/0'), IP('::/0')] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/test/test_IPy.py new/IPy-1.00/test/test_IPy.py --- old/IPy-0.83/test/test_IPy.py 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/test/test_IPy.py 2019-02-28 00:46:37.000000000 +0100 @@ -210,7 +210,7 @@ self.assertEqual(IPy._count1Bits(0xffffffff), 32) self.assertEqual(IPy._count1Bits(0xffffffffffffffffffffffffffffffff), 128)
- def testCount1Bits(self): + def testCount0Bits(self): self.assertEqual(IPy._count0Bits(0), 0) self.assertEqual(IPy._count0Bits(0xf0), 4) self.assertEqual(IPy._count0Bits(0xf00), 8) @@ -612,7 +612,7 @@ self.assertEqual(str(IPy.IP("0.0.0.0/0").netmask()), "0.0.0.0") self.assertEqual(str(IPy.IP("0.0.0.0/32").netmask()), "255.255.255.255") self.assertEqual(str(IPy.IP("127.0.0.0/24").netmask()), "255.255.255.0") - self.assertEqual(str(IPy.IP("2001:1234:5678:1234::/64").netmask()), "ffff:ffff:ffff:ffff:0000:0000:0000:0000") + self.assertEqual(str(IPy.IP("2001:1234:5678:1234::/64").netmask()), "ffff:ffff:ffff:ffff::") def testInt(self): """Prefixlen""" @@ -661,19 +661,6 @@ result = IPy.IP(a).overlaps(b) self.assertEqual(answer, result, (a, b, result, answer)) - def testNetmask(self): - """Normal string Output.""" - testValues = [(338770000845734292534325025077361652240, '0xfedcba9876543210fedcba9876543210'), - (21932261930451111902915077091070067066, '0x108000000000000000080800200c417a'), - (338958331222012082418099330867817087043, '0xff010000000000000000000000000043'), - (0, '0x0'), - (1, '0x1'), - (4294967295, '0xffffffff'), - (3588059479, '0xd5dd7157')] - for (question, answer) in testValues: - result = IPy.IP(question).strHex(question).lower() - self.assertEqual(answer, result, (question, result, answer)) - def testV46map(self): four = IPy.IP('192.168.1.1') six = IPy.IP('::ffff:192.168.1.1') @@ -904,6 +891,9 @@ self.assertEqual(len(IPy.IP('192.168.0.0/24')), 256) self.assertRaises(ValueError, IPy.IP, '192.168.1.0/42') + def testConsistentIP6StrInt(self): + self.assertEqual(IPy.IP('11', ipversion=6), IPy.IP(11, ipversion=6)) + class TestConstrutor(unittest.TestCase): def testCheckAddrPrefixlenOff(self): self.assertRaises(ValueError, IPy.IP, 0xffffffff + 1, ipversion=4) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/IPy-0.83/test_doc.py new/IPy-1.00/test_doc.py --- old/IPy-0.83/test_doc.py 2015-04-05 02:48:02.000000000 +0200 +++ new/IPy-1.00/test_doc.py 2018-02-01 09:32:18.000000000 +0100 @@ -5,7 +5,7 @@ total_failures, total_tests = (0, 0) print("=== Test file: README ===") - failure, tests = doctest.testfile('README', optionflags=doctest.ELLIPSIS) + failure, tests = doctest.testfile('README.rst', optionflags=doctest.ELLIPSIS) total_failures += failure total_tests += tests
participants (1)
-
root