Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 7 additions & 26 deletions Lib/ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -597,15 +597,11 @@ def __reduce__(self):

@functools.total_ordering
class _BaseNetwork(_IPAddressBase):

"""A generic IP network object.

This IP class contains the version independent methods which are
used by networks.

"""
def __init__(self, address):
self._cache = {}

def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, str(self))
Expand Down Expand Up @@ -687,22 +683,14 @@ def overlaps(self, other):
other.network_address in self or (
other.broadcast_address in self)))

@property
@functools.cached_property
def broadcast_address(self):
x = self._cache.get('broadcast_address')
if x is None:
x = self._address_class(int(self.network_address) |
int(self.hostmask))
self._cache['broadcast_address'] = x
return x
return self._address_class(int(self.network_address) |
int(self.hostmask))

@property
@functools.cached_property
def hostmask(self):
x = self._cache.get('hostmask')
if x is None:
x = self._address_class(int(self.netmask) ^ self._ALL_ONES)
self._cache['hostmask'] = x
return x
return self._address_class(int(self.netmask) ^ self._ALL_ONES)

@property
def with_prefixlen(self):
Expand Down Expand Up @@ -1346,7 +1334,7 @@ def __init__(self, address):

def __str__(self):
return '%s/%d' % (self._string_from_ip_int(self._ip),
self.network.prefixlen)
self._prefixlen)

def __eq__(self, other):
address_equal = IPv4Address.__eq__(self, other)
Expand Down Expand Up @@ -1413,7 +1401,6 @@ class IPv4Network(_BaseV4, _BaseNetwork):
_address_class = IPv4Address

def __init__(self, address, strict=True):

"""Instantiate a new IPv4 network object.

Args:
Expand Down Expand Up @@ -1447,10 +1434,7 @@ def __init__(self, address, strict=True):
an IPv4 address.
ValueError: If strict is True and a network address is not
supplied.

"""
_BaseNetwork.__init__(self, address)

# Constructing from a packed address or integer
if isinstance(address, (int, bytes)):
addr = address
Expand Down Expand Up @@ -2020,7 +2004,7 @@ def __init__(self, address):

def __str__(self):
return '%s/%d' % (self._string_from_ip_int(self._ip),
self.network.prefixlen)
self._prefixlen)

def __eq__(self, other):
address_equal = IPv6Address.__eq__(self, other)
Expand Down Expand Up @@ -2125,10 +2109,7 @@ def __init__(self, address, strict=True):
an IPv6 address.
ValueError: If strict was True and a network address was not
supplied.

"""
_BaseNetwork.__init__(self, address)

# Constructing from a packed address or integer
if isinstance(address, (int, bytes)):
addr = address
Expand Down
37 changes: 10 additions & 27 deletions Lib/test/test_ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -961,20 +961,6 @@ def testInternals(self):
self.assertEqual(128, ipaddress._count_righthand_zero_bits(0, 128))
self.assertEqual("IPv4Network('1.2.3.0/24')", repr(self.ipv4_network))

def testMissingNetworkVersion(self):
class Broken(ipaddress._BaseNetwork):
pass
broken = Broken('127.0.0.1')
with self.assertRaisesRegex(NotImplementedError, "Broken.*version"):
broken.version

def testMissingAddressClass(self):
class Broken(ipaddress._BaseNetwork):
pass
broken = Broken('127.0.0.1')
with self.assertRaisesRegex(NotImplementedError, "Broken.*address"):
broken._address_class

def testGetNetwork(self):
self.assertEqual(int(self.ipv4_network.network_address), 16909056)
self.assertEqual(str(self.ipv4_network.network_address), '1.2.3.0')
Expand Down Expand Up @@ -1986,25 +1972,22 @@ def testWithStar(self):

def testNetworkElementCaching(self):
# V4 - make sure we're empty
self.assertNotIn('network_address', self.ipv4_network._cache)
self.assertNotIn('broadcast_address', self.ipv4_network._cache)
self.assertNotIn('hostmask', self.ipv4_network._cache)
self.assertNotIn('broadcast_address', self.ipv4_network.__dict__)
self.assertNotIn('hostmask', self.ipv4_network.__dict__)

# V4 - populate and test
self.assertEqual(self.ipv4_network.network_address,
ipaddress.IPv4Address('1.2.3.0'))
self.assertEqual(self.ipv4_network.broadcast_address,
ipaddress.IPv4Address('1.2.3.255'))
self.assertEqual(self.ipv4_network.hostmask,
ipaddress.IPv4Address('0.0.0.255'))

# V4 - check we're cached
self.assertIn('broadcast_address', self.ipv4_network._cache)
self.assertIn('hostmask', self.ipv4_network._cache)
self.assertIn('broadcast_address', self.ipv4_network.__dict__)
self.assertIn('hostmask', self.ipv4_network.__dict__)

# V6 - make sure we're empty
self.assertNotIn('broadcast_address', self.ipv6_network._cache)
self.assertNotIn('hostmask', self.ipv6_network._cache)
self.assertNotIn('broadcast_address', self.ipv6_network.__dict__)
self.assertNotIn('hostmask', self.ipv6_network.__dict__)

# V6 - populate and test
self.assertEqual(self.ipv6_network.network_address,
Expand All @@ -2024,10 +2007,10 @@ def testNetworkElementCaching(self):
ipaddress.IPv6Address('::ffff:ffff:ffff:ffff'))

# V6 - check we're cached
self.assertIn('broadcast_address', self.ipv6_network._cache)
self.assertIn('hostmask', self.ipv6_network._cache)
self.assertIn('broadcast_address', self.ipv6_interface.network._cache)
self.assertIn('hostmask', self.ipv6_interface.network._cache)
self.assertIn('broadcast_address', self.ipv6_network.__dict__)
self.assertIn('hostmask', self.ipv6_network.__dict__)
self.assertIn('broadcast_address', self.ipv6_interface.network.__dict__)
self.assertIn('hostmask', self.ipv6_interface.network.__dict__)

def testTeredo(self):
# stolen from wikipedia
Expand Down