diff options
Diffstat (limited to 'Lib/ipaddress.py')
-rw-r--r-- | Lib/ipaddress.py | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 873c764408..c389f05288 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -618,6 +618,78 @@ class _BaseAddress(_IPAddressBase): def __reduce__(self): return self.__class__, (self._ip,) + def __format__(self, fmt): + """Returns an IP address as a formatted string. + + Supported presentation types are: + 's': returns the IP address as a string (default) + 'b' or 'n': converts to binary and returns a zero-padded string + 'X' or 'x': converts to upper- or lower-case hex and returns a zero-padded string + + For binary and hex presentation types, the alternate form specifier + '#' and the grouping option '_' are supported. + """ + + + # Support string formatting + if not fmt or fmt[-1] == 's': + # let format() handle it + return format(str(self), fmt) + + # From here on down, support for 'bnXx' + + import re + fmt_re = '^(?P<alternate>#?)(?P<grouping>_?)(?P<fmt_base>[xbnX]){1}$' + m = re.match(fmt_re, fmt) + if not m: + return super().__format__(fmt) + + groupdict = m.groupdict() + alternate = groupdict['alternate'] + grouping = groupdict['grouping'] + fmt_base = groupdict['fmt_base'] + + # Set some defaults + if fmt_base == 'n': + if self._version == 4: + fmt_base = 'b' # Binary is default for ipv4 + if self._version == 6: + fmt_base = 'x' # Hex is default for ipv6 + + # Handle binary formatting + if fmt_base == 'b': + if self._version == 4: + # resulting string is '0b' + 32 bits + # plus 7 _ if needed + padlen = IPV4LENGTH+2 + (7*len(grouping)) + elif self._version == 6: + # resulting string is '0b' + 128 bits + # plus 31 _ if needed + padlen = IPV6LENGTH+2 + (31*len(grouping)) + + # Handle hex formatting + elif fmt_base in 'Xx': + if self._version == 4: + # resulting string is '0x' + 8 hex digits + # plus a single _ if needed + padlen = int(IPV4LENGTH/4)+2 + len(grouping) + elif self._version == 6: + # resulting string is '0x' + 32 hex digits + # plus 7 _ if needed + padlen = int(IPV6LENGTH/4)+2 + (7*len(grouping)) + + retstr = f'{int(self):#0{padlen}{grouping}{fmt_base}}' + + if fmt_base == 'X': + retstr = retstr.upper() + + # If alternate is not set, strip the two leftmost + # characters ('0b') + if not alternate: + retstr = retstr[2:] + + return retstr + @functools.total_ordering class _BaseNetwork(_IPAddressBase): |