@@ -499,38 +499,30 @@ def _prefix_from_prefix_string(cls, prefixlen_str):
499
499
return prefixlen
500
500
501
501
@classmethod
502
- def _prefix_from_ip_string (cls , ip_str ):
503
- """Turn a netmask/hostmask string into a prefix length
502
+ def _split_addr_prefix (cls , arg ):
503
+ """Make a (address, prefix) tuple from the given argument.
504
504
505
505
Args:
506
- ip_str: The netmask/hostmask to be converted
506
+ arg: A string, bytes object or a tuple representing an address and
507
+ a network prefix.
507
508
508
509
Returns:
509
- An integer, the prefix length.
510
-
511
- Raises:
512
- NetmaskValueError: If the input is not a valid netmask/hostmask
510
+ A (address, netmask/prefix) tuple.
513
511
"""
514
- # Parse the netmask/hostmask like an IP address.
515
- try :
516
- ip_int = cls ._ip_int_from_string (ip_str )
517
- except AddressValueError :
518
- cls ._report_invalid_netmask (ip_str )
519
-
520
- # Try matching a netmask (this would be /1*0*/ as a bitwise regexp).
521
- # Note that the two ambiguous cases (all-ones and all-zeroes) are
522
- # treated as netmasks.
523
- try :
524
- return cls ._prefix_from_ip_int (ip_int )
525
- except ValueError :
526
- pass
512
+ if isinstance (arg , (int , bytes )):
513
+ addr = arg
514
+ prefix = cls ._max_prefixlen
515
+ elif isinstance (arg , tuple ) and len (arg ) == 2 :
516
+ addr , prefix = arg
517
+ else :
518
+ arg = _split_optional_netmask (arg )
519
+ addr = arg [0 ]
520
+ if len (arg ) == 2 :
521
+ prefix = arg [1 ]
522
+ else :
523
+ prefix = cls ._max_prefixlen
527
524
528
- # Invert the bits, and try matching a /0+1+/ hostmask instead.
529
- ip_int ^= cls ._ALL_ONES
530
- try :
531
- return cls ._prefix_from_ip_int (ip_int )
532
- except ValueError :
533
- cls ._report_invalid_netmask (ip_str )
525
+ return addr , prefix
534
526
535
527
def __reduce__ (self ):
536
528
return self .__class__ , (str (self ),)
@@ -1080,20 +1072,41 @@ def _make_netmask(cls, arg):
1080
1072
Argument can be:
1081
1073
- an integer (the prefix length)
1082
1074
- a string representing the prefix length (e.g. "24")
1083
- - a string representing the prefix netmask (e.g. "255.255.255.0")
1075
+ - a string representing the netmask or hostmask (e.g. "255.255.255.0")
1076
+ - a bytes object representing a netmask or hostmask
1077
+ (e.g. b"\xff \xff \xff \x00 ")
1078
+ - an IPv4Address object representing the netmask or hostmask
1084
1079
"""
1085
1080
if arg not in cls ._netmask_cache :
1086
1081
if isinstance (arg , int ):
1087
1082
prefixlen = arg
1083
+ netmask = IPv4Address (cls ._ip_int_from_prefix (prefixlen ))
1088
1084
else :
1089
1085
try :
1086
+ if isinstance (arg , IPv4Address ):
1087
+ netmask = arg
1088
+ else :
1089
+ netmask = IPv4Address (arg )
1090
+ except AddressValueError :
1090
1091
# Check for a netmask in prefix length form
1091
1092
prefixlen = cls ._prefix_from_prefix_string (arg )
1092
- except NetmaskValueError :
1093
- # Check for a netmask or hostmask in dotted-quad form.
1094
- # This may raise NetmaskValueError.
1095
- prefixlen = cls ._prefix_from_ip_string (arg )
1096
- netmask = IPv4Address (cls ._ip_int_from_prefix (prefixlen ))
1093
+ netmask = IPv4Address (cls ._ip_int_from_prefix (prefixlen ))
1094
+ else :
1095
+ try :
1096
+ # Try matching a netmask (this would be /1*0*/ as a
1097
+ # bitwise regexp). Note that the two ambiguous cases
1098
+ # (all-ones and all-zeroes) are treated as netmasks.
1099
+ prefixlen = cls ._prefix_from_ip_int (netmask ._ip )
1100
+ except ValueError :
1101
+ # Invert the bits, and try matching a /0+1+/ hostmask
1102
+ # instead.
1103
+ ip_int = netmask ._ip ^ cls ._ALL_ONES
1104
+ try :
1105
+ prefixlen = cls ._prefix_from_ip_int (ip_int )
1106
+ except ValueError :
1107
+ cls ._report_invalid_netmask (arg )
1108
+ else :
1109
+ netmask = IPv4Address (ip_int )
1097
1110
cls ._netmask_cache [arg ] = netmask , prefixlen
1098
1111
return cls ._netmask_cache [arg ]
1099
1112
@@ -1167,6 +1180,24 @@ def _string_from_ip_int(cls, ip_int):
1167
1180
"""
1168
1181
return '.' .join (map (str , ip_int .to_bytes (4 , 'big' )))
1169
1182
1183
+ @classmethod
1184
+ def _get_addr_prefix_tuple (cls , arg ):
1185
+ """Make a (address, (netmask, prefix)) tuple from the given argument.
1186
+
1187
+ Args:
1188
+ arg: A string, bytes object or a tuple representing an address and
1189
+ a network prefix.
1190
+
1191
+ Returns:
1192
+ A (address, (netmask, prefix)) tuple.
1193
+ """
1194
+ addr , prefix = cls ._split_addr_prefix (arg )
1195
+ if isinstance (addr , IPv4Address ):
1196
+ addr = IPv4Address (addr ._ip )
1197
+ else :
1198
+ addr = IPv4Address (addr )
1199
+ return (addr , cls ._make_netmask (prefix ))
1200
+
1170
1201
def _reverse_pointer (self ):
1171
1202
"""Return the reverse DNS pointer name for the IPv4 address.
1172
1203
@@ -1305,30 +1336,11 @@ def is_link_local(self):
1305
1336
class IPv4Interface (IPv4Address ):
1306
1337
1307
1338
def __init__ (self , address ):
1308
- if isinstance (address , (bytes , int )):
1309
- IPv4Address .__init__ (self , address )
1310
- self .network = IPv4Network (self ._ip )
1311
- self ._prefixlen = self ._max_prefixlen
1312
- return
1313
-
1314
- if isinstance (address , tuple ):
1315
- IPv4Address .__init__ (self , address [0 ])
1316
- if len (address ) > 1 :
1317
- self ._prefixlen = int (address [1 ])
1318
- else :
1319
- self ._prefixlen = self ._max_prefixlen
1320
-
1321
- self .network = IPv4Network (address , strict = False )
1322
- self .netmask = self .network .netmask
1323
- self .hostmask = self .network .hostmask
1324
- return
1325
-
1326
- addr = _split_optional_netmask (address )
1327
- IPv4Address .__init__ (self , addr [0 ])
1328
-
1329
- self .network = IPv4Network (address , strict = False )
1330
- self ._prefixlen = self .network ._prefixlen
1339
+ addr_prefix = self ._get_addr_prefix_tuple (address )
1340
+ addr , (self .netmask , self ._prefixlen ) = addr_prefix
1341
+ super ().__init__ (addr ._ip )
1331
1342
1343
+ self .network = IPv4Network ((addr , self ._prefixlen ), strict = False )
1332
1344
self .netmask = self .network .netmask
1333
1345
self .hostmask = self .network .hostmask
1334
1346
@@ -1435,30 +1447,15 @@ def __init__(self, address, strict=True):
1435
1447
ValueError: If strict is True and a network address is not
1436
1448
supplied.
1437
1449
"""
1438
- # Constructing from a packed address or integer
1439
- if isinstance (address , (int , bytes )):
1440
- addr = address
1441
- mask = self ._max_prefixlen
1442
- # Constructing from a tuple (addr, [mask])
1443
- elif isinstance (address , tuple ):
1444
- addr = address [0 ]
1445
- mask = address [1 ] if len (address ) > 1 else self ._max_prefixlen
1446
- # Assume input argument to be string or any object representation
1447
- # which converts into a formatted IP prefix string.
1448
- else :
1449
- args = _split_optional_netmask (address )
1450
- addr = self ._ip_int_from_string (args [0 ])
1451
- mask = args [1 ] if len (args ) == 2 else self ._max_prefixlen
1450
+ addr_prefix = self ._get_addr_prefix_tuple (address )
1451
+ self .network_address , (self .netmask , self ._prefixlen ) = addr_prefix
1452
1452
1453
- self .network_address = IPv4Address (addr )
1454
- self .netmask , self ._prefixlen = self ._make_netmask (mask )
1455
1453
packed = int (self .network_address )
1456
1454
if packed & int (self .netmask ) != packed :
1457
1455
if strict :
1458
1456
raise ValueError ('%s has host bits set' % self )
1459
1457
else :
1460
- self .network_address = IPv4Address (packed &
1461
- int (self .netmask ))
1458
+ self .network_address = IPv4Address (packed & int (self .netmask ))
1462
1459
1463
1460
if self ._prefixlen == (self ._max_prefixlen - 1 ):
1464
1461
self .hosts = self .__iter__
@@ -1539,14 +1536,26 @@ def _make_netmask(cls, arg):
1539
1536
Argument can be:
1540
1537
- an integer (the prefix length)
1541
1538
- a string representing the prefix length (e.g. "24")
1542
- - a string representing the prefix netmask (e.g. "255.255.255.0")
1539
+ - a bytes object representing the netmask (e.g. b'\xff '*16)
1540
+ - an IPv6Address object representing the netmask
1543
1541
"""
1544
1542
if arg not in cls ._netmask_cache :
1545
1543
if isinstance (arg , int ):
1546
1544
prefixlen = arg
1545
+ netmask = IPv6Address (cls ._ip_int_from_prefix (prefixlen ))
1547
1546
else :
1548
- prefixlen = cls ._prefix_from_prefix_string (arg )
1549
- netmask = IPv6Address (cls ._ip_int_from_prefix (prefixlen ))
1547
+ if isinstance (arg , (bytes , IPv6Address )):
1548
+ netmask = arg
1549
+ if isinstance (netmask , bytes ):
1550
+ netmask = IPv6Address (netmask )
1551
+ try :
1552
+ prefixlen = cls ._prefix_from_ip_int (netmask ._ip )
1553
+ except ValueError :
1554
+ cls ._report_invalid_netmask (arg )
1555
+ else :
1556
+ # Check for a netmask in prefix length form
1557
+ prefixlen = cls ._prefix_from_prefix_string (arg )
1558
+ netmask = IPv6Address (cls ._ip_int_from_prefix (prefixlen ))
1550
1559
cls ._netmask_cache [arg ] = netmask , prefixlen
1551
1560
return cls ._netmask_cache [arg ]
1552
1561
@@ -1778,6 +1787,24 @@ def _explode_shorthand_ip_string(self):
1778
1787
return '%s/%d' % (':' .join (parts ), self ._prefixlen )
1779
1788
return ':' .join (parts )
1780
1789
1790
+ @classmethod
1791
+ def _get_addr_prefix_tuple (cls , arg ):
1792
+ """Make a (address, (netmask, prefix)) tuple from the given argument.
1793
+
1794
+ Args:
1795
+ arg: A string, bytes object or a tuple representing an address and
1796
+ a network prefix.
1797
+
1798
+ Returns:
1799
+ A (address, (netmask, prefix)) tuple.
1800
+ """
1801
+ addr , prefix = cls ._split_addr_prefix (arg )
1802
+ if isinstance (addr , IPv6Address ):
1803
+ addr = IPv6Address (addr ._ip )
1804
+ else :
1805
+ addr = IPv6Address (addr )
1806
+ return (addr , cls ._make_netmask (prefix ))
1807
+
1781
1808
def _reverse_pointer (self ):
1782
1809
"""Return the reverse DNS pointer name for the IPv6 address.
1783
1810
@@ -1979,27 +2006,12 @@ def sixtofour(self):
1979
2006
class IPv6Interface (IPv6Address ):
1980
2007
1981
2008
def __init__ (self , address ):
1982
- if isinstance (address , (bytes , int )):
1983
- IPv6Address .__init__ (self , address )
1984
- self .network = IPv6Network (self ._ip )
1985
- self ._prefixlen = self ._max_prefixlen
1986
- return
1987
- if isinstance (address , tuple ):
1988
- IPv6Address .__init__ (self , address [0 ])
1989
- if len (address ) > 1 :
1990
- self ._prefixlen = int (address [1 ])
1991
- else :
1992
- self ._prefixlen = self ._max_prefixlen
1993
- self .network = IPv6Network (address , strict = False )
1994
- self .netmask = self .network .netmask
1995
- self .hostmask = self .network .hostmask
1996
- return
2009
+ addr_prefix = self ._get_addr_prefix_tuple (address )
2010
+ addr , (self .netmask , self ._prefixlen ) = addr_prefix
2011
+ super ().__init__ (addr ._ip )
1997
2012
1998
- addr = _split_optional_netmask (address )
1999
- IPv6Address .__init__ (self , addr [0 ])
2000
- self .network = IPv6Network (address , strict = False )
2013
+ self .network = IPv6Network ((addr , self ._prefixlen ), strict = False )
2001
2014
self .netmask = self .network .netmask
2002
- self ._prefixlen = self .network ._prefixlen
2003
2015
self .hostmask = self .network .hostmask
2004
2016
2005
2017
def __str__ (self ):
@@ -2110,30 +2122,15 @@ def __init__(self, address, strict=True):
2110
2122
ValueError: If strict was True and a network address was not
2111
2123
supplied.
2112
2124
"""
2113
- # Constructing from a packed address or integer
2114
- if isinstance (address , (int , bytes )):
2115
- addr = address
2116
- mask = self ._max_prefixlen
2117
- # Constructing from a tuple (addr, [mask])
2118
- elif isinstance (address , tuple ):
2119
- addr = address [0 ]
2120
- mask = address [1 ] if len (address ) > 1 else self ._max_prefixlen
2121
- # Assume input argument to be string or any object representation
2122
- # which converts into a formatted IP prefix string.
2123
- else :
2124
- args = _split_optional_netmask (address )
2125
- addr = self ._ip_int_from_string (args [0 ])
2126
- mask = args [1 ] if len (args ) == 2 else self ._max_prefixlen
2125
+ addr_prefix = self ._get_addr_prefix_tuple (address )
2126
+ self .network_address , (self .netmask , self ._prefixlen ) = addr_prefix
2127
2127
2128
- self .network_address = IPv6Address (addr )
2129
- self .netmask , self ._prefixlen = self ._make_netmask (mask )
2130
2128
packed = int (self .network_address )
2131
2129
if packed & int (self .netmask ) != packed :
2132
2130
if strict :
2133
2131
raise ValueError ('%s has host bits set' % self )
2134
2132
else :
2135
- self .network_address = IPv6Address (packed &
2136
- int (self .netmask ))
2133
+ self .network_address = IPv6Address (packed & int (self .netmask ))
2137
2134
2138
2135
if self ._prefixlen == (self ._max_prefixlen - 1 ):
2139
2136
self .hosts = self .__iter__
0 commit comments