@@ -294,7 +294,7 @@ def _collapse_addresses_internal(addresses):
294294 last = None
295295 for net in sorted (subnets .values ()):
296296 if last is not None :
297- # Since they are sorted, last.network_address <= net.network_address
297+ # Since they are sorted, last.first_address <= net.first_address
298298 # is a given.
299299 if last .last_address >= net .last_address :
300300 continue
@@ -338,7 +338,7 @@ def collapse_addresses(addresses):
338338 try :
339339 ips .append (ip .ip )
340340 except AttributeError :
341- ips .append (ip .network_address )
341+ ips .append (ip .first_address )
342342 else :
343343 if nets and nets [- 1 ].version != ip .version :
344344 raise TypeError ("%s and %s are not of the same version" % (
@@ -676,7 +676,7 @@ def __repr__(self):
676676 return '%s(%r)' % (self .__class__ .__name__ , str (self ))
677677
678678 def __str__ (self ):
679- return '%s/%d' % (self .network_address , self .prefixlen )
679+ return '%s/%d' % (self .first_address , self .prefixlen )
680680
681681 def hosts (self ):
682682 """Generate Iterator over usable hosts in a network.
@@ -685,19 +685,19 @@ def hosts(self):
685685 or broadcast addresses.
686686
687687 """
688- network = int (self .network_address )
688+ network = int (self .first_address )
689689 last = int (self .last_address )
690690 for x in range (network + 1 , last ):
691691 yield self ._address_class (x )
692692
693693 def __iter__ (self ):
694- network = int (self .network_address )
694+ network = int (self .first_address )
695695 last = int (self .last_address )
696696 for x in range (network , last + 1 ):
697697 yield self ._address_class (x )
698698
699699 def __getitem__ (self , n ):
700- network = int (self .network_address )
700+ network = int (self .first_address )
701701 last = int (self .last_address )
702702 if n >= 0 :
703703 if network + n > last :
@@ -715,22 +715,22 @@ def __lt__(self, other):
715715 if self .version != other .version :
716716 raise TypeError ('%s and %s are not of the same version' % (
717717 self , other ))
718- if self .network_address != other .network_address :
719- return self .network_address < other .network_address
718+ if self .first_address != other .first_address :
719+ return self .first_address < other .first_address
720720 if self .netmask != other .netmask :
721721 return self .netmask < other .netmask
722722 return False
723723
724724 def __eq__ (self , other ):
725725 try :
726726 return (self .version == other .version and
727- self .network_address == other .network_address and
727+ self .first_address == other .first_address and
728728 int (self .netmask ) == int (other .netmask ))
729729 except AttributeError :
730730 return NotImplemented
731731
732732 def __hash__ (self ):
733- return hash (int (self .network_address ) ^ int (self .netmask ))
733+ return hash (int (self .first_address ) ^ int (self .netmask ))
734734
735735 def __contains__ (self , other ):
736736 # always false if one is v4 and the other is v6.
@@ -742,35 +742,44 @@ def __contains__(self, other):
742742 # dealing with another address
743743 else :
744744 # address
745- return other ._ip & self .netmask ._ip == self .network_address ._ip
745+ return other ._ip & self .netmask ._ip == self .first_address ._ip
746746
747747 def overlaps (self , other ):
748748 """Tell if self is partly contained in other."""
749- return self .network_address in other or (
749+ return self .first_address in other or (
750750 self .last_address in other or (
751- other .network_address in self or (
751+ other .first_address in self or (
752752 other .last_address in self )))
753753
754754 @functools .cached_property
755755 def hostmask (self ):
756756 return self ._address_class (int (self .netmask ) ^ self ._ALL_ONES )
757757
758+ @functools .cached_property
759+ def first_address (self ):
760+ return self ._address_class (int (self .network_address ))
761+
762+ @functools .cached_property
763+ def last_address (self ):
764+ return self ._address_class (int (self .network_address ) |
765+ int (self .hostmask ))
766+
758767 @property
759768 def with_prefixlen (self ):
760- return '%s/%d' % (self .network_address , self ._prefixlen )
769+ return '%s/%d' % (self .first_address , self ._prefixlen )
761770
762771 @property
763772 def with_netmask (self ):
764- return '%s/%s' % (self .network_address , self .netmask )
773+ return '%s/%s' % (self .first_address , self .netmask )
765774
766775 @property
767776 def with_hostmask (self ):
768- return '%s/%s' % (self .network_address , self .hostmask )
777+ return '%s/%s' % (self .first_address , self .hostmask )
769778
770779 @property
771780 def num_addresses (self ):
772781 """Number of hosts in the current subnet."""
773- return int (self .last_address ) - int (self .network_address ) + 1
782+ return int (self .last_address ) - int (self .first_address ) + 1
774783
775784 @property
776785 def _address_class (self ):
@@ -833,7 +842,7 @@ def address_exclude(self, other):
833842 return
834843
835844 # Make sure we're comparing the network of other.
836- other = other .__class__ ('%s/%s' % (other .network_address ,
845+ other = other .__class__ ('%s/%s' % (other .first_address ,
837846 other .prefixlen ))
838847
839848 s1 , s2 = self .subnets ()
@@ -896,11 +905,11 @@ def compare_networks(self, other):
896905 raise TypeError ('%s and %s are not of the same type' % (
897906 self , other ))
898907 # self.version == other.version below here:
899- if self .network_address < other .network_address :
908+ if self .first_address < other .first_address :
900909 return - 1
901- if self .network_address > other .network_address :
910+ if self .first_address > other .first_address :
902911 return 1
903- # self.network_address == other.network_address below here:
912+ # self.first_address == other.first_address below here:
904913 if self .netmask < other .netmask :
905914 return - 1
906915 if self .netmask > other .netmask :
@@ -915,7 +924,7 @@ def _get_networks_key(self):
915924 and list.sort().
916925
917926 """
918- return (self .version , self .network_address , self .netmask )
927+ return (self .version , self .first_address , self .netmask )
919928
920929 def subnets (self , prefixlen_diff = 1 , new_prefix = None ):
921930 """The subnets which join to make the current subnet.
@@ -963,7 +972,7 @@ def subnets(self, prefixlen_diff=1, new_prefix=None):
963972 'prefix length diff %d is invalid for netblock %s' % (
964973 new_prefixlen , self ))
965974
966- start = int (self .network_address )
975+ start = int (self .first_address )
967976 end = int (self .last_address ) + 1
968977 step = (int (self .hostmask ) + 1 ) >> prefixlen_diff
969978 for new_addr in range (start , end , step ):
@@ -1007,7 +1016,7 @@ def supernet(self, prefixlen_diff=1, new_prefix=None):
10071016 'current prefixlen is %d, cannot have a prefixlen_diff of %d' %
10081017 (self .prefixlen , prefixlen_diff ))
10091018 return self .__class__ ((
1010- int (self .network_address ) & (int (self .netmask ) << prefixlen_diff ),
1019+ int (self .first_address ) & (int (self .netmask ) << prefixlen_diff ),
10111020 new_prefixlen
10121021 ))
10131022
@@ -1020,7 +1029,7 @@ def is_multicast(self):
10201029 See RFC 2373 2.7 for details.
10211030
10221031 """
1023- return (self .network_address .is_multicast and
1032+ return (self .first_address .is_multicast and
10241033 self .last_address .is_multicast )
10251034
10261035 @staticmethod
@@ -1029,7 +1038,7 @@ def _is_subnet_of(a, b):
10291038 # Always false if one is v4 and the other is v6.
10301039 if a .version != b .version :
10311040 raise TypeError (f"{ a } and { b } are not of the same version" )
1032- return (b .network_address <= a .network_address and
1041+ return (b .first_address <= a .first_address and
10331042 b .last_address >= a .last_address )
10341043 except AttributeError :
10351044 raise TypeError (f"Unable to test subnet containment "
@@ -1052,7 +1061,7 @@ def is_reserved(self):
10521061 reserved IPv6 Network ranges.
10531062
10541063 """
1055- return (self .network_address .is_reserved and
1064+ return (self .first_address .is_reserved and
10561065 self .last_address .is_reserved )
10571066
10581067 @property
@@ -1063,7 +1072,7 @@ def is_link_local(self):
10631072 A boolean, True if the address is reserved per RFC 4291.
10641073
10651074 """
1066- return (self .network_address .is_link_local and
1075+ return (self .first_address .is_link_local and
10671076 self .last_address .is_link_local )
10681077
10691078 @property
@@ -1075,10 +1084,10 @@ def is_private(self):
10751084 iana-ipv4-special-registry or iana-ipv6-special-registry.
10761085
10771086 """
1078- return any (self .network_address in priv_network and
1087+ return any (self .first_address in priv_network and
10791088 self .last_address in priv_network
10801089 for priv_network in self ._constants ._private_networks ) and all (
1081- self .network_address not in network and
1090+ self .first_address not in network and
10821091 self .last_address not in network
10831092 for network in self ._constants ._private_networks_exceptions
10841093 )
@@ -1103,7 +1112,7 @@ def is_unspecified(self):
11031112 RFC 2373 2.5.2.
11041113
11051114 """
1106- return (self .network_address .is_unspecified and
1115+ return (self .first_address .is_unspecified and
11071116 self .last_address .is_unspecified )
11081117
11091118 @property
@@ -1115,7 +1124,7 @@ def is_loopback(self):
11151124 RFC 2373 2.5.3.
11161125
11171126 """
1118- return (self .network_address .is_loopback and
1127+ return (self .first_address .is_loopback and
11191128 self .last_address .is_loopback )
11201129
11211130
@@ -1452,7 +1461,7 @@ def __lt__(self, other):
14521461 return False
14531462
14541463 def __hash__ (self ):
1455- return hash ((self ._ip , self ._prefixlen , int (self .network .network_address )))
1464+ return hash ((self ._ip , self ._prefixlen , int (self .network .first_address )))
14561465
14571466 __reduce__ = _IPAddressBase .__reduce__
14581467
@@ -1481,7 +1490,7 @@ class IPv4Network(_BaseV4, _BaseNetwork):
14811490 """This class represents and manipulates 32-bit IPv4 network + addresses..
14821491
14831492 Attributes: [examples for IPv4Network('192.0.2.0/27')]
1484- .network_address : IPv4Address('192.0.2.0')
1493+ .first_address : IPv4Address('192.0.2.0')
14851494 .hostmask: IPv4Address('0.0.0.31')
14861495 .broadcast_address: IPv4Address('192.0.2.32')
14871496 .netmask: IPv4Address('255.255.255.224')
@@ -1528,14 +1537,14 @@ def __init__(self, address, strict=True):
15281537 """
15291538 addr , mask = self ._split_addr_prefix (address )
15301539
1531- self .network_address = IPv4Address (addr )
1540+ self .first_address = IPv4Address (addr )
15321541 self .netmask , self ._prefixlen = self ._make_netmask (mask )
1533- packed = int (self .network_address )
1542+ packed = int (self .first_address )
15341543 if packed & int (self .netmask ) != packed :
15351544 if strict :
15361545 raise ValueError ('%s has host bits set' % self )
15371546 else :
1538- self .network_address = IPv4Address (packed &
1547+ self .first_address = IPv4Address (packed &
15391548 int (self .netmask ))
15401549
15411550 if self ._prefixlen == (self .max_prefixlen - 1 ):
@@ -1553,19 +1562,17 @@ def is_global(self):
15531562 iana-ipv4-special-registry.
15541563
15551564 """
1556- return (not (self .network_address in IPv4Network ('100.64.0.0/10' ) and
1565+ return (not (self .first_address in IPv4Network ('100.64.0.0/10' ) and
15571566 self .broadcast_address in IPv4Network ('100.64.0.0/10' )) and
15581567 not self .is_private )
15591568
1560- @functools .cached_property
1561- def last_address (self ):
1562- return self ._address_class (int (self .network_address ) |
1563- int (self .hostmask ))
1564-
15651569 @functools .cached_property
15661570 def broadcast_address (self ):
15671571 return self .last_address
15681572
1573+ @functools .cached_property
1574+ def network_address (self ):
1575+ return self .first_address
15691576
15701577class _IPv4Constants :
15711578 _linklocal_network = IPv4Network ('169.254.0.0/16' )
@@ -1861,7 +1868,7 @@ def _explode_shorthand_ip_string(self):
18611868
18621869 """
18631870 if isinstance (self , IPv6Network ):
1864- ip_str = str (self .network_address )
1871+ ip_str = str (self .first_address )
18651872 elif isinstance (self , IPv6Interface ):
18661873 ip_str = str (self .ip )
18671874 else :
@@ -2238,7 +2245,7 @@ def __lt__(self, other):
22382245 return False
22392246
22402247 def __hash__ (self ):
2241- return hash ((self ._ip , self ._prefixlen , int (self .network .network_address )))
2248+ return hash ((self ._ip , self ._prefixlen , int (self .network .first_address )))
22422249
22432250 __reduce__ = _IPAddressBase .__reduce__
22442251
@@ -2275,7 +2282,7 @@ class IPv6Network(_BaseV6, _BaseNetwork):
22752282 """This class represents and manipulates 128-bit IPv6 networks.
22762283
22772284 Attributes: [examples for IPv6('2001:db8::1000/124')]
2278- .network_address : IPv6Address('2001:db8::1000')
2285+ .first_address : IPv6Address('2001:db8::1000')
22792286 .hostmask: IPv6Address('::f')
22802287 .last_address: IPv6Address('2001:db8::100f')
22812288 .netmask: IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0')
@@ -2319,14 +2326,14 @@ def __init__(self, address, strict=True):
23192326 """
23202327 addr , mask = self ._split_addr_prefix (address )
23212328
2322- self .network_address = IPv6Address (addr )
2329+ self .first_address = IPv6Address (addr )
23232330 self .netmask , self ._prefixlen = self ._make_netmask (mask )
2324- packed = int (self .network_address )
2331+ packed = int (self .first_address )
23252332 if packed & int (self .netmask ) != packed :
23262333 if strict :
23272334 raise ValueError ('%s has host bits set' % self )
23282335 else :
2329- self .network_address = IPv6Address (packed &
2336+ self .first_address = IPv6Address (packed &
23302337 int (self .netmask ))
23312338
23322339 if self ._prefixlen == (self .max_prefixlen - 1 ):
@@ -2341,7 +2348,7 @@ def hosts(self):
23412348 Subnet-Router anycast address.
23422349
23432350 """
2344- network = int (self .network_address )
2351+ network = int (self .first_address )
23452352 last = int (self .last_address )
23462353 for x in range (network + 1 , last + 1 ):
23472354 yield self ._address_class (x )
@@ -2358,21 +2365,25 @@ def is_site_local(self):
23582365 A boolean, True if the address is reserved per RFC 3513 2.5.6.
23592366
23602367 """
2361- return (self .network_address .is_site_local and
2368+ return (self .first_address .is_site_local and
23622369 self .last_address .is_site_local )
23632370
2364- @property
2365- def last_address (self ):
2366- """The last address in the network, the address with all the host bits set."""
2367- return self ._address_class (int (self .network_address ) |
2368- int (self .hostmask ))
2371+ @functools .cached_property
2372+ def subnet_router_anycast_address (self ):
2373+ return self .first_address
23692374
2370- @property
2375+ @functools .cached_property
2376+ @warnings .deprecated ("IPv6 has no network addresses, use first_address or subnet_router_anycast_address instead." )
2377+ def network_address (self ):
2378+ return self .first_address
2379+
2380+ @functools .cached_property
23712381 @warnings .deprecated ("IPv6 has no broadcast addresses, use last_address instead for the address with all the host bits set." )
23722382 def broadcast_address (self ):
23732383 return self .last_address
23742384
23752385
2386+
23762387class _IPv6Constants :
23772388
23782389 _linklocal_network = IPv6Network ('fe80::/10' )
0 commit comments