bpo-27860: use cached_property (GH-12832)
* cached_property is more efficient than hand crafted cache. * In IPv[46]Network, `self.network.prefixlen` is same to `self._prefixlen`.
This commit is contained in:
parent
3c5a858ec6
commit
2430d532e2
|
@ -597,15 +597,11 @@ class _BaseAddress(_IPAddressBase):
|
||||||
|
|
||||||
@functools.total_ordering
|
@functools.total_ordering
|
||||||
class _BaseNetwork(_IPAddressBase):
|
class _BaseNetwork(_IPAddressBase):
|
||||||
|
|
||||||
"""A generic IP network object.
|
"""A generic IP network object.
|
||||||
|
|
||||||
This IP class contains the version independent methods which are
|
This IP class contains the version independent methods which are
|
||||||
used by networks.
|
used by networks.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, address):
|
|
||||||
self._cache = {}
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s(%r)' % (self.__class__.__name__, str(self))
|
return '%s(%r)' % (self.__class__.__name__, str(self))
|
||||||
|
@ -687,22 +683,14 @@ class _BaseNetwork(_IPAddressBase):
|
||||||
other.network_address in self or (
|
other.network_address in self or (
|
||||||
other.broadcast_address in self)))
|
other.broadcast_address in self)))
|
||||||
|
|
||||||
@property
|
@functools.cached_property
|
||||||
def broadcast_address(self):
|
def broadcast_address(self):
|
||||||
x = self._cache.get('broadcast_address')
|
return self._address_class(int(self.network_address) |
|
||||||
if x is None:
|
int(self.hostmask))
|
||||||
x = self._address_class(int(self.network_address) |
|
|
||||||
int(self.hostmask))
|
|
||||||
self._cache['broadcast_address'] = x
|
|
||||||
return x
|
|
||||||
|
|
||||||
@property
|
@functools.cached_property
|
||||||
def hostmask(self):
|
def hostmask(self):
|
||||||
x = self._cache.get('hostmask')
|
return self._address_class(int(self.netmask) ^ self._ALL_ONES)
|
||||||
if x is None:
|
|
||||||
x = self._address_class(int(self.netmask) ^ self._ALL_ONES)
|
|
||||||
self._cache['hostmask'] = x
|
|
||||||
return x
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def with_prefixlen(self):
|
def with_prefixlen(self):
|
||||||
|
@ -1346,7 +1334,7 @@ class IPv4Interface(IPv4Address):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '%s/%d' % (self._string_from_ip_int(self._ip),
|
return '%s/%d' % (self._string_from_ip_int(self._ip),
|
||||||
self.network.prefixlen)
|
self._prefixlen)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
address_equal = IPv4Address.__eq__(self, other)
|
address_equal = IPv4Address.__eq__(self, other)
|
||||||
|
@ -1413,7 +1401,6 @@ class IPv4Network(_BaseV4, _BaseNetwork):
|
||||||
_address_class = IPv4Address
|
_address_class = IPv4Address
|
||||||
|
|
||||||
def __init__(self, address, strict=True):
|
def __init__(self, address, strict=True):
|
||||||
|
|
||||||
"""Instantiate a new IPv4 network object.
|
"""Instantiate a new IPv4 network object.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -1447,10 +1434,7 @@ class IPv4Network(_BaseV4, _BaseNetwork):
|
||||||
an IPv4 address.
|
an IPv4 address.
|
||||||
ValueError: If strict is True and a network address is not
|
ValueError: If strict is True and a network address is not
|
||||||
supplied.
|
supplied.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
_BaseNetwork.__init__(self, address)
|
|
||||||
|
|
||||||
# Constructing from a packed address or integer
|
# Constructing from a packed address or integer
|
||||||
if isinstance(address, (int, bytes)):
|
if isinstance(address, (int, bytes)):
|
||||||
addr = address
|
addr = address
|
||||||
|
@ -2020,7 +2004,7 @@ class IPv6Interface(IPv6Address):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '%s/%d' % (self._string_from_ip_int(self._ip),
|
return '%s/%d' % (self._string_from_ip_int(self._ip),
|
||||||
self.network.prefixlen)
|
self._prefixlen)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
address_equal = IPv6Address.__eq__(self, other)
|
address_equal = IPv6Address.__eq__(self, other)
|
||||||
|
@ -2125,10 +2109,7 @@ class IPv6Network(_BaseV6, _BaseNetwork):
|
||||||
an IPv6 address.
|
an IPv6 address.
|
||||||
ValueError: If strict was True and a network address was not
|
ValueError: If strict was True and a network address was not
|
||||||
supplied.
|
supplied.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
_BaseNetwork.__init__(self, address)
|
|
||||||
|
|
||||||
# Constructing from a packed address or integer
|
# Constructing from a packed address or integer
|
||||||
if isinstance(address, (int, bytes)):
|
if isinstance(address, (int, bytes)):
|
||||||
addr = address
|
addr = address
|
||||||
|
|
|
@ -961,20 +961,6 @@ class IpaddrUnitTest(unittest.TestCase):
|
||||||
self.assertEqual(128, ipaddress._count_righthand_zero_bits(0, 128))
|
self.assertEqual(128, ipaddress._count_righthand_zero_bits(0, 128))
|
||||||
self.assertEqual("IPv4Network('1.2.3.0/24')", repr(self.ipv4_network))
|
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):
|
def testGetNetwork(self):
|
||||||
self.assertEqual(int(self.ipv4_network.network_address), 16909056)
|
self.assertEqual(int(self.ipv4_network.network_address), 16909056)
|
||||||
self.assertEqual(str(self.ipv4_network.network_address), '1.2.3.0')
|
self.assertEqual(str(self.ipv4_network.network_address), '1.2.3.0')
|
||||||
|
@ -1986,25 +1972,22 @@ class IpaddrUnitTest(unittest.TestCase):
|
||||||
|
|
||||||
def testNetworkElementCaching(self):
|
def testNetworkElementCaching(self):
|
||||||
# V4 - make sure we're empty
|
# V4 - make sure we're empty
|
||||||
self.assertNotIn('network_address', self.ipv4_network._cache)
|
self.assertNotIn('broadcast_address', self.ipv4_network.__dict__)
|
||||||
self.assertNotIn('broadcast_address', self.ipv4_network._cache)
|
self.assertNotIn('hostmask', self.ipv4_network.__dict__)
|
||||||
self.assertNotIn('hostmask', self.ipv4_network._cache)
|
|
||||||
|
|
||||||
# V4 - populate and test
|
# V4 - populate and test
|
||||||
self.assertEqual(self.ipv4_network.network_address,
|
|
||||||
ipaddress.IPv4Address('1.2.3.0'))
|
|
||||||
self.assertEqual(self.ipv4_network.broadcast_address,
|
self.assertEqual(self.ipv4_network.broadcast_address,
|
||||||
ipaddress.IPv4Address('1.2.3.255'))
|
ipaddress.IPv4Address('1.2.3.255'))
|
||||||
self.assertEqual(self.ipv4_network.hostmask,
|
self.assertEqual(self.ipv4_network.hostmask,
|
||||||
ipaddress.IPv4Address('0.0.0.255'))
|
ipaddress.IPv4Address('0.0.0.255'))
|
||||||
|
|
||||||
# V4 - check we're cached
|
# V4 - check we're cached
|
||||||
self.assertIn('broadcast_address', self.ipv4_network._cache)
|
self.assertIn('broadcast_address', self.ipv4_network.__dict__)
|
||||||
self.assertIn('hostmask', self.ipv4_network._cache)
|
self.assertIn('hostmask', self.ipv4_network.__dict__)
|
||||||
|
|
||||||
# V6 - make sure we're empty
|
# V6 - make sure we're empty
|
||||||
self.assertNotIn('broadcast_address', self.ipv6_network._cache)
|
self.assertNotIn('broadcast_address', self.ipv6_network.__dict__)
|
||||||
self.assertNotIn('hostmask', self.ipv6_network._cache)
|
self.assertNotIn('hostmask', self.ipv6_network.__dict__)
|
||||||
|
|
||||||
# V6 - populate and test
|
# V6 - populate and test
|
||||||
self.assertEqual(self.ipv6_network.network_address,
|
self.assertEqual(self.ipv6_network.network_address,
|
||||||
|
@ -2024,10 +2007,10 @@ class IpaddrUnitTest(unittest.TestCase):
|
||||||
ipaddress.IPv6Address('::ffff:ffff:ffff:ffff'))
|
ipaddress.IPv6Address('::ffff:ffff:ffff:ffff'))
|
||||||
|
|
||||||
# V6 - check we're cached
|
# V6 - check we're cached
|
||||||
self.assertIn('broadcast_address', self.ipv6_network._cache)
|
self.assertIn('broadcast_address', self.ipv6_network.__dict__)
|
||||||
self.assertIn('hostmask', self.ipv6_network._cache)
|
self.assertIn('hostmask', self.ipv6_network.__dict__)
|
||||||
self.assertIn('broadcast_address', self.ipv6_interface.network._cache)
|
self.assertIn('broadcast_address', self.ipv6_interface.network.__dict__)
|
||||||
self.assertIn('hostmask', self.ipv6_interface.network._cache)
|
self.assertIn('hostmask', self.ipv6_interface.network.__dict__)
|
||||||
|
|
||||||
def testTeredo(self):
|
def testTeredo(self):
|
||||||
# stolen from wikipedia
|
# stolen from wikipedia
|
||||||
|
|
Loading…
Reference in New Issue