Coverage for src/extratools_core/strtools.py: 58%
43 statements
« prev ^ index » next coverage.py v7.8.1, created at 2025-06-24 04:41 -0700
« prev ^ index » next coverage.py v7.8.1, created at 2025-06-24 04:41 -0700
1import gzip
2from base64 import b64decode, b64encode
3from collections.abc import Callable, Iterable
4from fnmatch import fnmatchcase
5from typing import Literal
7import simple_zstd as zstd
9from .iter import iter_to_grams
10from .seq.subseq import common_subseq, enumerate_subseqs
13def str_to_grams(
14 s: str,
15 *,
16 n: int,
17 pad: str = '',
18) -> Iterable[str]:
19 if n < 1 or len(pad) > 1:
20 raise ValueError
22 for c in iter_to_grams(s, n=n, pad=pad or None):
23 yield ''.join(c)
26def common_substr(a: str, b: str) -> str:
27 return ''.join(common_subseq(a, b))
30def enumerate_substrs(s: str) -> Iterable[str]:
31 return map(str, enumerate_subseqs(s))
34def compress(
35 s: str,
36 compress_func: Callable[[bytes], bytes] = gzip.compress,
37) -> str:
38 """
39 Compress a string by GZip + Base64 encoding.
41 https://base64.guru/developers/data-uri/gzip
43 Parameters
44 ----------
45 s : str
46 String to compress
47 compress_func : Callable[[bytes], bytes]
48 Optional function to compress (`gzip.compress` in default)
50 Returns
51 -------
52 str
53 Compressed string
54 """
56 return b64encode(compress_func(s.encode())).decode()
59def encode(
60 s: str,
61 *,
62 encoding: Literal["gzip", "zstd"] | None = None,
63) -> str:
64 match encoding:
65 case "gzip":
66 return compress(s, gzip.compress)
67 case "zstd":
68 return compress(s, zstd.compress)
69 case None:
70 return s
71 case _:
72 raise ValueError
75def decompress(
76 s: str,
77 decompress_func: Callable[[bytes], bytes] = gzip.decompress,
78) -> str:
79 """
80 Decompress a string with GZip + Base64 encoding.
82 https://base64.guru/developers/data-uri/gzip
84 Parameters
85 ----------
86 s : str
87 String to decompress
88 compress_func : Callable[[bytes], bytes]
89 Optional function to decompress (`gzip.decompress` in default)
91 Returns
92 -------
93 str
94 Decompressed string
95 """
97 return decompress_func(b64decode(s.encode())).decode()
100def decode(
101 s: str,
102 *,
103 encoding: Literal["gzip", "zstd"] | None = None,
104) -> str:
105 match encoding:
106 case "gzip":
107 return decompress(s, gzip.decompress)
108 case "zstd":
109 return decompress(s, zstd.decompress)
110 case None:
111 return s
112 case _:
113 raise ValueError
116def wildcard_match(
117 key: str,
118 *,
119 includes: Iterable[str] | None = None,
120 excludes: Iterable[str] | None = None,
121) -> bool:
122 return (
123 (
124 includes is None
125 or any(
126 fnmatchcase(key, include)
127 for include in includes
128 )
129 )
130 and (
131 excludes is None
132 or not any(
133 fnmatchcase(key, exclude)
134 for exclude in excludes
136 )
137 )
138 )