backrefs 5.8__py313-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- backrefs/__init__.py +2 -0
- backrefs/__meta__.py +197 -0
- backrefs/_bre_parse.py +1529 -0
- backrefs/_bregex_parse.py +1362 -0
- backrefs/_bregex_typing.py +6 -0
- backrefs/bre.py +652 -0
- backrefs/bregex.py +726 -0
- backrefs/py.typed +0 -0
- backrefs/uniprops/__init__.py +592 -0
- backrefs/uniprops/unidata/__init__.py +26 -0
- backrefs/uniprops/unidata/age.py +115 -0
- backrefs/uniprops/unidata/alias.py +771 -0
- backrefs/uniprops/unidata/bidiclass.py +99 -0
- backrefs/uniprops/unidata/bidipairedbrackettype.py +19 -0
- backrefs/uniprops/unidata/binary.py +331 -0
- backrefs/uniprops/unidata/block.py +1323 -0
- backrefs/uniprops/unidata/canonicalcombiningclass.py +1031 -0
- backrefs/uniprops/unidata/decompositiontype.py +79 -0
- backrefs/uniprops/unidata/eastasianwidth.py +31 -0
- backrefs/uniprops/unidata/generalcategory.py +173 -0
- backrefs/uniprops/unidata/graphemeclusterbreak.py +79 -0
- backrefs/uniprops/unidata/hangulsyllabletype.py +31 -0
- backrefs/uniprops/unidata/indicpositionalcategory.py +71 -0
- backrefs/uniprops/unidata/indicsyllabiccategory.py +151 -0
- backrefs/uniprops/unidata/joininggroup.py +423 -0
- backrefs/uniprops/unidata/joiningtype.py +31 -0
- backrefs/uniprops/unidata/linebreak.py +199 -0
- backrefs/uniprops/unidata/numerictype.py +23 -0
- backrefs/uniprops/unidata/numericvalue.py +583 -0
- backrefs/uniprops/unidata/quickcheck.py +59 -0
- backrefs/uniprops/unidata/script.py +667 -0
- backrefs/uniprops/unidata/scriptextensions.py +667 -0
- backrefs/uniprops/unidata/sentencebreak.py +67 -0
- backrefs/uniprops/unidata/verticalorientation.py +23 -0
- backrefs/uniprops/unidata/wordbreak.py +99 -0
- backrefs/util.py +163 -0
- backrefs-5.8.dist-info/METADATA +74 -0
- backrefs-5.8.dist-info/RECORD +40 -0
- backrefs-5.8.dist-info/WHEEL +4 -0
- backrefs-5.8.dist-info/licenses/LICENSE.md +21 -0
backrefs/bregex.py
ADDED
|
@@ -0,0 +1,726 @@
|
|
|
1
|
+
r"""
|
|
2
|
+
Backrefs for the 'regex' module.
|
|
3
|
+
|
|
4
|
+
Add the ability to use the following backrefs with re:
|
|
5
|
+
|
|
6
|
+
- `\Q` and `\Q...\E` - Escape/quote chars (search)
|
|
7
|
+
- `\c` and `\C...\E` - Uppercase char or chars (replace)
|
|
8
|
+
- `\l` and `\L...\E` - Lowercase char or chars (replace)
|
|
9
|
+
- `\N{Black Club Suit}` - Unicode character by name (replace)
|
|
10
|
+
- `\u0000` and `\U00000000` - Unicode characters (replace)
|
|
11
|
+
- `\R` - Generic line breaks (search)
|
|
12
|
+
|
|
13
|
+
Licensed under MIT
|
|
14
|
+
Copyright (c) 2015 - 2020 Isaac Muse <isaacmuse@gmail.com>
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
import regex as _regex # type: ignore[import]
|
|
18
|
+
import copyreg as _copyreg
|
|
19
|
+
from functools import lru_cache as _lru_cache
|
|
20
|
+
from . import util as _util
|
|
21
|
+
from . import _bregex_parse
|
|
22
|
+
from ._bregex_parse import ReplaceTemplate
|
|
23
|
+
from typing import AnyStr, Callable, Any, Generic, Mapping, Iterator, cast
|
|
24
|
+
from ._bregex_typing import Pattern, Match
|
|
25
|
+
|
|
26
|
+
__all__ = (
|
|
27
|
+
"expand", "expandf", "match", "fullmatch", "search", "sub", "subf", "subn", "subfn", "split", "splititer",
|
|
28
|
+
"findall", "finditer", "purge", "escape", "D", "DEBUG", "A", "ASCII", "B", "BESTMATCH",
|
|
29
|
+
"E", "ENHANCEMATCH", "F", "FULLCASE", "I", "IGNORECASE", "L", "LOCALE", "M", "MULTILINE", "R", "REVERSE",
|
|
30
|
+
"S", "DOTALL", "U", "UNICODE", "X", "VERBOSE", "V0", "VERSION0", "V1", "VERSION1", "W", "WORD",
|
|
31
|
+
"P", "POSIX", "DEFAULT_VERSION", "FORMAT", "compile", "compile_search", "compile_replace", "Bregex",
|
|
32
|
+
"ReplaceTemplate"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Expose some common re flags and methods to
|
|
36
|
+
# save having to import re and backrefs libraries
|
|
37
|
+
D = _regex.D
|
|
38
|
+
DEBUG = _regex.DEBUG
|
|
39
|
+
A = _regex.A
|
|
40
|
+
ASCII = _regex.ASCII
|
|
41
|
+
B = _regex.B
|
|
42
|
+
BESTMATCH = _regex.BESTMATCH
|
|
43
|
+
E = _regex.E
|
|
44
|
+
ENHANCEMATCH = _regex.ENHANCEMATCH
|
|
45
|
+
F = _regex.F
|
|
46
|
+
FULLCASE = _regex.FULLCASE
|
|
47
|
+
I = _regex.I
|
|
48
|
+
IGNORECASE = _regex.IGNORECASE
|
|
49
|
+
L = _regex.L
|
|
50
|
+
LOCALE = _regex.LOCALE
|
|
51
|
+
M = _regex.M
|
|
52
|
+
MULTILINE = _regex.MULTILINE
|
|
53
|
+
R = _regex.R
|
|
54
|
+
REVERSE = _regex.REVERSE
|
|
55
|
+
S = _regex.S
|
|
56
|
+
DOTALL = _regex.DOTALL
|
|
57
|
+
U = _regex.U
|
|
58
|
+
UNICODE = _regex.UNICODE
|
|
59
|
+
X = _regex.X
|
|
60
|
+
VERBOSE = _regex.VERBOSE
|
|
61
|
+
V0 = _regex.V0
|
|
62
|
+
VERSION0 = _regex.VERSION0
|
|
63
|
+
V1 = _regex.V1
|
|
64
|
+
VERSION1 = _regex.VERSION1
|
|
65
|
+
W = _regex.W
|
|
66
|
+
WORD = _regex.WORD
|
|
67
|
+
P = _regex.P
|
|
68
|
+
POSIX = _regex.POSIX
|
|
69
|
+
DEFAULT_VERSION = _regex.DEFAULT_VERSION
|
|
70
|
+
escape = _regex.escape
|
|
71
|
+
|
|
72
|
+
# Replace flags
|
|
73
|
+
FORMAT = 1
|
|
74
|
+
|
|
75
|
+
# Case upper or lower
|
|
76
|
+
_UPPER = 1
|
|
77
|
+
_LOWER = 2
|
|
78
|
+
|
|
79
|
+
# Maximum size of the cache.
|
|
80
|
+
_MAXCACHE = 500
|
|
81
|
+
|
|
82
|
+
_REGEX_TYPE = type(_regex.compile('', 0))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@_lru_cache(maxsize=_MAXCACHE)
|
|
86
|
+
def _cached_search_compile(
|
|
87
|
+
pattern: AnyStr,
|
|
88
|
+
re_verbose: bool,
|
|
89
|
+
re_version: bool,
|
|
90
|
+
pattern_type: type[AnyStr]
|
|
91
|
+
) -> AnyStr:
|
|
92
|
+
"""Cached search compile."""
|
|
93
|
+
|
|
94
|
+
return _bregex_parse._SearchParser(pattern, re_verbose, re_version).parse()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@_lru_cache(maxsize=_MAXCACHE)
|
|
98
|
+
def _cached_replace_compile(
|
|
99
|
+
pattern: Pattern[AnyStr],
|
|
100
|
+
repl: AnyStr,
|
|
101
|
+
flags: int,
|
|
102
|
+
pattern_type: type[AnyStr]
|
|
103
|
+
) -> ReplaceTemplate[AnyStr]:
|
|
104
|
+
"""Cached replace compile."""
|
|
105
|
+
|
|
106
|
+
return _bregex_parse._ReplaceParser(pattern, repl, bool(flags & FORMAT)).parse()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _get_cache_size(replace: bool = False) -> int:
|
|
110
|
+
"""Get size of cache."""
|
|
111
|
+
|
|
112
|
+
if not replace:
|
|
113
|
+
size = _cached_search_compile.cache_info().currsize
|
|
114
|
+
else:
|
|
115
|
+
size = _cached_replace_compile.cache_info().currsize
|
|
116
|
+
return size
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _purge_cache() -> None:
|
|
120
|
+
"""Purge the cache."""
|
|
121
|
+
|
|
122
|
+
_cached_replace_compile.cache_clear()
|
|
123
|
+
_cached_search_compile.cache_clear()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _is_replace(obj: Any) -> bool:
|
|
127
|
+
"""Check if object is a replace object."""
|
|
128
|
+
|
|
129
|
+
return isinstance(obj, ReplaceTemplate)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _apply_replace_backrefs(
|
|
133
|
+
m: Match[AnyStr] | None,
|
|
134
|
+
repl: ReplaceTemplate[AnyStr] | AnyStr,
|
|
135
|
+
flags: int = 0
|
|
136
|
+
) -> AnyStr:
|
|
137
|
+
"""Expand with either the `ReplaceTemplate` or compile on the fly, or return None."""
|
|
138
|
+
|
|
139
|
+
if m is None:
|
|
140
|
+
raise ValueError("Match is None!")
|
|
141
|
+
|
|
142
|
+
if isinstance(repl, ReplaceTemplate):
|
|
143
|
+
return repl.expand(m)
|
|
144
|
+
return _bregex_parse._ReplaceParser(m.re, repl, bool(flags & FORMAT)).parse().expand(m)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _apply_search_backrefs(
|
|
148
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
149
|
+
flags: int = 0
|
|
150
|
+
) -> AnyStr | Pattern[AnyStr]:
|
|
151
|
+
"""Apply the search backrefs to the search pattern."""
|
|
152
|
+
|
|
153
|
+
if isinstance(pattern, (str, bytes)):
|
|
154
|
+
re_verbose = VERBOSE & flags
|
|
155
|
+
if flags & V0:
|
|
156
|
+
re_version = V0
|
|
157
|
+
elif flags & V1:
|
|
158
|
+
re_version = V1
|
|
159
|
+
else:
|
|
160
|
+
re_version = 0
|
|
161
|
+
if not (flags & DEBUG):
|
|
162
|
+
p = _cached_search_compile(
|
|
163
|
+
pattern, re_verbose, re_version, type(pattern)
|
|
164
|
+
) # type: AnyStr | Pattern[AnyStr]
|
|
165
|
+
else: # pragma: no cover
|
|
166
|
+
p = _bregex_parse._SearchParser(cast(AnyStr, pattern), re_verbose, re_version).parse()
|
|
167
|
+
elif isinstance(pattern, Bregex):
|
|
168
|
+
if flags:
|
|
169
|
+
raise ValueError("Cannot process flags argument with a compiled pattern")
|
|
170
|
+
p = pattern._pattern
|
|
171
|
+
elif isinstance(pattern, _REGEX_TYPE):
|
|
172
|
+
if flags:
|
|
173
|
+
raise ValueError("Cannot process flags argument with a compiled pattern!")
|
|
174
|
+
p = pattern
|
|
175
|
+
else:
|
|
176
|
+
raise TypeError("Not a string or compiled pattern!")
|
|
177
|
+
return p
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _assert_expandable(repl: Any, use_format: bool = False) -> None:
|
|
181
|
+
"""Check if replace template is expandable."""
|
|
182
|
+
|
|
183
|
+
if isinstance(repl, ReplaceTemplate):
|
|
184
|
+
if repl.use_format != use_format:
|
|
185
|
+
if use_format:
|
|
186
|
+
raise ValueError("Replace not compiled as a format replace")
|
|
187
|
+
else:
|
|
188
|
+
raise ValueError("Replace should not be compiled as a format replace!")
|
|
189
|
+
elif not isinstance(repl, (str, bytes)):
|
|
190
|
+
raise TypeError("Expected string, buffer, or compiled replace!")
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
###########################
|
|
194
|
+
# API
|
|
195
|
+
##########################
|
|
196
|
+
class Bregex(_util.Immutable, Generic[AnyStr]):
|
|
197
|
+
"""Bregex object."""
|
|
198
|
+
|
|
199
|
+
_pattern: Pattern[AnyStr]
|
|
200
|
+
auto_compile: bool
|
|
201
|
+
_hash: int
|
|
202
|
+
|
|
203
|
+
__slots__ = ("_pattern", "auto_compile", "_hash")
|
|
204
|
+
|
|
205
|
+
def __init__(self, pattern: Pattern[AnyStr], auto_compile: bool = True) -> None:
|
|
206
|
+
"""Initialization."""
|
|
207
|
+
|
|
208
|
+
super().__init__(
|
|
209
|
+
_pattern=pattern,
|
|
210
|
+
auto_compile=auto_compile,
|
|
211
|
+
_hash=hash((type(self), type(pattern), pattern, auto_compile))
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def pattern(self) -> AnyStr:
|
|
216
|
+
"""Return pattern."""
|
|
217
|
+
|
|
218
|
+
return cast(AnyStr, self._pattern.pattern)
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def flags(self) -> int:
|
|
222
|
+
"""Return flags."""
|
|
223
|
+
|
|
224
|
+
return cast(int, self._pattern.flags)
|
|
225
|
+
|
|
226
|
+
@property
|
|
227
|
+
def groupindex(self) -> Mapping[str, int]:
|
|
228
|
+
"""Return group index."""
|
|
229
|
+
|
|
230
|
+
return cast(Mapping[str, int], self._pattern.groupindex)
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def groups(self) -> tuple[AnyStr | None, ...]:
|
|
234
|
+
"""Return groups."""
|
|
235
|
+
|
|
236
|
+
return cast('tuple[AnyStr | None, ...]', self._pattern.groups)
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def scanner(self) -> Any:
|
|
240
|
+
"""Return scanner."""
|
|
241
|
+
|
|
242
|
+
return self._pattern.scanner
|
|
243
|
+
|
|
244
|
+
def __hash__(self) -> int:
|
|
245
|
+
"""Hash."""
|
|
246
|
+
|
|
247
|
+
return self._hash
|
|
248
|
+
|
|
249
|
+
def __eq__(self, other: Any) -> bool:
|
|
250
|
+
"""Equal."""
|
|
251
|
+
|
|
252
|
+
return (
|
|
253
|
+
isinstance(other, Bregex) and
|
|
254
|
+
self._pattern == other._pattern and
|
|
255
|
+
self.auto_compile == other.auto_compile
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
def __ne__(self, other: Any) -> bool:
|
|
259
|
+
"""Equal."""
|
|
260
|
+
|
|
261
|
+
return (
|
|
262
|
+
not isinstance(other, Bregex) or
|
|
263
|
+
self._pattern != other._pattern or
|
|
264
|
+
self.auto_compile != other.auto_compile
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
def __repr__(self) -> str: # pragma: no cover
|
|
268
|
+
"""Representation."""
|
|
269
|
+
|
|
270
|
+
return '{}.{}({!r}, auto_compile={!r})'.format(
|
|
271
|
+
self.__module__, self.__class__.__name__, self._pattern, self.auto_compile
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
def _auto_compile(
|
|
275
|
+
self,
|
|
276
|
+
template: AnyStr | Callable[..., AnyStr],
|
|
277
|
+
use_format: bool = False
|
|
278
|
+
) -> AnyStr | Callable[..., AnyStr]:
|
|
279
|
+
"""Compile replacements."""
|
|
280
|
+
|
|
281
|
+
if isinstance(template, ReplaceTemplate):
|
|
282
|
+
if use_format != template.use_format:
|
|
283
|
+
raise ValueError("Compiled replace cannot be a format object!")
|
|
284
|
+
elif isinstance(template, ReplaceTemplate) or (isinstance(template, (str, bytes)) and self.auto_compile):
|
|
285
|
+
return self.compile(template, (FORMAT if use_format and not isinstance(template, ReplaceTemplate) else 0))
|
|
286
|
+
elif isinstance(template, (str, bytes)) and use_format:
|
|
287
|
+
# Reject an attempt to run format replace when auto-compiling
|
|
288
|
+
# of template strings has been disabled and we are using a
|
|
289
|
+
# template string.
|
|
290
|
+
raise AttributeError('Format replaces cannot be called without compiling replace template!')
|
|
291
|
+
return template
|
|
292
|
+
|
|
293
|
+
def compile( # noqa A001
|
|
294
|
+
self,
|
|
295
|
+
repl: AnyStr | Callable[..., AnyStr],
|
|
296
|
+
flags: int = 0
|
|
297
|
+
) -> Callable[..., AnyStr]:
|
|
298
|
+
"""Compile replace."""
|
|
299
|
+
|
|
300
|
+
return compile_replace(self._pattern, repl, flags)
|
|
301
|
+
|
|
302
|
+
@property
|
|
303
|
+
def named_lists(self) -> Mapping[str, set[str | bytes]]:
|
|
304
|
+
"""Returned named lists."""
|
|
305
|
+
|
|
306
|
+
return cast('Mapping[str, set[str | bytes]]', self._pattern.named_lists)
|
|
307
|
+
|
|
308
|
+
def search(
|
|
309
|
+
self,
|
|
310
|
+
string: AnyStr,
|
|
311
|
+
*args: Any,
|
|
312
|
+
**kwargs: Any
|
|
313
|
+
) -> Match[AnyStr] | None:
|
|
314
|
+
"""Apply `search`."""
|
|
315
|
+
|
|
316
|
+
return self._pattern.search(string, *args, **kwargs)
|
|
317
|
+
|
|
318
|
+
def match(
|
|
319
|
+
self,
|
|
320
|
+
string: AnyStr,
|
|
321
|
+
*args: Any,
|
|
322
|
+
**kwargs: Any
|
|
323
|
+
) -> Match[AnyStr] | None:
|
|
324
|
+
"""Apply `match`."""
|
|
325
|
+
|
|
326
|
+
return cast('Match[AnyStr] | None', self._pattern.match(string, *args, **kwargs))
|
|
327
|
+
|
|
328
|
+
def fullmatch(
|
|
329
|
+
self,
|
|
330
|
+
string: AnyStr,
|
|
331
|
+
*args: Any,
|
|
332
|
+
**kwargs: Any
|
|
333
|
+
) -> Match[AnyStr] | None:
|
|
334
|
+
"""Apply `fullmatch`."""
|
|
335
|
+
|
|
336
|
+
return cast('Match[AnyStr] | None', self._pattern.fullmatch(string, *args, **kwargs))
|
|
337
|
+
|
|
338
|
+
def split(
|
|
339
|
+
self,
|
|
340
|
+
string: AnyStr,
|
|
341
|
+
*args: Any,
|
|
342
|
+
**kwargs: Any
|
|
343
|
+
) -> list[AnyStr]:
|
|
344
|
+
"""Apply `split`."""
|
|
345
|
+
|
|
346
|
+
return cast('list[AnyStr]', self._pattern.split(string, *args, **kwargs))
|
|
347
|
+
|
|
348
|
+
def splititer(
|
|
349
|
+
self,
|
|
350
|
+
string: AnyStr,
|
|
351
|
+
*args: Any,
|
|
352
|
+
**kwargs: Any
|
|
353
|
+
) -> Iterator[AnyStr]:
|
|
354
|
+
"""Apply `splititer`."""
|
|
355
|
+
|
|
356
|
+
return cast(Iterator[AnyStr], self._pattern.splititer(string, *args, **kwargs))
|
|
357
|
+
|
|
358
|
+
def findall(
|
|
359
|
+
self,
|
|
360
|
+
string: AnyStr,
|
|
361
|
+
*args: Any,
|
|
362
|
+
**kwargs: Any
|
|
363
|
+
) -> list[AnyStr] | list[tuple[AnyStr, ...]]:
|
|
364
|
+
"""Apply `findall`."""
|
|
365
|
+
|
|
366
|
+
return cast('list[AnyStr] | list[tuple[AnyStr, ...]]', self._pattern.findall(string, *args, **kwargs))
|
|
367
|
+
|
|
368
|
+
def finditer(
|
|
369
|
+
self,
|
|
370
|
+
string: AnyStr,
|
|
371
|
+
*args: Any,
|
|
372
|
+
**kwargs: Any
|
|
373
|
+
) -> Iterator[Match[AnyStr]]:
|
|
374
|
+
"""Apply `finditer`."""
|
|
375
|
+
|
|
376
|
+
return cast(Iterator[Match[AnyStr]], self._pattern.finditer(string, *args, **kwargs))
|
|
377
|
+
|
|
378
|
+
def sub(
|
|
379
|
+
self,
|
|
380
|
+
repl: AnyStr | Callable[..., AnyStr],
|
|
381
|
+
string: AnyStr,
|
|
382
|
+
*args: Any,
|
|
383
|
+
**kwargs: Any
|
|
384
|
+
) -> AnyStr:
|
|
385
|
+
"""Apply `sub`."""
|
|
386
|
+
|
|
387
|
+
return cast(AnyStr, self._pattern.sub(self._auto_compile(repl), string, *args, **kwargs))
|
|
388
|
+
|
|
389
|
+
def subf(
|
|
390
|
+
self,
|
|
391
|
+
repl: AnyStr | Callable[..., AnyStr],
|
|
392
|
+
string: AnyStr,
|
|
393
|
+
*args: Any,
|
|
394
|
+
**kwargs: Any
|
|
395
|
+
) -> AnyStr: # noqa A002
|
|
396
|
+
"""Apply `sub` with format style replace."""
|
|
397
|
+
|
|
398
|
+
return cast(AnyStr, self._pattern.subf(self._auto_compile(repl, True), string, *args, **kwargs))
|
|
399
|
+
|
|
400
|
+
def subn(
|
|
401
|
+
self,
|
|
402
|
+
repl: AnyStr | Callable[..., AnyStr],
|
|
403
|
+
string: AnyStr,
|
|
404
|
+
*args: Any,
|
|
405
|
+
**kwargs: Any
|
|
406
|
+
) -> tuple[AnyStr, int]:
|
|
407
|
+
"""Apply `subn` with format style replace."""
|
|
408
|
+
|
|
409
|
+
return cast('tuple[AnyStr, int]', self._pattern.subn(self._auto_compile(repl), string, *args, **kwargs))
|
|
410
|
+
|
|
411
|
+
def subfn(
|
|
412
|
+
self,
|
|
413
|
+
repl: AnyStr | Callable[..., AnyStr],
|
|
414
|
+
string: AnyStr,
|
|
415
|
+
*args: Any,
|
|
416
|
+
**kwargs: Any
|
|
417
|
+
) -> tuple[AnyStr, int]: # noqa A002
|
|
418
|
+
"""Apply `subn` after applying backrefs."""
|
|
419
|
+
|
|
420
|
+
return cast('tuple[AnyStr, int]', self._pattern.subfn(self._auto_compile(repl, True), string, *args, **kwargs))
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def compile( # noqa A001
|
|
424
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
425
|
+
flags: int = 0,
|
|
426
|
+
auto_compile: bool | None = None,
|
|
427
|
+
**kwargs: Any
|
|
428
|
+
) -> Bregex[AnyStr]:
|
|
429
|
+
"""Compile both the search or search and replace into one object."""
|
|
430
|
+
|
|
431
|
+
if isinstance(pattern, Bregex):
|
|
432
|
+
if auto_compile is not None:
|
|
433
|
+
raise ValueError("Cannot compile Bregex with a different auto_compile!")
|
|
434
|
+
elif flags != 0:
|
|
435
|
+
raise ValueError("Cannot process flags argument with a compiled pattern")
|
|
436
|
+
return pattern
|
|
437
|
+
else:
|
|
438
|
+
if auto_compile is None:
|
|
439
|
+
auto_compile = True
|
|
440
|
+
|
|
441
|
+
return Bregex(compile_search(pattern, flags, **kwargs), auto_compile)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def compile_search(
|
|
445
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
446
|
+
flags: int = 0,
|
|
447
|
+
**kwargs: Any
|
|
448
|
+
) -> Pattern[AnyStr]:
|
|
449
|
+
"""Compile with extended search references."""
|
|
450
|
+
|
|
451
|
+
return cast(Pattern[AnyStr], _regex.compile(_apply_search_backrefs(pattern, flags), flags, **kwargs))
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def compile_replace(
|
|
455
|
+
pattern: Pattern[AnyStr],
|
|
456
|
+
repl: AnyStr | Callable[..., AnyStr],
|
|
457
|
+
flags: int = 0
|
|
458
|
+
) -> Callable[..., AnyStr]:
|
|
459
|
+
"""Construct a method that can be used as a replace method for `sub`, `subn`, etc."""
|
|
460
|
+
|
|
461
|
+
if pattern is not None and isinstance(pattern, _REGEX_TYPE):
|
|
462
|
+
if isinstance(repl, (str, bytes)):
|
|
463
|
+
if not (pattern.flags & DEBUG):
|
|
464
|
+
call = _cached_replace_compile(pattern, repl, flags, type(repl))
|
|
465
|
+
else: # pragma: no cover
|
|
466
|
+
call = _bregex_parse._ReplaceParser(pattern, repl, bool(flags & FORMAT)).parse()
|
|
467
|
+
elif isinstance(repl, ReplaceTemplate):
|
|
468
|
+
if flags:
|
|
469
|
+
raise ValueError("Cannot process flags argument with a ReplaceTemplate!")
|
|
470
|
+
if repl.pattern_hash != hash(pattern):
|
|
471
|
+
raise ValueError("Pattern hash doesn't match hash in compiled replace!")
|
|
472
|
+
call = repl
|
|
473
|
+
else:
|
|
474
|
+
raise TypeError("Not a valid type!")
|
|
475
|
+
else:
|
|
476
|
+
raise TypeError("Pattern must be a compiled regular expression!")
|
|
477
|
+
return call
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
def purge() -> None:
|
|
481
|
+
"""Purge caches."""
|
|
482
|
+
|
|
483
|
+
_purge_cache()
|
|
484
|
+
_regex.purge()
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def expand(m: Match[AnyStr] | None, repl: ReplaceTemplate[AnyStr] | AnyStr) -> AnyStr:
|
|
488
|
+
"""Expand the string using the replace pattern or function."""
|
|
489
|
+
|
|
490
|
+
_assert_expandable(repl)
|
|
491
|
+
return _apply_replace_backrefs(m, repl)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def expandf(m: Match[AnyStr] | None, repl: ReplaceTemplate[AnyStr] | AnyStr) -> AnyStr:
|
|
495
|
+
"""Expand the string using the format replace pattern or function."""
|
|
496
|
+
|
|
497
|
+
_assert_expandable(repl, True)
|
|
498
|
+
return _apply_replace_backrefs(m, repl, flags=FORMAT)
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def match(
|
|
502
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
503
|
+
string: AnyStr,
|
|
504
|
+
flags: int = 0,
|
|
505
|
+
*args: Any,
|
|
506
|
+
**kwargs: Any
|
|
507
|
+
) -> Match[AnyStr] | None:
|
|
508
|
+
"""Wrapper for `match`."""
|
|
509
|
+
|
|
510
|
+
return cast(
|
|
511
|
+
'Match[AnyStr] | None',
|
|
512
|
+
_regex.match(_apply_search_backrefs(pattern, flags), string, flags, *args, **kwargs)
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
def fullmatch(
|
|
517
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
518
|
+
string: AnyStr,
|
|
519
|
+
flags: int = 0,
|
|
520
|
+
*args: Any,
|
|
521
|
+
**kwargs: Any
|
|
522
|
+
) -> Match[AnyStr] | None:
|
|
523
|
+
"""Wrapper for `fullmatch`."""
|
|
524
|
+
|
|
525
|
+
return cast(
|
|
526
|
+
'Match[AnyStr] | None',
|
|
527
|
+
_regex.fullmatch(_apply_search_backrefs(pattern, flags), string, flags, *args, **kwargs)
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
def search(
|
|
532
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
533
|
+
string: AnyStr,
|
|
534
|
+
flags: int = 0,
|
|
535
|
+
*args: Any,
|
|
536
|
+
**kwargs: Any
|
|
537
|
+
) -> Match[AnyStr] | None:
|
|
538
|
+
"""Wrapper for `search`."""
|
|
539
|
+
|
|
540
|
+
return cast(
|
|
541
|
+
'Match[AnyStr] | None',
|
|
542
|
+
_regex.search(_apply_search_backrefs(pattern, flags), string, flags, *args, **kwargs)
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
def sub(
|
|
547
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
548
|
+
repl: AnyStr | Callable[..., AnyStr],
|
|
549
|
+
string: AnyStr,
|
|
550
|
+
count: int = 0,
|
|
551
|
+
flags: int = 0,
|
|
552
|
+
*args: Any,
|
|
553
|
+
**kwargs: Any
|
|
554
|
+
) -> AnyStr:
|
|
555
|
+
"""Wrapper for `sub`."""
|
|
556
|
+
|
|
557
|
+
is_replace = _is_replace(repl)
|
|
558
|
+
is_string = isinstance(repl, (str, bytes))
|
|
559
|
+
if is_replace and cast(ReplaceTemplate[AnyStr], repl).use_format:
|
|
560
|
+
raise ValueError("Compiled replace cannot be a format object!")
|
|
561
|
+
|
|
562
|
+
pattern = compile_search(pattern, flags)
|
|
563
|
+
return cast(
|
|
564
|
+
AnyStr,
|
|
565
|
+
_regex.sub(
|
|
566
|
+
pattern, (compile_replace(pattern, repl) if is_replace or is_string else repl), string,
|
|
567
|
+
count,
|
|
568
|
+
0,
|
|
569
|
+
*args, **kwargs
|
|
570
|
+
)
|
|
571
|
+
)
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
def subf(
|
|
575
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
576
|
+
repl: AnyStr | Callable[..., AnyStr],
|
|
577
|
+
string: AnyStr,
|
|
578
|
+
count: int = 0,
|
|
579
|
+
flags: int = 0,
|
|
580
|
+
*args: Any,
|
|
581
|
+
**kwargs: Any
|
|
582
|
+
) -> AnyStr:
|
|
583
|
+
"""Wrapper for `subf`."""
|
|
584
|
+
|
|
585
|
+
is_replace = _is_replace(repl)
|
|
586
|
+
is_string = isinstance(repl, (str, bytes))
|
|
587
|
+
if is_replace and not cast(ReplaceTemplate[AnyStr], repl).use_format:
|
|
588
|
+
raise ValueError("Compiled replace is not a format object!")
|
|
589
|
+
|
|
590
|
+
pattern = compile_search(pattern, flags)
|
|
591
|
+
rflags = FORMAT if is_string else 0
|
|
592
|
+
return cast(
|
|
593
|
+
AnyStr,
|
|
594
|
+
_regex.sub(
|
|
595
|
+
pattern, (compile_replace(pattern, repl, flags=rflags) if is_replace or is_string else repl), string,
|
|
596
|
+
count,
|
|
597
|
+
0,
|
|
598
|
+
*args, **kwargs
|
|
599
|
+
)
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
def subn(
|
|
604
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
605
|
+
repl: AnyStr | Callable[..., AnyStr],
|
|
606
|
+
string: AnyStr,
|
|
607
|
+
count: int = 0,
|
|
608
|
+
flags: int = 0,
|
|
609
|
+
*args: Any,
|
|
610
|
+
**kwargs: Any
|
|
611
|
+
) -> tuple[AnyStr, int]:
|
|
612
|
+
"""Wrapper for `subn`."""
|
|
613
|
+
|
|
614
|
+
is_replace = _is_replace(repl)
|
|
615
|
+
is_string = isinstance(repl, (str, bytes))
|
|
616
|
+
if is_replace and cast(ReplaceTemplate[AnyStr], repl).use_format:
|
|
617
|
+
raise ValueError("Compiled replace cannot be a format object!")
|
|
618
|
+
|
|
619
|
+
pattern = compile_search(pattern, flags)
|
|
620
|
+
return cast(
|
|
621
|
+
'tuple[AnyStr, int]',
|
|
622
|
+
_regex.subn(
|
|
623
|
+
pattern, (compile_replace(pattern, repl) if is_replace or is_string else repl), string,
|
|
624
|
+
count,
|
|
625
|
+
0,
|
|
626
|
+
*args, **kwargs
|
|
627
|
+
)
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
def subfn(
|
|
632
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
633
|
+
repl: AnyStr | Callable[..., AnyStr],
|
|
634
|
+
string: AnyStr,
|
|
635
|
+
count: int = 0,
|
|
636
|
+
flags: int = 0,
|
|
637
|
+
*args: Any,
|
|
638
|
+
**kwargs: Any
|
|
639
|
+
) -> tuple[AnyStr, int]:
|
|
640
|
+
"""Wrapper for `subfn`."""
|
|
641
|
+
|
|
642
|
+
is_replace = _is_replace(repl)
|
|
643
|
+
is_string = isinstance(repl, (str, bytes))
|
|
644
|
+
if is_replace and not cast(ReplaceTemplate[AnyStr], repl).use_format:
|
|
645
|
+
raise ValueError("Compiled replace is not a format object!")
|
|
646
|
+
|
|
647
|
+
pattern = compile_search(pattern, flags)
|
|
648
|
+
rflags = FORMAT if is_string else 0
|
|
649
|
+
return cast(
|
|
650
|
+
'tuple[AnyStr, int]',
|
|
651
|
+
_regex.subn(
|
|
652
|
+
pattern, (compile_replace(pattern, repl, flags=rflags) if is_replace or is_string else repl), string,
|
|
653
|
+
count,
|
|
654
|
+
0,
|
|
655
|
+
*args, **kwargs
|
|
656
|
+
)
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
def split(
|
|
661
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
662
|
+
string: AnyStr,
|
|
663
|
+
maxsplit: int = 0,
|
|
664
|
+
flags: int = 0,
|
|
665
|
+
*args: Any,
|
|
666
|
+
**kwargs: Any
|
|
667
|
+
) -> list[AnyStr]:
|
|
668
|
+
"""Wrapper for `split`."""
|
|
669
|
+
|
|
670
|
+
return cast(
|
|
671
|
+
'list[AnyStr]',
|
|
672
|
+
_regex.split(_apply_search_backrefs(pattern, flags), string, maxsplit, flags, *args, **kwargs)
|
|
673
|
+
)
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def splititer(
|
|
677
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
678
|
+
string: AnyStr,
|
|
679
|
+
maxsplit: int = 0,
|
|
680
|
+
flags: int = 0,
|
|
681
|
+
*args: Any,
|
|
682
|
+
**kwargs: Any
|
|
683
|
+
) -> Iterator[AnyStr]:
|
|
684
|
+
"""Wrapper for `splititer`."""
|
|
685
|
+
|
|
686
|
+
return cast(
|
|
687
|
+
Iterator[AnyStr],
|
|
688
|
+
_regex.splititer(_apply_search_backrefs(pattern, flags), string, maxsplit, flags, *args, **kwargs)
|
|
689
|
+
)
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
def findall(
|
|
693
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
694
|
+
string: AnyStr,
|
|
695
|
+
flags: int = 0,
|
|
696
|
+
*args: Any,
|
|
697
|
+
**kwargs: Any
|
|
698
|
+
) -> list[AnyStr] | list[tuple[AnyStr, ...]]:
|
|
699
|
+
"""Wrapper for `findall`."""
|
|
700
|
+
|
|
701
|
+
return cast(
|
|
702
|
+
'list[AnyStr] | list[tuple[AnyStr, ...]]',
|
|
703
|
+
_regex.findall(_apply_search_backrefs(pattern, flags), string, flags, *args, **kwargs)
|
|
704
|
+
)
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
def finditer(
|
|
708
|
+
pattern: AnyStr | Pattern[AnyStr] | Bregex[AnyStr],
|
|
709
|
+
string: AnyStr,
|
|
710
|
+
flags: int = 0,
|
|
711
|
+
*args: Any,
|
|
712
|
+
**kwargs: Any
|
|
713
|
+
) -> Iterator[Match[AnyStr]]:
|
|
714
|
+
"""Wrapper for `finditer`."""
|
|
715
|
+
|
|
716
|
+
return cast(
|
|
717
|
+
Iterator[Match[AnyStr]],
|
|
718
|
+
_regex.finditer(_apply_search_backrefs(pattern, flags), string, *args, **kwargs)
|
|
719
|
+
)
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
def _pickle(p): # type: ignore[no-untyped-def]
|
|
723
|
+
return Bregex, (p._pattern, p.auto_compile)
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
_copyreg.pickle(Bregex, _pickle)
|