@@ -560,6 +560,8 @@ def __reduce__(self):
560
560
return self .__class__ , (str (self ),)
561
561
562
562
563
+ _address_fmt_re = None
564
+
563
565
@functools .total_ordering
564
566
class _BaseAddress (_IPAddressBase ):
565
567
@@ -623,72 +625,49 @@ def __format__(self, fmt):
623
625
624
626
Supported presentation types are:
625
627
's': returns the IP address as a string (default)
626
- 'b' or 'n' : converts to binary and returns a zero-padded string
628
+ 'b': converts to binary and returns a zero-padded string
627
629
'X' or 'x': converts to upper- or lower-case hex and returns a zero-padded string
630
+ 'n': the same as 'b' for IPv4 and 'x' for IPv6
628
631
629
632
For binary and hex presentation types, the alternate form specifier
630
633
'#' and the grouping option '_' are supported.
631
634
"""
632
635
633
-
634
636
# Support string formatting
635
637
if not fmt or fmt [- 1 ] == 's' :
636
- # let format() handle it
637
638
return format (str (self ), fmt )
638
639
639
640
# From here on down, support for 'bnXx'
641
+ global _address_fmt_re
642
+ if _address_fmt_re is None :
643
+ import re
644
+ _address_fmt_re = re .compile ('(#?)(_?)([xbnX])' )
640
645
641
- import re
642
- fmt_re = '^(?P<alternate>#?)(?P<grouping>_?)(?P<fmt_base>[xbnX]){1}$'
643
- m = re .match (fmt_re , fmt )
646
+ m = _address_fmt_re .fullmatch (fmt )
644
647
if not m :
645
648
return super ().__format__ (fmt )
646
649
647
- groupdict = m .groupdict ()
648
- alternate = groupdict ['alternate' ]
649
- grouping = groupdict ['grouping' ]
650
- fmt_base = groupdict ['fmt_base' ]
650
+ alternate , grouping , fmt_base = m .groups ()
651
651
652
652
# Set some defaults
653
653
if fmt_base == 'n' :
654
654
if self ._version == 4 :
655
655
fmt_base = 'b' # Binary is default for ipv4
656
- if self . _version == 6 :
656
+ else :
657
657
fmt_base = 'x' # Hex is default for ipv6
658
658
659
- # Handle binary formatting
660
659
if fmt_base == 'b' :
661
- if self ._version == 4 :
662
- # resulting string is '0b' + 32 bits
663
- # plus 7 _ if needed
664
- padlen = IPV4LENGTH + 2 + (7 * len (grouping ))
665
- elif self ._version == 6 :
666
- # resulting string is '0b' + 128 bits
667
- # plus 31 _ if needed
668
- padlen = IPV6LENGTH + 2 + (31 * len (grouping ))
669
-
670
- # Handle hex formatting
671
- elif fmt_base in 'Xx' :
672
- if self ._version == 4 :
673
- # resulting string is '0x' + 8 hex digits
674
- # plus a single _ if needed
675
- padlen = int (IPV4LENGTH / 4 )+ 2 + len (grouping )
676
- elif self ._version == 6 :
677
- # resulting string is '0x' + 32 hex digits
678
- # plus 7 _ if needed
679
- padlen = int (IPV6LENGTH / 4 )+ 2 + (7 * len (grouping ))
680
-
681
- retstr = f'{ int (self ):#0{padlen }{grouping }{fmt_base }} '
660
+ padlen = self ._max_prefixlen
661
+ else :
662
+ padlen = self ._max_prefixlen // 4
682
663
683
- if fmt_base == 'X' :
684
- retstr = retstr . upper ()
664
+ if grouping :
665
+ padlen += padlen // 4 - 1
685
666
686
- # If alternate is not set, strip the two leftmost
687
- # characters ('0b')
688
- if not alternate :
689
- retstr = retstr [2 :]
667
+ if alternate :
668
+ padlen += 2 # 0b or 0x
690
669
691
- return retstr
670
+ return format ( int ( self ), f' { alternate } 0 { padlen } { grouping } { fmt_base } ' )
692
671
693
672
694
673
@functools .total_ordering
0 commit comments