Skip to content

Commit 2430d53

Browse files
authored
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`.
1 parent 3c5a858 commit 2430d53

File tree

2 files changed

+17
-53
lines changed

2 files changed

+17
-53
lines changed

Lib/ipaddress.py

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -597,15 +597,11 @@ def __reduce__(self):
597597

598598
@functools.total_ordering
599599
class _BaseNetwork(_IPAddressBase):
600-
601600
"""A generic IP network object.
602601
603602
This IP class contains the version independent methods which are
604603
used by networks.
605-
606604
"""
607-
def __init__(self, address):
608-
self._cache = {}
609605

610606
def __repr__(self):
611607
return '%s(%r)' % (self.__class__.__name__, str(self))
@@ -687,22 +683,14 @@ def overlaps(self, other):
687683
other.network_address in self or (
688684
other.broadcast_address in self)))
689685

690-
@property
686+
@functools.cached_property
691687
def broadcast_address(self):
692-
x = self._cache.get('broadcast_address')
693-
if x is None:
694-
x = self._address_class(int(self.network_address) |
695-
int(self.hostmask))
696-
self._cache['broadcast_address'] = x
697-
return x
688+
return self._address_class(int(self.network_address) |
689+
int(self.hostmask))
698690

699-
@property
691+
@functools.cached_property
700692
def hostmask(self):
701-
x = self._cache.get('hostmask')
702-
if x is None:
703-
x = self._address_class(int(self.netmask) ^ self._ALL_ONES)
704-
self._cache['hostmask'] = x
705-
return x
693+
return self._address_class(int(self.netmask) ^ self._ALL_ONES)
706694

707695
@property
708696
def with_prefixlen(self):
@@ -1346,7 +1334,7 @@ def __init__(self, address):
13461334

13471335
def __str__(self):
13481336
return '%s/%d' % (self._string_from_ip_int(self._ip),
1349-
self.network.prefixlen)
1337+
self._prefixlen)
13501338

13511339
def __eq__(self, other):
13521340
address_equal = IPv4Address.__eq__(self, other)
@@ -1413,7 +1401,6 @@ class IPv4Network(_BaseV4, _BaseNetwork):
14131401
_address_class = IPv4Address
14141402

14151403
def __init__(self, address, strict=True):
1416-
14171404
"""Instantiate a new IPv4 network object.
14181405
14191406
Args:
@@ -1447,10 +1434,7 @@ def __init__(self, address, strict=True):
14471434
an IPv4 address.
14481435
ValueError: If strict is True and a network address is not
14491436
supplied.
1450-
14511437
"""
1452-
_BaseNetwork.__init__(self, address)
1453-
14541438
# Constructing from a packed address or integer
14551439
if isinstance(address, (int, bytes)):
14561440
addr = address
@@ -2020,7 +2004,7 @@ def __init__(self, address):
20202004

20212005
def __str__(self):
20222006
return '%s/%d' % (self._string_from_ip_int(self._ip),
2023-
self.network.prefixlen)
2007+
self._prefixlen)
20242008

20252009
def __eq__(self, other):
20262010
address_equal = IPv6Address.__eq__(self, other)
@@ -2125,10 +2109,7 @@ def __init__(self, address, strict=True):
21252109
an IPv6 address.
21262110
ValueError: If strict was True and a network address was not
21272111
supplied.
2128-
21292112
"""
2130-
_BaseNetwork.__init__(self, address)
2131-
21322113
# Constructing from a packed address or integer
21332114
if isinstance(address, (int, bytes)):
21342115
addr = address

Lib/test/test_ipaddress.py

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -961,20 +961,6 @@ def testInternals(self):
961961
self.assertEqual(128, ipaddress._count_righthand_zero_bits(0, 128))
962962
self.assertEqual("IPv4Network('1.2.3.0/24')", repr(self.ipv4_network))
963963

964-
def testMissingNetworkVersion(self):
965-
class Broken(ipaddress._BaseNetwork):
966-
pass
967-
broken = Broken('127.0.0.1')
968-
with self.assertRaisesRegex(NotImplementedError, "Broken.*version"):
969-
broken.version
970-
971-
def testMissingAddressClass(self):
972-
class Broken(ipaddress._BaseNetwork):
973-
pass
974-
broken = Broken('127.0.0.1')
975-
with self.assertRaisesRegex(NotImplementedError, "Broken.*address"):
976-
broken._address_class
977-
978964
def testGetNetwork(self):
979965
self.assertEqual(int(self.ipv4_network.network_address), 16909056)
980966
self.assertEqual(str(self.ipv4_network.network_address), '1.2.3.0')
@@ -1986,25 +1972,22 @@ def testWithStar(self):
19861972

19871973
def testNetworkElementCaching(self):
19881974
# V4 - make sure we're empty
1989-
self.assertNotIn('network_address', self.ipv4_network._cache)
1990-
self.assertNotIn('broadcast_address', self.ipv4_network._cache)
1991-
self.assertNotIn('hostmask', self.ipv4_network._cache)
1975+
self.assertNotIn('broadcast_address', self.ipv4_network.__dict__)
1976+
self.assertNotIn('hostmask', self.ipv4_network.__dict__)
19921977

19931978
# V4 - populate and test
1994-
self.assertEqual(self.ipv4_network.network_address,
1995-
ipaddress.IPv4Address('1.2.3.0'))
19961979
self.assertEqual(self.ipv4_network.broadcast_address,
19971980
ipaddress.IPv4Address('1.2.3.255'))
19981981
self.assertEqual(self.ipv4_network.hostmask,
19991982
ipaddress.IPv4Address('0.0.0.255'))
20001983

20011984
# V4 - check we're cached
2002-
self.assertIn('broadcast_address', self.ipv4_network._cache)
2003-
self.assertIn('hostmask', self.ipv4_network._cache)
1985+
self.assertIn('broadcast_address', self.ipv4_network.__dict__)
1986+
self.assertIn('hostmask', self.ipv4_network.__dict__)
20041987

20051988
# V6 - make sure we're empty
2006-
self.assertNotIn('broadcast_address', self.ipv6_network._cache)
2007-
self.assertNotIn('hostmask', self.ipv6_network._cache)
1989+
self.assertNotIn('broadcast_address', self.ipv6_network.__dict__)
1990+
self.assertNotIn('hostmask', self.ipv6_network.__dict__)
20081991

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

20262009
# V6 - check we're cached
2027-
self.assertIn('broadcast_address', self.ipv6_network._cache)
2028-
self.assertIn('hostmask', self.ipv6_network._cache)
2029-
self.assertIn('broadcast_address', self.ipv6_interface.network._cache)
2030-
self.assertIn('hostmask', self.ipv6_interface.network._cache)
2010+
self.assertIn('broadcast_address', self.ipv6_network.__dict__)
2011+
self.assertIn('hostmask', self.ipv6_network.__dict__)
2012+
self.assertIn('broadcast_address', self.ipv6_interface.network.__dict__)
2013+
self.assertIn('hostmask', self.ipv6_interface.network.__dict__)
20312014

20322015
def testTeredo(self):
20332016
# stolen from wikipedia

0 commit comments

Comments
 (0)