X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=string_utils.py;h=097dc1b092dc51bb031f104e82e09047bef1b8ad;hb=44a7740bf6fe18673f8636658256a227e0622880;hp=623ae45f03e6eb12c608f966b421ba9c5495b0e9;hpb=fa4298fa508e00759565c246aef423ba28fedf31;p=python_utils.git diff --git a/string_utils.py b/string_utils.py index 623ae45..097dc1b 100644 --- a/string_utils.py +++ b/string_utils.py @@ -791,6 +791,9 @@ def extract_mac_address(in_str: Any, *, separator: str = ":") -> Optional[str]: >>> extract_mac_address(' MAC Address: 34:29:8F:12:0D:2F') '34:29:8F:12:0D:2F' + >>> extract_mac_address('? (10.0.0.30) at d8:5d:e2:34:54:86 on em0 expires in 1176 seconds [ethernet]') + 'd8:5d:e2:34:54:86' + """ if not is_full_string(in_str): return None @@ -1138,6 +1141,24 @@ def valid_datetime(in_str: str) -> bool: return False +def squeeze(in_str: str, character_to_squeeze: str = ' ') -> str: + """ + Squeeze runs of more than one character_to_squeeze into one. + + >>> squeeze(' this is a test ') + ' this is a test ' + + >>> squeeze('one|!||!|two|!||!|three', character_to_squeeze='|!|') + 'one|!|two|!|three' + + """ + return re.sub( + r'(' + re.escape(character_to_squeeze) + r')+', + character_to_squeeze, + in_str + ) + + def dedent(in_str: str) -> str: """ Removes tab indentation from multi line strings (inspired by analogous Scala function). @@ -1461,10 +1482,14 @@ def to_bitstring(txt: str, *, delimiter='', encoding='utf-8', errors='surrogatep >>> to_bitstring('test', delimiter=' ') '01110100 01100101 01110011 01110100' + >>> to_bitstring(b'test') + '01110100011001010111001101110100' + """ + etxt = to_ascii(txt) bits = bin( int.from_bytes( - txt.encode(encoding, errors), + etxt, 'big' ) ) @@ -1496,6 +1521,38 @@ def from_bitstring(bits: str, encoding='utf-8', errors='surrogatepass') -> str: return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0' +def ip_v4_sort_key(txt: str) -> Tuple[int]: + """Turn an IPv4 address into a tuple for sorting purposes. + + >>> ip_v4_sort_key('10.0.0.18') + (10, 0, 0, 18) + + >>> ips = ['10.0.0.10', '100.0.0.1', '1.2.3.4', '10.0.0.9'] + >>> sorted(ips, key=lambda x: ip_v4_sort_key(x)) + ['1.2.3.4', '10.0.0.9', '10.0.0.10', '100.0.0.1'] + + """ + if not is_ip_v4(txt): + print(f"not IP: {txt}") + return None + return tuple([int(x) for x in txt.split('.')]) + + +def path_ancestors_before_descendants_sort_key(volume: str) -> Tuple[str]: + """Chunk up a file path so that parent/ancestor paths sort before + children/descendant paths. + + >>> path_ancestors_before_descendants_sort_key('/usr/local/bin') + ('usr', 'local', 'bin') + + >>> paths = ['/usr/local', '/usr/local/bin', '/usr'] + >>> sorted(paths, key=lambda x: path_ancestors_before_descendants_sort_key(x)) + ['/usr', '/usr/local', '/usr/local/bin'] + + """ + return tuple([x for x in volume.split('/') if len(x) > 0]) + + if __name__ == '__main__': import doctest doctest.testmod()