@@ -1785,6 +1785,30 @@ def _reverse_pointer(self):
1785
1785
reverse_chars = self .exploded [::- 1 ].replace (':' , '' )
1786
1786
return '.' .join (reverse_chars ) + '.ip6.arpa'
1787
1787
1788
+ @staticmethod
1789
+ def _split_scope_id (ip_str ):
1790
+ """Helper function to parse IPv6 string address with scope id.
1791
+
1792
+ See RFC 4007 for details.
1793
+
1794
+ Arg:
1795
+ ip_str: A string, the IPv6 address.
1796
+
1797
+ Returns:
1798
+ [addr, scope_id] list.
1799
+ """
1800
+ if '%' not in ip_str :
1801
+ return ip_str , None
1802
+
1803
+ split_addr = ip_str .split ('%' )
1804
+ if len (split_addr ) > 2 or split_addr [- 1 ] == '' :
1805
+ raise AddressValueError ('Invalid IPv6 address: "%r"' % ip_str )
1806
+ try :
1807
+ addr , scope_id = split_addr
1808
+ except ValueError :
1809
+ return split_addr , None
1810
+ return addr , scope_id
1811
+
1788
1812
@property
1789
1813
def max_prefixlen (self ):
1790
1814
return self ._max_prefixlen
@@ -1798,7 +1822,7 @@ class IPv6Address(_BaseV6, _BaseAddress):
1798
1822
1799
1823
"""Represent and manipulate single IPv6 Addresses."""
1800
1824
1801
- __slots__ = ('_ip' , '__weakref__' )
1825
+ __slots__ = ('_ip' , 'scope_id' , ' __weakref__' )
1802
1826
1803
1827
def __init__ (self , address ):
1804
1828
"""Instantiate a new IPv6 address object.
@@ -1817,6 +1841,8 @@ def __init__(self, address):
1817
1841
AddressValueError: If address isn't a valid IPv6 address.
1818
1842
1819
1843
"""
1844
+ self .scope_id = None
1845
+
1820
1846
# Efficient constructor from integer.
1821
1847
if isinstance (address , int ):
1822
1848
self ._check_int_address (address )
@@ -1829,13 +1855,20 @@ def __init__(self, address):
1829
1855
self ._ip = int .from_bytes (address , 'big' )
1830
1856
return
1831
1857
1858
+
1832
1859
# Assume input argument to be string or any object representation
1833
1860
# which converts into a formatted IP string.
1834
1861
addr_str = str (address )
1835
1862
if '/' in addr_str :
1836
1863
raise AddressValueError ("Unexpected '/' in %r" % address )
1864
+ addr_str , self .scope_id = self ._split_scope_id (addr_str )
1865
+
1837
1866
self ._ip = self ._ip_int_from_string (addr_str )
1838
1867
1868
+ def __str__ (self ):
1869
+ ip_str = self ._string_from_ip_int (self ._ip )
1870
+ return ip_str if self .scope_id is None else ip_str + '%' + self .scope_id
1871
+
1839
1872
@property
1840
1873
def packed (self ):
1841
1874
"""The binary representation of this address."""
@@ -1973,7 +2006,6 @@ def sixtofour(self):
1973
2006
return None
1974
2007
return IPv4Address ((self ._ip >> 80 ) & 0xFFFFFFFF )
1975
2008
1976
-
1977
2009
class IPv6Interface (IPv6Address ):
1978
2010
1979
2011
def __init__ (self , address ):
@@ -1989,7 +2021,7 @@ def hostmask(self):
1989
2021
return self .network .hostmask
1990
2022
1991
2023
def __str__ (self ):
1992
- return '%s/%d' % (self . _string_from_ip_int ( self . _ip ),
2024
+ return '%s/%d' % (super (). __str__ ( ),
1993
2025
self ._prefixlen )
1994
2026
1995
2027
def __eq__ (self , other ):
0 commit comments