Skip to content
Snippets Groups Projects
Commit 4892f4b9 authored by Pavel Kácha's avatar Pavel Kácha
Browse files

Initial commit - split from IDEA repository, commit e341f9e836b6a8bca64704acdeb93e1ef40e810f

parents
No related branches found
No related tags found
No related merge requests found
!.gitignore
.directory
*.[oa]
*~
*.log
*.pem
*.cert
*.key
*.gpg
*.tar
*.gz
*.bz2
*.xz
*.tgz
*.tbz2
*.txz
*.deb
# Python related stuff.
*.pyc
*.egg-info
__pycache__
build
# Grunt automation tool related stuff
/node_modules/
LICENSE 0 → 100644
Copyright (c) 2016, CESNET, z. s. p. o.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
\ No newline at end of file
Makefile 0 → 100644
#-------------------------------------------------------------------------------
# Copyright (c) since 2016, CESNET, z. s. p. o.
# Authors: Pavel Kácha <pavel.kacha@cesnet.cz>
# Jan Mach <jan.mach@cesnet.cz>
# Use of this source is governed by an ISC license, see LICENSE file.
#-------------------------------------------------------------------------------
all: archive bdist deploy
build: archive bdist
help:
$(info List of possible make targets:)
$(info )
$(info * all: archive previous packages, build new distribution and deploy to PyPI [default])
$(info * build: archive previous packages and build new distribution)
$(info * test: run unit tests)
$(info * archive: archive previous packages)
$(info * bdist: build new distribution)
$(info * install: install distribution on local machine)
$(info * deploy: deploy to PyPI)
$(info )
# Perform unit tests
test: FORCE
$(info Testing source code)
nosetests
# Move old distribution files to archive directory
archive: FORCE
$(info Checking if dist archivation is needed)
@if ! [ `ls dist/ipranges* | wc -l` = "0" ]; then\
echo "Moving old distribution files to local archive";\
mv -f dist/ipranges* archive;\
fi
# Build various Python package distributions
bdist:
$(info Building distributions)
# Build and upload (insecure)
#python3 setup.py sdist bdist_wheel upload
# Build only
python3 setup.py sdist bdist_wheel --universal
# Perform installation from local files for both Python 2 and 3
install: FORCE
$(info Local installation)
pip install dist/ipranges*.whl
pip3 install dist/ipranges*.whl
# Deploy latest packages to PyPI
deploy: FORCE
$(info PyPI deployment)
# Secure upload with Twine
twine upload dist/ipranges*
# Empty rule as dependency wil force make to always perform target
# Source: https://www.gnu.org/software/make/manual/html_node/Force-Targets.html
FORCE:
ipranges
================================================================================
Python 2 and 3 compatible library for working with IPv4 and IPv6 addressess in
many notations (sible IP, CIDR, range).
This README file is work in progress, for more information please visit home page
at https://idea.cesnet.cz/en/index.
# Ignore everything in this directory
*
# Except this file
!.gitignore
# Ignore everything in this directory
*
# Except this file
!.gitignore
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2016, CESNET, z. s. p. o.
# Use of this source is governed by an ISC license, see LICENSE file.
__version__ = '0.1.7'
__author__ = 'Pavel Kácha <pavel.kacha@cesnet.cz>'
import socket
import struct
import numbers
try:
basestring
except NameError:
basestring = str
class Range(object):
__slots__ = ()
single = int
def __len__(self):
return self.high() - self.low() + 1
def __eq__(self, other):
return (self.low() == other.low() and self.high() == other.high())
def __ne__(self, other):
return not self.__eq__(other)
def __contains__(self, other):
return (self.low() <= other.low() and self.high() >= other.high())
def __iter__(self):
for i in range(self.low(), self.high()+1):
yield self.util.single(i)
def __getitem__(self, key):
if isinstance(key, slice):
return (self.util.single(self.low() + i) for i in range(*key.indices(len(self))))
else:
if key < 0:
idx = self.high() + key + 1
else:
idx = self.low() + key
if self.low() <= idx <= self.high():
return self.util.single(idx)
else:
raise IndexError
def __repr__(self):
return "%s('%s')" % (type(self).__name__, str(self))
class IPBase(Range):
__slots__ = ()
def __init__(self, s):
if isinstance(s, basestring):
rng = self._from_str(s)
elif isinstance(s, IPBase):
rng = self._from_range(s)
else:
rng = self._from_val(s)
self._assign(rng)
def cidr_split(self):
lo, hi = self.low(), self.high()
lo, hi = min(lo, hi), max(lo, hi)
while lo<=hi:
lower_bits = (~lo & (lo-1)).bit_length()
size = hi - lo + 1
size_bits = size.bit_length() - 1
bits = min(lower_bits, size_bits)
yield self.util.net((lo, self.util.bit_length-bits))
lo += 1 << bits
def _from_val(self, v):
try:
a, b = v
return int(a), int(b)
except Exception:
raise ValueError("Two value tuple expected, got %s" % v)
class IPRangeBase(IPBase):
__slots__ = ("lo", "hi")
def _from_range(self, r):
return (r.low(), r.high())
def _from_str(self, s):
try:
ip1, ip2 = s.split("-")
return (self.util.from_str(ip1), self.util.from_str(ip2))
except Exception:
raise ValueError("Wrong range format: %s" % s)
def _assign(self, v):
self.lo = min(v)
self.hi = max(v)
def low(self): return self.lo
def high(self): return self.hi
def __str__(self):
return "%s-%s" % (self.util.to_str(self.lo), self.util.to_str(self.hi))
class IPNetBase(IPBase):
__slots__ = ("base", "cidr", "mask")
def _from_range(self, r):
lo = r.low()
mask = len(r) - 1
if (len(r) & mask) or (lo & mask):
raise ValueError("%s is not a proper network prefix" % r)
return lo, self.util.bit_length - mask.bit_length()
def _from_str(self, s):
try:
net, cidr = s.split("/")
base = self.util.from_str(net)
cidr = int(cidr)
return base, cidr
except Exception:
raise ValueError("Wrong network format: %s" % s)
def _assign(self, v):
self.base, self.cidr = v
self.mask = (self.util.full_mask << (self.util.bit_length - self.cidr)) & self.util.full_mask
def low(self): return self.base & self.mask
def high(self): return self.base | (self.mask ^ self.util.full_mask)
def __str__(self):
return "%s/%i" % (self.util.to_str(self.base), self.cidr)
class IPAddrBase(IPBase):
__slots__ = ("ip")
def _from_range(self, r):
if len(r)!=1:
raise ValueError("Unable to convert network %s to one ip address" % r)
return r.low()
def _from_str(self, s): return self.util.from_str(s)
def _from_val(self, r):
try:
return int(r)
except Exception:
raise ValueError("Integer expected as IP")
def _assign(self, v): self.ip = v
def __str__(self): return self.util.to_str(self.ip)
def __int__(self): return self.ip
def low(self): return self.ip
def high(self): return self.ip
class IP4Util(object):
__slots__ = ()
bit_length = 32
full_mask = 2**bit_length-1
@staticmethod
def from_str(s):
try:
return struct.unpack("!L", socket.inet_pton(socket.AF_INET, s))[0]
except Exception:
raise ValueError("Wrong IPv4 address format: %s" % s)
@staticmethod
def to_str(i):
try:
return socket.inet_ntop(socket.AF_INET, struct.pack('!L', i))
except Exception:
raise ValueError("Unable to convert to IPv6 address: %s" % i)
class IP6Util(object):
__slots__ = ()
bit_length = 128
full_mask = 2**bit_length-1
@staticmethod
def from_str(s):
try:
hi, lo = struct.unpack("!QQ", socket.inet_pton(socket.AF_INET6, s))
return hi << 64 | lo
except Exception:
raise ValueError("Wrong IPv6 address format: %s" % s)
@staticmethod
def to_str(i):
try:
hi = i >> 64
lo = i & 0xFFFFFFFFFFFFFFFF
return socket.inet_ntop(socket.AF_INET6, struct.pack('!QQ', hi, lo))
except Exception:
raise ValueError("Unable to convert to IPv6 address: %s" % i)
class IP4(IPAddrBase):
__slots__ = ()
util = IP4Util
class IP6(IPAddrBase):
__slots__ = ()
util = IP6Util
class IP4Range(IPRangeBase):
__slots__ = ()
util = IP4Util
class IP6Range(IPRangeBase):
__slots__ = ()
util = IP6Util
class IP4Net(IPNetBase):
__slots__ = ()
util = IP4Util
class IP6Net(IPNetBase):
__slots__ = ()
util = IP6Util
IP4Util.single = IP4
IP6Util.single = IP6
IP4Util.net = IP4Net
IP6Util.net = IP6Net
def from_str(s):
for t in IP4Net, IP4Range, IP4, IP6Net, IP6Range, IP6:
try:
return t(s)
except ValueError:
pass
raise ValueError("%s does not appear as IP address, network or range string" % s)
def from_str_v4(s):
for t in IP4Net, IP4Range, IP4:
try:
return t(s)
except ValueError:
pass
raise ValueError("%s does not appear as IPv4 address, network or range string" % s)
def from_str_v6(s):
for t in IP6Net, IP6Range, IP6:
try:
return t(s)
except ValueError:
pass
raise ValueError("%s does not appear as IPv6 address, network or range string" % s)
setup.py 0 → 100644
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#-------------------------------------------------------------------------------
# Copyright (c) since 2016, CESNET, z. s. p. o.
# Authors: Pavel Kácha <pavel.kacha@cesnet.cz>
# Jan Mach <jan.mach@cesnet.cz>
# Use of this source is governed by an ISC license, see LICENSE file.
#-------------------------------------------------------------------------------
# Resources:
# https://packaging.python.org/en/latest/
# http://python-packaging-user-guide.readthedocs.io/distributing/
# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path
here = path.abspath(path.dirname(__file__))
# Get the long description from the README file
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
long_description = f.read()
setup(
name = 'ipranges',
version = '0.1.7',
description = 'Python library for working with IP addressess.',
long_description = long_description,
classifiers = [
'Development Status :: 4 - Beta',
'License :: OSI Approved :: ISC License (ISCL)',
'Programming Language :: Python',
],
keywords = 'library',
url = 'https://homeproj.cesnet.cz/git/idea.git',
author = 'Pavel Kacha',
author_email = 'pavel.kacha@cesnet.cz',
license = 'ISC',
py_modules = ['ipranges'],
test_suite = 'nose.collector',
tests_require = [
'nose'
],
zip_safe = True
)
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2016, CESNET, z. s. p. o.
# Use of this source is governed by an ISC license, see LICENSE file.
import unittest
from ipranges import IP4, IP6, IP4Range, IP6Range, IP4Net, IP6Net, from_str
class TestIPRange(unittest.TestCase):
def testIP4(self):
for ip in ["0.0.0.0", "192.0.2.100", "255.255.255.255"]:
self.assertEqual(str(IP4(ip)), ip)
def testIP4Fail(self):
for ip in ["", "-", "/", "0", "123", "1.2.3.4.5"]:
with self.assertRaises(ValueError):
IP4(ip)
def testIP6(self):
for ip in ["::", "2001:db8:220:1:248:1893:25c8:1946", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]:
self.assertEqual(str(IP6(ip)), ip)
def testIP6Fail(self):
for ip in ["", "-", "/", "0", "123", "1:2::3::"]:
with self.assertRaises(ValueError):
IP6(ip)
def testIP4Range(self):
for r in ["0.0.0.0-255.255.255.255", "192.0.2.64-192.0.2.127", "192.0.2.5-192.0.2.5"]:
self.assertEqual(str(IP4Range(r)), r)
def testIP4RangeFail(self):
for r in ["", "0.0.0.0", "asdf"]:
with self.assertRaises(ValueError):
IP4Range(r)
def testIP4RangeFail2(self):
for r in ["192.0.2.64-", "-192.0.2.5", "-"]:
with self.assertRaises(ValueError):
IP4Range(r)
def testIP6Range(self):
for r in ["::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "2001:db8:220:1:248:1893:25c8:1946-2001:db8:230:1:248:1893:25c8:1946", "2001:db8:230::25c8:1946-2001:db8:230::25c8:1946"]:
self.assertEqual(str(IP6Range(r)), r)
def testIP6RangeFail(self):
for r in ["", "::", "asdf"]:
with self.assertRaises(ValueError):
IP6Range(r)
def testIP6RangeFail2(self):
for r in ["2001:db8:220:1:248:1893:25c8:1946-", "-2001:db8:220:1:248:1893:25c8:1946", "-"]:
with self.assertRaises(ValueError):
IP6Range(r)
def testIP4Net(self):
for n in ["0.0.0.0/0", "192.0.2.64/26", "192.0.2.5/32"]:
self.assertEqual(str(IP4Net(n)), n)
def testIP4NetFail(self):
for r in ["", "0.0.0.0", "asdf", "192.0.2.64/", "192.0.2.64/?"]:
with self.assertRaises(ValueError):
IP4Net(r)
def testIP4NetFail2(self):
for r in ["/26", "/"]:
with self.assertRaises(ValueError):
IP4Net(r)
def testIP6Net(self):
for n in ["::/0", "2001:db8:220:1::/64", "2001:db8:230::25c8:1946/32"]:
self.assertEqual(str(IP6Net(n)), n)
def testIP6NetFail(self):
for r in ["", "0.0.0.0", "asdf", "2001:db8:220:1::/", "2001:db8:220:1::/?"]:
with self.assertRaises(ValueError):
IP6Net(r)
def testIP6NetFail2(self):
for r in ["/26", "/"]:
with self.assertRaises(ValueError):
IP6Net(r)
def test4SameNetRange(self):
net1 = IP4Net("192.0.2.64/26")
net2 = IP4Range("192.0.2.64-192.0.2.127")
self.assertTrue(net1 == net2)
self.assertFalse(net1 != net2)
def test4SameOne(self):
ip1 = IP4Net("192.0.2.65/32")
ip2 = IP4Range("192.0.2.65-192.0.2.65")
ip3 = IP4("192.0.2.65")
self.assertTrue(ip1 == ip2)
self.assertTrue(ip2 == ip3)
self.assertTrue(ip1 == ip3)
self.assertFalse(ip1 != ip2)
self.assertFalse(ip2 != ip3)
self.assertFalse(ip1 != ip3)
def test6SameNetRange(self):
net1 = IP6Net("2001:db8:220:1::/64")
net2 = IP6Range("2001:db8:220:1::-2001:db8:220:1:ffff:ffff:ffff:ffff")
self.assertTrue(net1 == net2)
self.assertFalse(net1 != net2)
def test6SameOne(self):
ip1 = IP6Net("2001:db8:220:1:248:1893:25c8:1946/128")
ip2 = IP6Range("2001:db8:220:1:248:1893:25c8:1946-2001:db8:220:1:248:1893:25c8:1946")
ip3 = IP6("2001:db8:220:1:248:1893:25c8:1946")
self.assertTrue(ip1 == ip2)
self.assertTrue(ip2 == ip3)
self.assertTrue(ip1 == ip3)
self.assertFalse(ip1 != ip2)
self.assertFalse(ip2 != ip3)
self.assertFalse(ip1 != ip3)
def test4Contains(self):
self.assertTrue(IP4Net("192.0.2.64/28") in IP4Net("192.0.2.64/26"))
self.assertTrue(IP4Net("192.0.2.64/28") in IP4Range("192.0.2.64-192.0.2.127"))
self.assertTrue(IP4Net("192.0.2.65/32") in IP4("192.0.2.65"))
self.assertTrue(IP4Range("192.0.2.65-192.0.2.126") in IP4Range("192.0.2.64-192.0.2.127"))
self.assertTrue(IP4Range("192.0.2.65-192.0.2.126") in IP4Net("192.0.2.64/26"))
self.assertTrue(IP4Range("192.0.2.65-192.0.2.65") in IP4("192.0.2.65"))
self.assertTrue(IP4("192.0.2.65") in IP4Range("192.0.2.64-192.0.2.127"))
self.assertTrue(IP4("192.0.2.65") in IP4Net("192.0.2.64/26"))
self.assertTrue(IP4("192.0.2.65") in IP4("192.0.2.65"))
def test6Contains(self):
self.assertTrue(IP6Net("2001:db8:220:1::/64") in IP6Net("2001:db8:220:1::/64"))
self.assertTrue(IP6Net("2001:db8:220:1::/64") in IP6Range("2001:db8:220:1::-2001:db8:220:1:ffff:ffff:ffff:ffff"))
self.assertTrue(IP6Net("2001:db8:220:1:248:1893:25c8:1946/128") in IP6("2001:db8:220:1:248:1893:25c8:1946"))
self.assertTrue(IP6Range("2001:db8:220:1::-2001:db8:220:1:ffff:ffff:ffff:ffff") in IP6Range("2001:db8:220:1::-2001:db8:220:1:ffff:ffff:ffff:ffff"))
self.assertTrue(IP6Range("2001:db8:220:1::-2001:db8:220:1:ffff:ffff:ffff:ffff") in IP6Net("2001:db8:220:1::/64"))
self.assertTrue(IP6Range("2001:db8:220:1:248:1893:25c8:1946-2001:db8:220:1:248:1893:25c8:1946") in IP6("2001:db8:220:1:248:1893:25c8:1946"))
self.assertTrue(IP6("2001:db8:220:1:248:1893:25c8:1946") in IP6Range("2001:db8:220:1::-2001:db8:220:1:ffff:ffff:ffff:ffff"))
self.assertTrue(IP6("2001:db8:220:1:248:1893:25c8:1946") in IP6Net("2001:db8:220:1::/64"))
self.assertTrue(IP6("2001:db8:220:1:248:1893:25c8:1946") in IP6("2001:db8:220:1:248:1893:25c8:1946"))
def test4Iter(self):
self.assertEqual(
tuple(str(ip) for ip in IP4Net("192.0.2.64/30")),
("192.0.2.64", "192.0.2.65", "192.0.2.66", "192.0.2.67"))
self.assertEqual(
tuple(str(ip) for ip in IP4Range("192.0.2.64-192.0.2.67")),
("192.0.2.64", "192.0.2.65", "192.0.2.66", "192.0.2.67"))
self.assertEqual(
tuple(str(ip) for ip in IP4("192.0.2.65")),
("192.0.2.65",))
def test6Iter(self):
self.assertEqual(
tuple(str(ip) for ip in IP6Net("2001:db8:220:1:248:1893:25c8:1944/126")),
("2001:db8:220:1:248:1893:25c8:1944",
"2001:db8:220:1:248:1893:25c8:1945",
"2001:db8:220:1:248:1893:25c8:1946",
"2001:db8:220:1:248:1893:25c8:1947"))
self.assertEqual(
tuple(str(ip) for ip in IP6Range("2001:db8:220:1:248:1893:25c8:1944-2001:db8:220:1:248:1893:25c8:1947")),
("2001:db8:220:1:248:1893:25c8:1944",
"2001:db8:220:1:248:1893:25c8:1945",
"2001:db8:220:1:248:1893:25c8:1946",
"2001:db8:220:1:248:1893:25c8:1947"))
self.assertEqual(
tuple(str(ip) for ip in IP6("2001:db8:220:1:248:1893:25c8:1947")),
("2001:db8:220:1:248:1893:25c8:1947",))
def testGetItem(self):
for rng in (
IP4Range("192.0.2.64-192.0.2.67"),
IP4Net("192.0.2.64/30"),
IP4("192.0.2.65"),
IP6Range("2001:db8:220:1:248:1893:25c8:1944-2001:db8:220:1:248:1893:25c8:1947"),
IP6Net("2001:db8:220:1:248:1893:25c8:1944/126"),
IP6("2001:db8:220:1:248:1893:25c8:1947")):
for idx in (0, -1):
res = [str(rng[i]) for i in range(len(rng))][idx]
res2 = str(rng[idx])
self.assertEqual(res, res2)
def testGetSlice(self):
for rng in (
IP4Range("192.0.2.64-192.0.2.67"),
IP4Net("192.0.2.64/30"),
IP4("192.0.2.65"),
IP6Range("2001:db8:220:1:248:1893:25c8:1944-2001:db8:220:1:248:1893:25c8:1947"),
IP6Net("2001:db8:220:1:248:1893:25c8:1944/126"),
IP6("2001:db8:220:1:248:1893:25c8:1947")):
for idx in (slice(None, None, None), slice(-3, -1), slice(0, -1, 2)):
res = [str(rng[i]) for i in range(len(rng))][idx]
res2 = [str(ip) for ip in rng[idx]]
self.assertEqual(res, res2)
def testConvToIP(self):
self.assertEqual(IP4(IP4Range("192.0.2.64-192.0.2.64")), IP4("192.0.2.64"))
self.assertEqual(IP4(IP4Net("192.0.2.64/32")), IP4("192.0.2.64"))
with self.assertRaises(ValueError):
IP4(IP4Net("192.0.2.64/30"))
self.assertEqual(IP6(IP6Range("2001:db8:220:1:248:1893:25c8:1944-2001:db8:220:1:248:1893:25c8:1944")), IP6("2001:db8:220:1:248:1893:25c8:1944"))
self.assertEqual(IP6(IP6Net("2001:db8:220:1:248:1893:25c8:1944/128")), IP6("2001:db8:220:1:248:1893:25c8:1944"))
with self.assertRaises(ValueError):
IP6(IP6Net("2001:db8:220:1:248:1893:25c8:1944/126"))
def testConvToNet(self):
self.assertEqual(IP4Net(IP4Range("192.0.2.64-192.0.2.127")), IP4Net("192.0.2.64/26"))
self.assertEqual(IP4Net(IP4("192.0.2.64")), IP4Net("192.0.2.64/32"))
with self.assertRaises(ValueError):
IP4Net(IP4Range("192.0.2.64-192.0.2.120"))
self.assertEqual(IP4Net(IP4Range("192.0.2.64-192.0.2.127")), IP4Net("192.0.2.64/26"))
self.assertEqual(IP4Net(IP4("192.0.2.64")), IP4Net("192.0.2.64/32"))
with self.assertRaises(ValueError):
IP4Net(IP4Range("192.0.2.64-192.0.2.120"))
self.assertEqual(IP6Net(IP6Range("2001:db8:220:1:248:1893:25c8:1944-2001:db8:220:1:248:1893:25c8:1947")), IP6Net("2001:db8:220:1:248:1893:25c8:1944/126"))
self.assertEqual(IP6Net(IP6("2001:db8:220:1:248:1893:25c8:1947")), IP6Net("2001:db8:220:1:248:1893:25c8:1947/128"))
with self.assertRaises(ValueError):
IP6Net(IP6Range("2001:db8:220:1:248:1893:25c8:1944-2001:db8:220:1:248:1893:25c8:1948"))
def testFromStr(self):
fs = from_str("192.0.2.64")
obj = IP4("192.0.2.64")
self.assertEqual(fs, obj)
self.assertTrue(isinstance(fs, IP4))
fs = from_str("192.0.2.64-192.0.2.127")
obj = IP4Range("192.0.2.64-192.0.2.127")
self.assertEqual(fs, obj)
self.assertTrue(isinstance(fs, IP4Range))
fs = from_str("192.0.2.64/26")
obj = IP4Net("192.0.2.64/26")
self.assertEqual(fs, obj)
self.assertTrue(isinstance(fs, IP4Net))
fs = from_str("2001:db8:220:1:248:1893:25c8:1947")
obj = IP6("2001:db8:220:1:248:1893:25c8:1947")
self.assertEqual(fs, obj)
self.assertTrue(isinstance(fs, IP6))
fs = from_str("2001:db8:220:1:248:1893:25c8:1944-2001:db8:220:1:248:1893:25c8:1947")
obj = IP6Range("2001:db8:220:1:248:1893:25c8:1944-2001:db8:220:1:248:1893:25c8:1947")
self.assertEqual(fs, obj)
self.assertTrue(isinstance(fs, IP6Range))
fs = from_str("2001:db8:220:1:248:1893:25c8:1947/128")
obj = IP6Net("2001:db8:220:1:248:1893:25c8:1947/128")
self.assertEqual(fs, obj)
self.assertTrue(isinstance(fs, IP6Net))
def testFromStrInvalid(self):
with self.assertRaises(ValueError):
from_str("192.0.2.500")
with self.assertRaises(ValueError):
from_str(":::")
with self.assertRaises(ValueError):
from_str("asdf")
with self.assertRaises(ValueError):
from_str("-")
with self.assertRaises(ValueError):
from_str("/")
if __name__ == "__main__":
unittest.main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment