diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 516a623..b6a5152 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -52,6 +52,12 @@ repos: name: "Python: Formating files" args: [--line-length=88, --preview, --safe] types: [file, python] + - repo: https://github.com/asottile/pyupgrade + rev: v2.32.1 + hooks: + - id: pyupgrade + name: "Python: upgrade syntax" + args: [--py37-plus] - repo: https://github.com/hadialqattan/pycln rev: v1.3.2 hooks: @@ -93,6 +99,7 @@ repos: # making isort line length compatible with black - "--max-line-length=88" - "--max-complexity=18" + - "--kwargs-max-positional-arguments=4" # allowing these errors now that in the past we ignored. # D100 Missing docstring in public module # D103 Missing docstring in public function @@ -131,7 +138,13 @@ repos: - flake8-colors - flake8-tuple - pandas-vet - # - wemake-python-styleguide + - flake8-length + - flake8-assertive + - flake8-warnings + - flake8-comprehensions + - flake8-simplify + - flake8-noqa + - flake8-force-keyword-arguments exclude: "setup[.]py|conf[.]py|__init__[.]py" types: [file, python] - repo: https://github.com/asottile/add-trailing-comma diff --git a/.vscode/settings.json b/.vscode/settings.json index 19a66dd..3a46794 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,5 +12,9 @@ "pylance", "pyright", "Verbex" + ], + "python.linting.flake8Enabled": true, + "python.linting.flake8Args": [ + "--ignore=E501" ] } diff --git a/check_names.py b/check_names.py index b6d6eeb..3525104 100644 --- a/check_names.py +++ b/check_names.py @@ -50,20 +50,18 @@ def main() -> int: print(f"ERROR: '{module_name}' is not all lowercase with underscores") return ExitCode.DATA_ERR # check package if exists - if package_name.strip() != "": - # check package name - if not re.fullmatch("[A-Za-z]+", package_name): - if re.fullmatch("[A-Za-z0-9]+", package_name): - print( - f"WARNING: '{package_name}' has numbers - allowing but note" - " this is not 'strictly' to pep 8 best practices", - ) - else: - print( - f"ERROR: '{package_name}' is not all lowercase with no" - " underscores", - ) - return ExitCode.DATA_ERR + # check package name + if package_name.strip() != "" and not re.fullmatch("[A-Za-z]+", package_name): + if re.fullmatch("[A-Za-z0-9]+", package_name): + print( + f"WARNING: '{package_name}' has numbers - allowing but note" + " this is not 'strictly' to pep 8 best practices", + ) + else: + print( + f"ERROR: '{package_name}' is not all lowercase with no underscores", + ) + return ExitCode.DATA_ERR return ExitCode.OK diff --git a/docs/verbex/verbex.html b/docs/verbex/verbex.html index 59dc123..17bbb44 100644 --- a/docs/verbex/verbex.html +++ b/docs/verbex/verbex.html @@ -261,631 +261,634 @@

15except ImportError: 16 from typing_extensions import TypeAlias, Protocol, Annotated, ParamSpec, runtime_checkable # type: ignore # <--- if Python < 3.9.0 # noqa E501 17 - 18from typing import Pattern, TypeVar + 18from typing import TYPE_CHECKING, Pattern, TypeVar 19 - 20from beartype import beartype # type: ignore - 21from beartype.typing import ( # type: ignore - 22 Any, - 23 Callable, - 24 Dict, - 25 Iterator, - 26 List, - 27 Optional, - 28 Tuple, - 29 Union, - 30 cast, - 31) - 32from beartype.vale import Is # type: ignore - 33 - 34 - 35def _string_len_is_1(text: object) -> bool: - 36 return isinstance(text, str) and len(text) == 1 + 20if TYPE_CHECKING: + 21 from typing import Protocol # noqa: F811 + 22 + 23from beartype import beartype # type: ignore + 24from beartype.typing import ( # type: ignore + 25 Any, + 26 Callable, + 27 Dict, + 28 Iterator, + 29 List, + 30 Optional, + 31 Tuple, + 32 Union, + 33 cast, + 34) + 35from beartype.vale import Is # type: ignore + 36 37 - 38 - 39Char = Annotated[str, Is[_string_len_is_1]] + 38def _string_len_is_1(text: object) -> bool: + 39 return isinstance(text, str) and len(text) == 1 40 41 - 42P = ParamSpec("P") # noqa VNE001 - 43R = TypeVar("R") # noqa VNE001 + 42Char = Annotated[str, Is[_string_len_is_1]] + 43 44 - 45 - 46# work around for bug https://github.com/python/mypy/issues/12660 - 47# fixed in next version of mypy. - 48@runtime_checkable - 49class HasIter(Protocol): - 50 """Workaround for mypy P.args.""" - 51 - 52 def __iter__(self) -> Iterator[Any]: - 53 """Object can be iterated. + 45P = ParamSpec("P") # noqa: VNE001 + 46R = TypeVar("R") # noqa: VNE001 + 47 + 48 + 49# work around for bug https://github.com/python/mypy/issues/12660 + 50# fixed in next version of mypy. + 51@runtime_checkable + 52class HasIter(Protocol): + 53 """Workaround for mypy P.args.""" 54 - 55 Yields: - 56 Next object. - 57 """ - 58 ... - 59 - 60 - 61# work around for bug https://github.com/python/mypy/issues/12660 - 62# fixed in next version of mypy - 63@runtime_checkable - 64class HasItems(Protocol): - 65 """Workaround for mypy P.kwargs.""" - 66 - 67 def items(self) -> Tuple[str, Any]: - 68 """Object has items method. + 55 def __iter__(self) -> Iterator[Any]: + 56 """Object can be iterated. + 57 + 58 Yields: + 59 Next object. + 60 """ + 61 ... + 62 + 63 + 64# work around for bug https://github.com/python/mypy/issues/12660 + 65# fixed in next version of mypy + 66@runtime_checkable + 67class HasItems(Protocol): + 68 """Workaround for mypy P.kwargs.""" 69 - 70 Returns: - 71 The dict of items. - 72 """ - 73 ... - 74 - 75 - 76class EscapedText(str): - 77 """Text that has been escaped for regex. + 70 def items(self) -> Tuple[str, Any]: + 71 """Object has items method. + 72 + 73 Returns: + 74 The dict of items. + 75 """ + 76 ... + 77 78 - 79 Arguments: - 80 str -- Extend the string class. - 81 """ - 82 - 83 def __new__(cls, value: str) -> EscapedText: - 84 """Return a escaped regex string. + 79class EscapedText(str): + 80 """Text that has been escaped for regex. + 81 + 82 Arguments: + 83 str -- Extend the string class. + 84 """ 85 - 86 Arguments: - 87 value -- the string to escape + 86 def __new__(cls, value: str) -> EscapedText: + 87 """Return a escaped regex string. 88 - 89 Returns: - 90 _description_ - 91 """ - 92 return str.__new__(cls, re.escape(value)) - 93 - 94 - 95def re_escape(func: Callable[P, R]) -> Callable[P, R]: - 96 """Automatically escape any string parameters as EscapedText. + 89 Arguments: + 90 value -- the string to escape + 91 + 92 Returns: + 93 _description_ + 94 """ + 95 return str.__new__(cls, re.escape(value)) + 96 97 - 98 Arguments: - 99 func -- The function to decorate. + 98def re_escape(func: Callable[P, R]) -> Callable[P, R]: + 99 """Automatically escape any string parameters as EscapedText. 100 -101 Returns: -102 The decorated function. -103 """ -104 -105 @wraps(func) -106 def inner(*args: P.args, **kwargs: P.kwargs) -> R: # type: ignore -107 escaped_args: List[Any] = [] -108 escaped_kwargs: Dict[str, Any] = {} -109 for arg in cast(HasIter, args): -110 if not isinstance(arg, EscapedText) and isinstance(arg, str): -111 escaped_args.append(EscapedText(arg)) -112 else: -113 escaped_args.append(arg) -114 arg_k: str -115 arg_v: Any -116 for arg_k, arg_v in cast(HasItems, kwargs).items(): -117 if not isinstance(arg_v, EscapedText) and isinstance(arg_v, str): -118 escaped_kwargs[arg_k] = EscapedText(str(arg_v)) -119 else: -120 escaped_kwargs[arg_k] = arg_v -121 return func(*escaped_args, **escaped_kwargs) # type: ignore -122 -123 return inner -124 +101 Arguments: +102 func -- The function to decorate. +103 +104 Returns: +105 The decorated function. +106 """ +107 +108 @wraps(func) +109 def inner(*args: P.args, **kwargs: P.kwargs) -> R: # type: ignore +110 escaped_args: List[Any] = [] +111 escaped_kwargs: Dict[str, Any] = {} +112 for arg in cast(HasIter, args): +113 if not isinstance(arg, EscapedText) and isinstance(arg, str): +114 escaped_args.append(EscapedText(arg)) +115 else: +116 escaped_args.append(arg) +117 arg_k: str +118 arg_v: Any +119 for arg_k, arg_v in cast(HasItems, kwargs).items(): +120 if not isinstance(arg_v, EscapedText) and isinstance(arg_v, str): +121 escaped_kwargs[arg_k] = EscapedText(str(arg_v)) +122 else: +123 escaped_kwargs[arg_k] = arg_v +124 return func(*escaped_args, **escaped_kwargs) # type: ignore 125 -126class CharClass(Enum): -127 """Enum of character classes in regex. +126 return inner +127 128 -129 Arguments: -130 Enum -- Extends the Enum class. -131 """ -132 -133 DIGIT = "\\d" -134 LETTER = "\\w" -135 UPPERCASE_LETTER = "\\u" -136 LOWERCASE_LETTER = "\\l" -137 WHITESPACE = "\\s" -138 TAB = "\\t" -139 -140 def __str__(self) -> str: -141 """To string method based on Enum value. +129class CharClass(Enum): +130 """Enum of character classes in regex. +131 +132 Arguments: +133 Enum -- Extends the Enum class. +134 """ +135 +136 DIGIT = "\\d" +137 LETTER = "\\w" +138 UPPERCASE_LETTER = "\\u" +139 LOWERCASE_LETTER = "\\l" +140 WHITESPACE = "\\s" +141 TAB = "\\t" 142 -143 Returns: -144 value of Enum -145 """ -146 return self.value -147 -148 -149class SpecialChar(Enum): -150 """Enum of special charaters, shorthand. +143 def __str__(self) -> str: +144 """To string method based on Enum value. +145 +146 Returns: +147 value of Enum +148 """ +149 return self.value +150 151 -152 Arguments: -153 Enum -- Extends the Enum class. -154 """ -155 -156 # does not work / should not be used in [ ] -157 LINEBREAK = "(\\n|(\\r\\n))" -158 START_OF_LINE = "^" -159 END_OF_LINE = "$" -160 TAB = "\t" -161 -162 def __str__(self) -> str: -163 """To string for special chars enum. +152class SpecialChar(Enum): +153 """Enum of special charaters, shorthand. +154 +155 Arguments: +156 Enum -- Extends the Enum class. +157 """ +158 +159 # does not work / should not be used in [ ] +160 LINEBREAK = "(\\n|(\\r\\n))" +161 START_OF_LINE = "^" +162 END_OF_LINE = "$" +163 TAB = "\t" 164 -165 Returns: -166 Return value of enum as string. -167 """ -168 return self.value -169 -170 -171CharClassOrChars: TypeAlias = Union[str, CharClass] -172EscapedCharClassOrSpecial: TypeAlias = Union[str, CharClass, SpecialChar] -173VerbexEscapedCharClassOrSpecial: TypeAlias = Union["Verbex", EscapedCharClassOrSpecial] -174 -175 -176def _poseur_decorator(*poseur: Any) -> Any: -177 """Positional-only arguments runtime checker.""" -178 import functools -179 -180 def caller(func: Callable[P, R]) -> Callable[P, R]: # type: ignore -181 @functools.wraps(func) -182 def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: -183 poseur_args = set(poseur).intersection(kwargs) # type: ignore -184 if poseur_args: -185 raise TypeError( -186 "%s() got some positional-only arguments passed as keyword" -187 " arguments: %r" % (func.__name__, ", ".join(poseur_args)), -188 ) -189 return func(*args, **kwargs) # type: ignore -190 -191 return wrapper -192 -193 return caller -194 +165 def __str__(self) -> str: +166 """To string for special chars enum. +167 +168 Returns: +169 Return value of enum as string. +170 """ +171 return self.value +172 +173 +174CharClassOrChars: TypeAlias = Union[str, CharClass] +175EscapedCharClassOrSpecial: TypeAlias = Union[str, CharClass, SpecialChar] +176VerbexEscapedCharClassOrSpecial: TypeAlias = Union["Verbex", EscapedCharClassOrSpecial] +177 +178 +179def _poseur_decorator(*poseur: Any) -> Any: +180 """Positional-only arguments runtime checker.""" +181 import functools +182 +183 def caller(func: Callable[P, R]) -> Callable[P, R]: # type: ignore +184 @functools.wraps(func) +185 def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: +186 poseur_args = set(poseur).intersection(kwargs) # type: ignore +187 if poseur_args: +188 raise TypeError( +189 "%s() got some positional-only arguments passed as keyword" +190 " arguments: %r" % (func.__name__, ", ".join(poseur_args)), +191 ) +192 return func(*args, **kwargs) # type: ignore +193 +194 return wrapper 195 -196class Verbex: -197 """ -198 VerbalExpressions class. -199 -200 the following methods do not try to match the original js lib! -201 """ +196 return caller +197 +198 +199class Verbex: +200 """ +201 VerbalExpressions class. 202 -203 EMPTY_REGEX_FLAG = re.RegexFlag(0) -204 -205 @re_escape -206 @beartype -207 def __init__(self, modifiers: re.RegexFlag = EMPTY_REGEX_FLAG): -208 """Create a Verbex object; setting any needed flags. -209 -210 Keyword Arguments: -211 modifiers -- Regex modifying flags (default: {re.RegexFlag(0)}) -212 """ -213 # self._parts: List[str] = [text] -214 self._parts: List[str] = [] -215 self._modifiers = modifiers -216 -217 @property -218 def modifiers(self) -> re.RegexFlag: -219 """Return the modifiers for this Verbex object. -220 -221 Returns: -222 The modifiers applied to this object. -223 """ -224 return self._modifiers -225 -226 def __str__(self) -> str: -227 """Return regex string representation.""" -228 return "".join(self._parts) -229 -230 @beartype -231 def _add(self, value: Union[str, List[str]]) -> Verbex: -232 """ -233 Append a transformed value to internal expression to be compiled. -234 -235 As possible, this method should be "private". -236 """ -237 if isinstance(value, list): -238 self._parts.extend(value) -239 else: -240 self._parts.append(value) -241 return self -242 -243 def regex(self) -> Pattern[str]: -244 """Get a regular expression object.""" -245 return re.compile( -246 str(self), -247 self._modifiers, -248 ) -249 -250 # allow VerbexEscapedCharClassOrSpecial -251 -252 @re_escape -253 @beartype -254 def _capture_group_with_name( -255 self, -256 name: str, -257 text: VerbexEscapedCharClassOrSpecial, -258 ) -> Verbex: -259 return self._add(f"(?<{name}>{str(text)})") -260 -261 @re_escape -262 @beartype -263 def _capture_group_without_name( -264 self, -265 text: VerbexEscapedCharClassOrSpecial, -266 ) -> Verbex: -267 return self._add(f"({str(text)})") -268 -269 @re_escape -270 @beartype -271 @_poseur_decorator("self") -272 def capture_group( -273 self, -274 name_or_text: Union[Optional[str], VerbexEscapedCharClassOrSpecial] = None, -275 text: Optional[VerbexEscapedCharClassOrSpecial] = None, -276 ) -> Verbex: -277 """Create a capture group. -278 -279 Name is optional if not specified then the first argument is the text. -280 -281 Keyword Arguments: -282 name_or_text -- The name of the group / text to search for (default: {None}) -283 text -- The text to search for (default: {None}) -284 -285 Raises: -286 ValueError: If name is specified then text must be as well. +203 the following methods do not try to match the original js lib! +204 """ +205 +206 EMPTY_REGEX_FLAG = re.RegexFlag(0) +207 +208 @re_escape +209 @beartype +210 def __init__(self, modifiers: re.RegexFlag = EMPTY_REGEX_FLAG): +211 """Create a Verbex object; setting any needed flags. +212 +213 Keyword Arguments: +214 modifiers -- Regex modifying flags (default: {re.RegexFlag(0)}) +215 """ +216 # self._parts: List[str] = [text] +217 self._parts: List[str] = [] +218 self._modifiers = modifiers +219 +220 @property +221 def modifiers(self) -> re.RegexFlag: +222 """Return the modifiers for this Verbex object. +223 +224 Returns: +225 The modifiers applied to this object. +226 """ +227 return self._modifiers +228 +229 def __str__(self) -> str: +230 """Return regex string representation.""" +231 return "".join(self._parts) +232 +233 @beartype +234 def _add(self, value: Union[str, List[str]]) -> Verbex: +235 """ +236 Append a transformed value to internal expression to be compiled. +237 +238 As possible, this method should be "private". +239 """ +240 if isinstance(value, list): +241 self._parts.extend(value) +242 else: +243 self._parts.append(value) +244 return self +245 +246 def regex(self) -> Pattern[str]: +247 """Get a regular expression object.""" +248 return re.compile( +249 str(self), +250 self._modifiers, +251 ) +252 +253 # allow VerbexEscapedCharClassOrSpecial +254 +255 @re_escape +256 @beartype +257 def _capture_group_with_name( +258 self, +259 name: str, +260 text: VerbexEscapedCharClassOrSpecial, +261 ) -> Verbex: +262 return self._add(f"(?<{name}>{str(text)})") +263 +264 @re_escape +265 @beartype +266 def _capture_group_without_name( +267 self, +268 text: VerbexEscapedCharClassOrSpecial, +269 ) -> Verbex: +270 return self._add(f"({str(text)})") +271 +272 @re_escape +273 @beartype +274 @_poseur_decorator("self") +275 def capture_group( +276 self, +277 name_or_text: Union[Optional[str], VerbexEscapedCharClassOrSpecial] = None, +278 text: Optional[VerbexEscapedCharClassOrSpecial] = None, +279 ) -> Verbex: +280 """Create a capture group. +281 +282 Name is optional if not specified then the first argument is the text. +283 +284 Keyword Arguments: +285 name_or_text -- The name of the group / text to search for (default: {None}) +286 text -- The text to search for (default: {None}) 287 -288 Returns: -289 Verbex with added capture group. -290 """ -291 if name_or_text is not None: -292 if text is None: -293 _text = name_or_text -294 return self._capture_group_without_name(_text) -295 if isinstance(name_or_text, str): -296 return self._capture_group_with_name(name_or_text, text) -297 raise ValueError("text must be specified with optional name") -298 -299 @re_escape -300 @beartype -301 def OR(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: # noqa N802 -302 """`or` is a python keyword so we use `OR` instead. -303 -304 Arguments: -305 text -- Text to find or a Verbex object. +288 Raises: +289 ValueError: If name is specified then text must be as well. +290 +291 Returns: +292 Verbex with added capture group. +293 """ +294 if name_or_text is not None: +295 if text is None: +296 _text = name_or_text +297 return self._capture_group_without_name(_text) +298 if isinstance(name_or_text, str): +299 return self._capture_group_with_name(name_or_text, text) +300 raise ValueError("text must be specified with optional name") +301 +302 @re_escape +303 @beartype +304 def OR(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: # noqa: N802 +305 """`or` is a python keyword so we use `OR` instead. 306 -307 Returns: -308 Modified Verbex object. -309 """ -310 return self._add("|").find(text) -311 -312 @re_escape -313 @beartype -314 def zero_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: -315 """Find the text or Verbex object zero or more times. -316 -317 Arguments: -318 text -- The text / Verbex object to look for. +307 Arguments: +308 text -- Text to find or a Verbex object. +309 +310 Returns: +311 Modified Verbex object. +312 """ +313 return self._add("|").find(text) +314 +315 @re_escape +316 @beartype +317 def zero_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: +318 """Find the text or Verbex object zero or more times. 319 -320 Returns: -321 Modified Verbex object. -322 """ -323 return self._add(f"(?:{str(text)})*") -324 -325 @re_escape -326 @beartype -327 def one_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: -328 """Find the text or Verbex object one or more times. -329 -330 Arguments: -331 text -- The text / Verbex object to look for. +320 Arguments: +321 text -- The text / Verbex object to look for. +322 +323 Returns: +324 Modified Verbex object. +325 """ +326 return self._add(f"(?:{str(text)})*") +327 +328 @re_escape +329 @beartype +330 def one_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: +331 """Find the text or Verbex object one or more times. 332 -333 Returns: -334 Modified Verbex object. -335 """ -336 return self._add(f"(?:{str(text)})+") -337 -338 @re_escape -339 @beartype -340 def n_times( -341 self, -342 text: VerbexEscapedCharClassOrSpecial, -343 n: int, # noqa: VNE001 -344 ) -> Verbex: -345 """Find the text or Verbex object n or more times. -346 -347 Arguments: -348 text -- The text / Verbex object to look for. +333 Arguments: +334 text -- The text / Verbex object to look for. +335 +336 Returns: +337 Modified Verbex object. +338 """ +339 return self._add(f"(?:{str(text)})+") +340 +341 @re_escape +342 @beartype +343 def n_times( +344 self, +345 text: VerbexEscapedCharClassOrSpecial, +346 n: int, # noqa: VNE001 +347 ) -> Verbex: +348 """Find the text or Verbex object n or more times. 349 -350 Returns: -351 Modified Verbex object. -352 """ -353 return self._add(f"(?:{str(text)}){{{n}}}") -354 -355 @re_escape -356 @beartype -357 def n_times_or_more( -358 self, -359 text: VerbexEscapedCharClassOrSpecial, -360 n: int, # noqa: VNE001 -361 ) -> Verbex: -362 """Find the text or Verbex object at least n times. -363 -364 Arguments: -365 text -- The text / Verbex object to look for. +350 Arguments: +351 text -- The text / Verbex object to look for. +352 +353 Returns: +354 Modified Verbex object. +355 """ +356 return self._add(f"(?:{str(text)}){{{n}}}") +357 +358 @re_escape +359 @beartype +360 def n_times_or_more( +361 self, +362 text: VerbexEscapedCharClassOrSpecial, +363 n: int, # noqa: VNE001 +364 ) -> Verbex: +365 """Find the text or Verbex object at least n times. 366 -367 Returns: -368 Modified Verbex object. -369 """ -370 return self._add(f"(?:{str(text)}){{{n},}}") -371 -372 @re_escape -373 @beartype -374 def n_to_m_times( -375 self, -376 text: VerbexEscapedCharClassOrSpecial, -377 n: int, # noqa: VNE001 -378 m: int, # noqa: VNE001 -379 ) -> Verbex: -380 """Find the text or Verbex object between n and m times. -381 -382 Arguments: -383 text -- The text / Verbex object to look for. +367 Arguments: +368 text -- The text / Verbex object to look for. +369 +370 Returns: +371 Modified Verbex object. +372 """ +373 return self._add(f"(?:{str(text)}){{{n},}}") +374 +375 @re_escape +376 @beartype +377 def n_to_m_times( +378 self, +379 text: VerbexEscapedCharClassOrSpecial, +380 n: int, # noqa: VNE001 +381 m: int, # noqa: VNE001 +382 ) -> Verbex: +383 """Find the text or Verbex object between n and m times. 384 -385 Returns: -386 Modified Verbex object. -387 """ -388 return self._add(f"(?:{str(text)}){{{n},{m}}}") -389 -390 @re_escape -391 @beartype -392 def maybe(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: -393 """Possibly find the text / Verbex object. -394 -395 Arguments: -396 text -- The text / Verbex object to possibly find. +385 Arguments: +386 text -- The text / Verbex object to look for. +387 +388 Returns: +389 Modified Verbex object. +390 """ +391 return self._add(f"(?:{str(text)}){{{n},{m}}}") +392 +393 @re_escape +394 @beartype +395 def maybe(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: +396 """Possibly find the text / Verbex object. 397 -398 Returns: -399 Modified Verbex object. -400 """ -401 return self._add(f"(?:{str(text)})?") -402 -403 @re_escape -404 @beartype -405 def find(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: -406 """Find the text or Verbex object. -407 -408 Arguments: -409 text -- The text / Verbex object to look for. +398 Arguments: +399 text -- The text / Verbex object to possibly find. +400 +401 Returns: +402 Modified Verbex object. +403 """ +404 return self._add(f"(?:{str(text)})?") +405 +406 @re_escape +407 @beartype +408 def find(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: +409 """Find the text or Verbex object. 410 -411 Returns: -412 Modified Verbex object. -413 """ -414 return self._add(str(text)) -415 -416 @re_escape -417 @beartype -418 def then(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: -419 """Synonym for find. -420 -421 Arguments: -422 text -- The text / Verbex object to look for. +411 Arguments: +412 text -- The text / Verbex object to look for. +413 +414 Returns: +415 Modified Verbex object. +416 """ +417 return self._add(str(text)) +418 +419 @re_escape +420 @beartype +421 def then(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: +422 """Synonym for find. 423 -424 Returns: -425 Modified Verbex object. -426 """ -427 return self.find(text) -428 -429 @re_escape -430 @beartype -431 def followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: -432 """Match if string is followed by text. -433 -434 Positive lookahead -435 -436 Returns: -437 Modified Verbex object. -438 """ -439 return self._add(f"(?={text})") -440 -441 @re_escape -442 @beartype -443 def not_followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: -444 """Match if string is not followed by text. -445 -446 Negative lookahead -447 -448 Returns: -449 Modified Verbex object. -450 """ -451 return self._add(f"(?!{text})") -452 -453 @re_escape -454 @beartype -455 def preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: -456 """Match if string is not preceded by text. -457 -458 Positive lookbehind -459 -460 Returns: -461 Modified Verbex object. -462 """ -463 return self._add(f"(?<={text})") -464 -465 @re_escape -466 @beartype -467 def not_preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: -468 """Match if string is not preceded by text. -469 -470 Negative Lookbehind -471 -472 Returns: -473 Modified Verbex object. -474 """ -475 return self._add(f"(?<!{text})") -476 -477 # only allow CharclassOrChars -478 -479 @re_escape -480 @beartype -481 def any_of(self, chargroup: CharClassOrChars) -> Verbex: -482 """Find anything in this group of chars or char class. -483 -484 Arguments: -485 text -- The characters to look for. +424 Arguments: +425 text -- The text / Verbex object to look for. +426 +427 Returns: +428 Modified Verbex object. +429 """ +430 return self.find(text) +431 +432 @re_escape +433 @beartype +434 def followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: +435 """Match if string is followed by text. +436 +437 Positive lookahead +438 +439 Returns: +440 Modified Verbex object. +441 """ +442 return self._add(f"(?={text})") +443 +444 @re_escape +445 @beartype +446 def not_followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: +447 """Match if string is not followed by text. +448 +449 Negative lookahead +450 +451 Returns: +452 Modified Verbex object. +453 """ +454 return self._add(f"(?!{text})") +455 +456 @re_escape +457 @beartype +458 def preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: +459 """Match if string is not preceded by text. +460 +461 Positive lookbehind +462 +463 Returns: +464 Modified Verbex object. +465 """ +466 return self._add(f"(?<={text})") +467 +468 @re_escape +469 @beartype +470 def not_preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: +471 """Match if string is not preceded by text. +472 +473 Negative Lookbehind +474 +475 Returns: +476 Modified Verbex object. +477 """ +478 return self._add(f"(?<!{text})") +479 +480 # only allow CharclassOrChars +481 +482 @re_escape +483 @beartype +484 def any_of(self, chargroup: CharClassOrChars) -> Verbex: +485 """Find anything in this group of chars or char class. 486 -487 Returns: -488 Modified Verbex object. -489 """ -490 return self._add(f"(?:[{chargroup}])") -491 -492 @re_escape -493 @beartype -494 def not_any_of(self, text: CharClassOrChars) -> Verbex: -495 """Find anything but this group of chars or char class. -496 -497 Arguments: -498 text -- The characters to not look for. +487 Arguments: +488 text -- The characters to look for. +489 +490 Returns: +491 Modified Verbex object. +492 """ +493 return self._add(f"(?:[{chargroup}])") +494 +495 @re_escape +496 @beartype +497 def not_any_of(self, text: CharClassOrChars) -> Verbex: +498 """Find anything but this group of chars or char class. 499 -500 Returns: -501 Modified Verbex object. -502 """ -503 return self._add(f"(?:[^{text}])") -504 -505 @re_escape -506 def anything_but(self, chargroup: EscapedCharClassOrSpecial) -> Verbex: -507 """Find anything one or more times but this group of chars or char class. -508 -509 Arguments: -510 text -- The characters to not look for. +500 Arguments: +501 text -- The characters to not look for. +502 +503 Returns: +504 Modified Verbex object. +505 """ +506 return self._add(f"(?:[^{text}])") +507 +508 @re_escape +509 def anything_but(self, chargroup: EscapedCharClassOrSpecial) -> Verbex: +510 """Find anything one or more times but this group of chars or char class. 511 -512 Returns: -513 Modified Verbex object. -514 """ -515 return self._add(f"[^{chargroup}]+") -516 -517 # no text input -518 -519 def start_of_line(self) -> Verbex: -520 """Find the start of the line. +512 Arguments: +513 text -- The characters to not look for. +514 +515 Returns: +516 Modified Verbex object. +517 """ +518 return self._add(f"[^{chargroup}]+") +519 +520 # no text input 521 -522 Returns: -523 Modified Verbex object. -524 """ -525 return self.find(SpecialChar.START_OF_LINE) -526 -527 def end_of_line(self) -> Verbex: -528 """Find the end of the line. +522 def start_of_line(self) -> Verbex: +523 """Find the start of the line. +524 +525 Returns: +526 Modified Verbex object. +527 """ +528 return self.find(SpecialChar.START_OF_LINE) 529 -530 Returns: -531 Modified Verbex object. -532 """ -533 return self.find(SpecialChar.END_OF_LINE) -534 -535 def line_break(self) -> Verbex: -536 """Find a line break. +530 def end_of_line(self) -> Verbex: +531 """Find the end of the line. +532 +533 Returns: +534 Modified Verbex object. +535 """ +536 return self.find(SpecialChar.END_OF_LINE) 537 -538 Returns: -539 Modified Verbex object. -540 """ -541 return self.find(SpecialChar.LINEBREAK) -542 -543 def tab(self) -> Verbex: -544 """Find a tab. +538 def line_break(self) -> Verbex: +539 """Find a line break. +540 +541 Returns: +542 Modified Verbex object. +543 """ +544 return self.find(SpecialChar.LINEBREAK) 545 -546 Returns: -547 Modified Verbex object. -548 """ -549 return self.find(SpecialChar.TAB) -550 -551 def anything(self) -> Verbex: -552 """Find anything one or more time. +546 def tab(self) -> Verbex: +547 """Find a tab. +548 +549 Returns: +550 Modified Verbex object. +551 """ +552 return self.find(SpecialChar.TAB) 553 -554 Returns: -555 Modified Verbex object. -556 """ -557 return self._add(".+") -558 -559 def as_few(self) -> Verbex: -560 """Modify previous search to not be greedy. +554 def anything(self) -> Verbex: +555 """Find anything one or more time. +556 +557 Returns: +558 Modified Verbex object. +559 """ +560 return self._add(".+") 561 -562 Returns: -563 Modified Verbex object. -564 """ -565 return self._add("?") -566 -567 @beartype -568 def number_range(self, start: int, end: int) -> Verbex: -569 """Generate a range of numbers. -570 -571 Arguments: -572 start -- Start of the range -573 end -- End of the range -574 -575 Returns: -576 Modified Verbex object. -577 """ -578 return self._add("(?:" + "|".join(str(i) for i in range(start, end + 1)) + ")") -579 -580 @beartype -581 def letter_range(self, start: Char, end: Char) -> Verbex: -582 """Generate a range of letters. -583 -584 Arguments: -585 start -- Start of the range -586 end -- End of the range -587 -588 Returns: -589 Modified Verbex object. -590 """ -591 return self._add(f"[{start}-{end}]") -592 -593 def word(self) -> Verbex: -594 """Find a word on word boundary. +562 def as_few(self) -> Verbex: +563 """Modify previous search to not be greedy. +564 +565 Returns: +566 Modified Verbex object. +567 """ +568 return self._add("?") +569 +570 @beartype +571 def number_range(self, start: int, end: int) -> Verbex: +572 """Generate a range of numbers. +573 +574 Arguments: +575 start -- Start of the range +576 end -- End of the range +577 +578 Returns: +579 Modified Verbex object. +580 """ +581 return self._add("(?:" + "|".join(str(i) for i in range(start, end + 1)) + ")") +582 +583 @beartype +584 def letter_range(self, start: Char, end: Char) -> Verbex: +585 """Generate a range of letters. +586 +587 Arguments: +588 start -- Start of the range +589 end -- End of the range +590 +591 Returns: +592 Modified Verbex object. +593 """ +594 return self._add(f"[{start}-{end}]") 595 -596 Returns: -597 Modified Verbex object. -598 """ -599 return self._add("(\\b\\w+\\b)") -600 -601 # # --------------- modifiers ------------------------ -602 -603 def with_any_case(self) -> Verbex: -604 """Modify Verbex object to be case insensitive. +596 def word(self) -> Verbex: +597 """Find a word on word boundary. +598 +599 Returns: +600 Modified Verbex object. +601 """ +602 return self._add("(\\b\\w+\\b)") +603 +604 # # --------------- modifiers ------------------------ 605 -606 Returns: -607 Modified Verbex object. -608 """ -609 self._modifiers |= re.IGNORECASE -610 return self -611 -612 def search_by_line(self) -> Verbex: -613 """Search each line, ^ and $ match begining and end of line respectively. +606 def with_any_case(self) -> Verbex: +607 """Modify Verbex object to be case insensitive. +608 +609 Returns: +610 Modified Verbex object. +611 """ +612 self._modifiers |= re.IGNORECASE +613 return self 614 -615 Returns: -616 Modified Verbex object. -617 """ -618 self._modifiers |= re.MULTILINE -619 return self -620 -621 def with_ascii(self) -> Verbex: -622 """Match ascii instead of unicode. +615 def search_by_line(self) -> Verbex: +616 """Search each line, ^ and $ match begining and end of line respectively. +617 +618 Returns: +619 Modified Verbex object. +620 """ +621 self._modifiers |= re.MULTILINE +622 return self 623 -624 Returns: -625 Modified Verbex object. -626 """ -627 self._modifiers |= re.ASCII -628 return self -629 -630 -631# left over notes from original version -632# def __getattr__(self, attr): -633# """ any other function will be sent to the regex object """ -634# regex = self.regex() -635# return getattr(regex, attr) -636 -637# def replace(self, string, repl): -638# return self.sub(repl, string) +624 def with_ascii(self) -> Verbex: +625 """Match ascii instead of unicode. +626 +627 Returns: +628 Modified Verbex object. +629 """ +630 self._modifiers |= re.ASCII +631 return self +632 +633 +634# left over notes from original version +635# def __getattr__(self, attr): +636# """ any other function will be sent to the regex object """ +637# regex = self.regex() +638# return getattr(regex, attr) 639 -640 -641if __name__ == "__main__": -642 pass +640# def replace(self, string, repl): +641# return self.sub(repl, string) +642 +643 +644if __name__ == "__main__": +645 pass @@ -913,17 +916,17 @@

View Source -
49@runtime_checkable
-50class HasIter(Protocol):
-51    """Workaround for mypy P.args."""
-52
-53    def __iter__(self) -> Iterator[Any]:
-54        """Object can be iterated.
+            
52@runtime_checkable
+53class HasIter(Protocol):
+54    """Workaround for mypy P.args."""
 55
-56        Yields:
-57            Next object.
-58        """
-59        ...
+56    def __iter__(self) -> Iterator[Any]:
+57        """Object can be iterated.
+58
+59        Yields:
+60            Next object.
+61        """
+62        ...
 
@@ -988,17 +991,17 @@

View Source -
64@runtime_checkable
-65class HasItems(Protocol):
-66    """Workaround for mypy P.kwargs."""
-67
-68    def items(self) -> Tuple[str, Any]:
-69        """Object has items method.
+            
67@runtime_checkable
+68class HasItems(Protocol):
+69    """Workaround for mypy P.kwargs."""
 70
-71        Returns:
-72            The dict of items.
-73        """
-74        ...
+71    def items(self) -> Tuple[str, Any]:
+72        """Object has items method.
+73
+74        Returns:
+75            The dict of items.
+76        """
+77        ...
 
@@ -1060,13 +1063,13 @@

View Source -
68    def items(self) -> Tuple[str, Any]:
-69        """Object has items method.
-70
-71        Returns:
-72            The dict of items.
-73        """
-74        ...
+            
71    def items(self) -> Tuple[str, Any]:
+72        """Object has items method.
+73
+74        Returns:
+75            The dict of items.
+76        """
+77        ...
 
@@ -1091,23 +1094,23 @@

View Source -
77class EscapedText(str):
-78    """Text that has been escaped for regex.
-79
-80    Arguments:
-81        str -- Extend the string class.
-82    """
-83
-84    def __new__(cls, value: str) -> EscapedText:
-85        """Return a escaped regex string.
+            
80class EscapedText(str):
+81    """Text that has been escaped for regex.
+82
+83    Arguments:
+84        str -- Extend the string class.
+85    """
 86
-87        Arguments:
-88            value -- the string to escape
+87    def __new__(cls, value: str) -> EscapedText:
+88        """Return a escaped regex string.
 89
-90        Returns:
-91            _description_
-92        """
-93        return str.__new__(cls, re.escape(value))
+90        Arguments:
+91            value -- the string to escape
+92
+93        Returns:
+94            _description_
+95        """
+96        return str.__new__(cls, re.escape(value))
 
@@ -1128,16 +1131,16 @@

View Source -
84    def __new__(cls, value: str) -> EscapedText:
-85        """Return a escaped regex string.
-86
-87        Arguments:
-88            value -- the string to escape
+            
87    def __new__(cls, value: str) -> EscapedText:
+88        """Return a escaped regex string.
 89
-90        Returns:
-91            _description_
-92        """
-93        return str.__new__(cls, re.escape(value))
+90        Arguments:
+91            value -- the string to escape
+92
+93        Returns:
+94            _description_
+95        """
+96        return str.__new__(cls, re.escape(value))
 
@@ -1221,35 +1224,35 @@

Inherited Members
View Source -
 96def re_escape(func: Callable[P, R]) -> Callable[P, R]:
- 97    """Automatically escape any string parameters as EscapedText.
- 98
- 99    Arguments:
-100        func -- The function to decorate.
+            
 99def re_escape(func: Callable[P, R]) -> Callable[P, R]:
+100    """Automatically escape any string parameters as EscapedText.
 101
-102    Returns:
-103        The decorated function.
-104    """
-105
-106    @wraps(func)
-107    def inner(*args: P.args, **kwargs: P.kwargs) -> R:  # type: ignore
-108        escaped_args: List[Any] = []
-109        escaped_kwargs: Dict[str, Any] = {}
-110        for arg in cast(HasIter, args):
-111            if not isinstance(arg, EscapedText) and isinstance(arg, str):
-112                escaped_args.append(EscapedText(arg))
-113            else:
-114                escaped_args.append(arg)
-115        arg_k: str
-116        arg_v: Any
-117        for arg_k, arg_v in cast(HasItems, kwargs).items():
-118            if not isinstance(arg_v, EscapedText) and isinstance(arg_v, str):
-119                escaped_kwargs[arg_k] = EscapedText(str(arg_v))
-120            else:
-121                escaped_kwargs[arg_k] = arg_v
-122        return func(*escaped_args, **escaped_kwargs)  # type: ignore
-123
-124    return inner
+102    Arguments:
+103        func -- The function to decorate.
+104
+105    Returns:
+106        The decorated function.
+107    """
+108
+109    @wraps(func)
+110    def inner(*args: P.args, **kwargs: P.kwargs) -> R:  # type: ignore
+111        escaped_args: List[Any] = []
+112        escaped_kwargs: Dict[str, Any] = {}
+113        for arg in cast(HasIter, args):
+114            if not isinstance(arg, EscapedText) and isinstance(arg, str):
+115                escaped_args.append(EscapedText(arg))
+116            else:
+117                escaped_args.append(arg)
+118        arg_k: str
+119        arg_v: Any
+120        for arg_k, arg_v in cast(HasItems, kwargs).items():
+121            if not isinstance(arg_v, EscapedText) and isinstance(arg_v, str):
+122                escaped_kwargs[arg_k] = EscapedText(str(arg_v))
+123            else:
+124                escaped_kwargs[arg_k] = arg_v
+125        return func(*escaped_args, **escaped_kwargs)  # type: ignore
+126
+127    return inner
 
@@ -1276,27 +1279,27 @@
Inherited Members
View Source -
127class CharClass(Enum):
-128    """Enum of character classes in regex.
-129
-130    Arguments:
-131        Enum -- Extends the Enum class.
-132    """
-133
-134    DIGIT = "\\d"
-135    LETTER = "\\w"
-136    UPPERCASE_LETTER = "\\u"
-137    LOWERCASE_LETTER = "\\l"
-138    WHITESPACE = "\\s"
-139    TAB = "\\t"
-140
-141    def __str__(self) -> str:
-142        """To string method based on Enum value.
+            
130class CharClass(Enum):
+131    """Enum of character classes in regex.
+132
+133    Arguments:
+134        Enum -- Extends the Enum class.
+135    """
+136
+137    DIGIT = "\\d"
+138    LETTER = "\\w"
+139    UPPERCASE_LETTER = "\\u"
+140    LOWERCASE_LETTER = "\\l"
+141    WHITESPACE = "\\s"
+142    TAB = "\\t"
 143
-144        Returns:
-145            value of Enum
-146        """
-147        return self.value
+144    def __str__(self) -> str:
+145        """To string method based on Enum value.
+146
+147        Returns:
+148            value of Enum
+149        """
+150        return self.value
 
@@ -1390,26 +1393,26 @@
Inherited Members
View Source -
150class SpecialChar(Enum):
-151    """Enum of special charaters, shorthand.
-152
-153    Arguments:
-154        Enum -- Extends the Enum class.
-155    """
-156
-157    # does not work  / should not be used in [ ]
-158    LINEBREAK = "(\\n|(\\r\\n))"
-159    START_OF_LINE = "^"
-160    END_OF_LINE = "$"
-161    TAB = "\t"
-162
-163    def __str__(self) -> str:
-164        """To string for special chars enum.
+            
153class SpecialChar(Enum):
+154    """Enum of special charaters, shorthand.
+155
+156    Arguments:
+157        Enum -- Extends the Enum class.
+158    """
+159
+160    # does not work  / should not be used in [ ]
+161    LINEBREAK = "(\\n|(\\r\\n))"
+162    START_OF_LINE = "^"
+163    END_OF_LINE = "$"
+164    TAB = "\t"
 165
-166        Returns:
-167            Return value of enum as string.
-168        """
-169        return self.value
+166    def __str__(self) -> str:
+167        """To string for special chars enum.
+168
+169        Returns:
+170            Return value of enum as string.
+171        """
+172        return self.value
 
@@ -1513,439 +1516,439 @@
Inherited Members
View Source -
197class Verbex:
-198    """
-199    VerbalExpressions class.
-200
-201    the following methods do not try to match the original js lib!
-202    """
+            
200class Verbex:
+201    """
+202    VerbalExpressions class.
 203
-204    EMPTY_REGEX_FLAG = re.RegexFlag(0)
-205
-206    @re_escape
-207    @beartype
-208    def __init__(self, modifiers: re.RegexFlag = EMPTY_REGEX_FLAG):
-209        """Create a Verbex object; setting any needed flags.
-210
-211        Keyword Arguments:
-212            modifiers -- Regex modifying flags (default: {re.RegexFlag(0)})
-213        """
-214        # self._parts: List[str] = [text]
-215        self._parts: List[str] = []
-216        self._modifiers = modifiers
-217
-218    @property
-219    def modifiers(self) -> re.RegexFlag:
-220        """Return the modifiers for this Verbex object.
-221
-222        Returns:
-223            The modifiers applied to this object.
-224        """
-225        return self._modifiers
-226
-227    def __str__(self) -> str:
-228        """Return regex string representation."""
-229        return "".join(self._parts)
-230
-231    @beartype
-232    def _add(self, value: Union[str, List[str]]) -> Verbex:
-233        """
-234        Append a transformed value to internal expression to be compiled.
-235
-236        As possible, this method should be "private".
-237        """
-238        if isinstance(value, list):
-239            self._parts.extend(value)
-240        else:
-241            self._parts.append(value)
-242        return self
-243
-244    def regex(self) -> Pattern[str]:
-245        """Get a regular expression object."""
-246        return re.compile(
-247            str(self),
-248            self._modifiers,
-249        )
-250
-251    # allow VerbexEscapedCharClassOrSpecial
-252
-253    @re_escape
-254    @beartype
-255    def _capture_group_with_name(
-256        self,
-257        name: str,
-258        text: VerbexEscapedCharClassOrSpecial,
-259    ) -> Verbex:
-260        return self._add(f"(?<{name}>{str(text)})")
-261
-262    @re_escape
-263    @beartype
-264    def _capture_group_without_name(
-265        self,
-266        text: VerbexEscapedCharClassOrSpecial,
-267    ) -> Verbex:
-268        return self._add(f"({str(text)})")
-269
-270    @re_escape
-271    @beartype
-272    @_poseur_decorator("self")
-273    def capture_group(
-274        self,
-275        name_or_text: Union[Optional[str], VerbexEscapedCharClassOrSpecial] = None,
-276        text: Optional[VerbexEscapedCharClassOrSpecial] = None,
-277    ) -> Verbex:
-278        """Create a capture group.
-279
-280        Name is optional if not specified then the first argument is the text.
-281
-282        Keyword Arguments:
-283            name_or_text -- The name of the group / text to search for (default: {None})
-284            text -- The text to search for (default: {None})
-285
-286        Raises:
-287            ValueError: If name is specified then text must be as well.
+204    the following methods do not try to match the original js lib!
+205    """
+206
+207    EMPTY_REGEX_FLAG = re.RegexFlag(0)
+208
+209    @re_escape
+210    @beartype
+211    def __init__(self, modifiers: re.RegexFlag = EMPTY_REGEX_FLAG):
+212        """Create a Verbex object; setting any needed flags.
+213
+214        Keyword Arguments:
+215            modifiers -- Regex modifying flags (default: {re.RegexFlag(0)})
+216        """
+217        # self._parts: List[str] = [text]
+218        self._parts: List[str] = []
+219        self._modifiers = modifiers
+220
+221    @property
+222    def modifiers(self) -> re.RegexFlag:
+223        """Return the modifiers for this Verbex object.
+224
+225        Returns:
+226            The modifiers applied to this object.
+227        """
+228        return self._modifiers
+229
+230    def __str__(self) -> str:
+231        """Return regex string representation."""
+232        return "".join(self._parts)
+233
+234    @beartype
+235    def _add(self, value: Union[str, List[str]]) -> Verbex:
+236        """
+237        Append a transformed value to internal expression to be compiled.
+238
+239        As possible, this method should be "private".
+240        """
+241        if isinstance(value, list):
+242            self._parts.extend(value)
+243        else:
+244            self._parts.append(value)
+245        return self
+246
+247    def regex(self) -> Pattern[str]:
+248        """Get a regular expression object."""
+249        return re.compile(
+250            str(self),
+251            self._modifiers,
+252        )
+253
+254    # allow VerbexEscapedCharClassOrSpecial
+255
+256    @re_escape
+257    @beartype
+258    def _capture_group_with_name(
+259        self,
+260        name: str,
+261        text: VerbexEscapedCharClassOrSpecial,
+262    ) -> Verbex:
+263        return self._add(f"(?<{name}>{str(text)})")
+264
+265    @re_escape
+266    @beartype
+267    def _capture_group_without_name(
+268        self,
+269        text: VerbexEscapedCharClassOrSpecial,
+270    ) -> Verbex:
+271        return self._add(f"({str(text)})")
+272
+273    @re_escape
+274    @beartype
+275    @_poseur_decorator("self")
+276    def capture_group(
+277        self,
+278        name_or_text: Union[Optional[str], VerbexEscapedCharClassOrSpecial] = None,
+279        text: Optional[VerbexEscapedCharClassOrSpecial] = None,
+280    ) -> Verbex:
+281        """Create a capture group.
+282
+283        Name is optional if not specified then the first argument is the text.
+284
+285        Keyword Arguments:
+286            name_or_text -- The name of the group / text to search for (default: {None})
+287            text -- The text to search for (default: {None})
 288
-289        Returns:
-290            Verbex with added capture group.
-291        """
-292        if name_or_text is not None:
-293            if text is None:
-294                _text = name_or_text
-295                return self._capture_group_without_name(_text)
-296            if isinstance(name_or_text, str):
-297                return self._capture_group_with_name(name_or_text, text)
-298        raise ValueError("text must be specified with optional name")
-299
-300    @re_escape
-301    @beartype
-302    def OR(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:  # noqa N802
-303        """`or` is a python keyword so we use `OR` instead.
-304
-305        Arguments:
-306            text -- Text to find or a Verbex object.
+289        Raises:
+290            ValueError: If name is specified then text must be as well.
+291
+292        Returns:
+293            Verbex with added capture group.
+294        """
+295        if name_or_text is not None:
+296            if text is None:
+297                _text = name_or_text
+298                return self._capture_group_without_name(_text)
+299            if isinstance(name_or_text, str):
+300                return self._capture_group_with_name(name_or_text, text)
+301        raise ValueError("text must be specified with optional name")
+302
+303    @re_escape
+304    @beartype
+305    def OR(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:  # noqa: N802
+306        """`or` is a python keyword so we use `OR` instead.
 307
-308        Returns:
-309            Modified Verbex object.
-310        """
-311        return self._add("|").find(text)
-312
-313    @re_escape
-314    @beartype
-315    def zero_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-316        """Find the text or Verbex object zero or more times.
-317
-318        Arguments:
-319            text -- The text / Verbex object to look for.
+308        Arguments:
+309            text -- Text to find or a Verbex object.
+310
+311        Returns:
+312            Modified Verbex object.
+313        """
+314        return self._add("|").find(text)
+315
+316    @re_escape
+317    @beartype
+318    def zero_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+319        """Find the text or Verbex object zero or more times.
 320
-321        Returns:
-322            Modified Verbex object.
-323        """
-324        return self._add(f"(?:{str(text)})*")
-325
-326    @re_escape
-327    @beartype
-328    def one_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-329        """Find the text or Verbex object one or more times.
-330
-331        Arguments:
-332            text -- The text / Verbex object to look for.
+321        Arguments:
+322            text -- The text / Verbex object to look for.
+323
+324        Returns:
+325            Modified Verbex object.
+326        """
+327        return self._add(f"(?:{str(text)})*")
+328
+329    @re_escape
+330    @beartype
+331    def one_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+332        """Find the text or Verbex object one or more times.
 333
-334        Returns:
-335            Modified Verbex object.
-336        """
-337        return self._add(f"(?:{str(text)})+")
-338
-339    @re_escape
-340    @beartype
-341    def n_times(
-342        self,
-343        text: VerbexEscapedCharClassOrSpecial,
-344        n: int,  # noqa: VNE001
-345    ) -> Verbex:
-346        """Find the text or Verbex object n or more times.
-347
-348        Arguments:
-349            text -- The text / Verbex object to look for.
+334        Arguments:
+335            text -- The text / Verbex object to look for.
+336
+337        Returns:
+338            Modified Verbex object.
+339        """
+340        return self._add(f"(?:{str(text)})+")
+341
+342    @re_escape
+343    @beartype
+344    def n_times(
+345        self,
+346        text: VerbexEscapedCharClassOrSpecial,
+347        n: int,  # noqa: VNE001
+348    ) -> Verbex:
+349        """Find the text or Verbex object n or more times.
 350
-351        Returns:
-352            Modified Verbex object.
-353        """
-354        return self._add(f"(?:{str(text)}){{{n}}}")
-355
-356    @re_escape
-357    @beartype
-358    def n_times_or_more(
-359        self,
-360        text: VerbexEscapedCharClassOrSpecial,
-361        n: int,  # noqa: VNE001
-362    ) -> Verbex:
-363        """Find the text or Verbex object at least n times.
-364
-365        Arguments:
-366            text -- The text / Verbex object to look for.
+351        Arguments:
+352            text -- The text / Verbex object to look for.
+353
+354        Returns:
+355            Modified Verbex object.
+356        """
+357        return self._add(f"(?:{str(text)}){{{n}}}")
+358
+359    @re_escape
+360    @beartype
+361    def n_times_or_more(
+362        self,
+363        text: VerbexEscapedCharClassOrSpecial,
+364        n: int,  # noqa: VNE001
+365    ) -> Verbex:
+366        """Find the text or Verbex object at least n times.
 367
-368        Returns:
-369            Modified Verbex object.
-370        """
-371        return self._add(f"(?:{str(text)}){{{n},}}")
-372
-373    @re_escape
-374    @beartype
-375    def n_to_m_times(
-376        self,
-377        text: VerbexEscapedCharClassOrSpecial,
-378        n: int,  # noqa: VNE001
-379        m: int,  # noqa: VNE001
-380    ) -> Verbex:
-381        """Find the text or Verbex object between n and m times.
-382
-383        Arguments:
-384            text -- The text / Verbex object to look for.
+368        Arguments:
+369            text -- The text / Verbex object to look for.
+370
+371        Returns:
+372            Modified Verbex object.
+373        """
+374        return self._add(f"(?:{str(text)}){{{n},}}")
+375
+376    @re_escape
+377    @beartype
+378    def n_to_m_times(
+379        self,
+380        text: VerbexEscapedCharClassOrSpecial,
+381        n: int,  # noqa: VNE001
+382        m: int,  # noqa: VNE001
+383    ) -> Verbex:
+384        """Find the text or Verbex object between n and m times.
 385
-386        Returns:
-387            Modified Verbex object.
-388        """
-389        return self._add(f"(?:{str(text)}){{{n},{m}}}")
-390
-391    @re_escape
-392    @beartype
-393    def maybe(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-394        """Possibly find the text / Verbex object.
-395
-396        Arguments:
-397            text -- The text / Verbex object to possibly find.
+386        Arguments:
+387            text -- The text / Verbex object to look for.
+388
+389        Returns:
+390            Modified Verbex object.
+391        """
+392        return self._add(f"(?:{str(text)}){{{n},{m}}}")
+393
+394    @re_escape
+395    @beartype
+396    def maybe(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+397        """Possibly find the text / Verbex object.
 398
-399        Returns:
-400            Modified Verbex object.
-401        """
-402        return self._add(f"(?:{str(text)})?")
-403
-404    @re_escape
-405    @beartype
-406    def find(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-407        """Find the text or Verbex object.
-408
-409        Arguments:
-410            text -- The text / Verbex object to look for.
+399        Arguments:
+400            text -- The text / Verbex object to possibly find.
+401
+402        Returns:
+403            Modified Verbex object.
+404        """
+405        return self._add(f"(?:{str(text)})?")
+406
+407    @re_escape
+408    @beartype
+409    def find(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+410        """Find the text or Verbex object.
 411
-412        Returns:
-413            Modified Verbex object.
-414        """
-415        return self._add(str(text))
-416
-417    @re_escape
-418    @beartype
-419    def then(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-420        """Synonym for find.
-421
-422        Arguments:
-423            text -- The text / Verbex object to look for.
+412        Arguments:
+413            text -- The text / Verbex object to look for.
+414
+415        Returns:
+416            Modified Verbex object.
+417        """
+418        return self._add(str(text))
+419
+420    @re_escape
+421    @beartype
+422    def then(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+423        """Synonym for find.
 424
-425        Returns:
-426            Modified Verbex object.
-427        """
-428        return self.find(text)
-429
-430    @re_escape
-431    @beartype
-432    def followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-433        """Match if string is followed by text.
-434
-435        Positive lookahead
-436
-437        Returns:
-438            Modified Verbex object.
-439        """
-440        return self._add(f"(?={text})")
-441
-442    @re_escape
-443    @beartype
-444    def not_followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-445        """Match if string is not followed by text.
-446
-447        Negative lookahead
-448
-449        Returns:
-450            Modified Verbex object.
-451        """
-452        return self._add(f"(?!{text})")
-453
-454    @re_escape
-455    @beartype
-456    def preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-457        """Match if string is not preceded by text.
-458
-459        Positive lookbehind
-460
-461        Returns:
-462            Modified Verbex object.
-463        """
-464        return self._add(f"(?<={text})")
-465
-466    @re_escape
-467    @beartype
-468    def not_preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-469        """Match if string is not preceded by text.
-470
-471        Negative Lookbehind
-472
-473        Returns:
-474            Modified Verbex object.
-475        """
-476        return self._add(f"(?<!{text})")
-477
-478    # only allow CharclassOrChars
-479
-480    @re_escape
-481    @beartype
-482    def any_of(self, chargroup: CharClassOrChars) -> Verbex:
-483        """Find anything in this group of chars or char class.
-484
-485        Arguments:
-486            text -- The characters to look for.
+425        Arguments:
+426            text -- The text / Verbex object to look for.
+427
+428        Returns:
+429            Modified Verbex object.
+430        """
+431        return self.find(text)
+432
+433    @re_escape
+434    @beartype
+435    def followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+436        """Match if string is followed by text.
+437
+438        Positive lookahead
+439
+440        Returns:
+441            Modified Verbex object.
+442        """
+443        return self._add(f"(?={text})")
+444
+445    @re_escape
+446    @beartype
+447    def not_followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+448        """Match if string is not followed by text.
+449
+450        Negative lookahead
+451
+452        Returns:
+453            Modified Verbex object.
+454        """
+455        return self._add(f"(?!{text})")
+456
+457    @re_escape
+458    @beartype
+459    def preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+460        """Match if string is not preceded by text.
+461
+462        Positive lookbehind
+463
+464        Returns:
+465            Modified Verbex object.
+466        """
+467        return self._add(f"(?<={text})")
+468
+469    @re_escape
+470    @beartype
+471    def not_preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+472        """Match if string is not preceded by text.
+473
+474        Negative Lookbehind
+475
+476        Returns:
+477            Modified Verbex object.
+478        """
+479        return self._add(f"(?<!{text})")
+480
+481    # only allow CharclassOrChars
+482
+483    @re_escape
+484    @beartype
+485    def any_of(self, chargroup: CharClassOrChars) -> Verbex:
+486        """Find anything in this group of chars or char class.
 487
-488        Returns:
-489            Modified Verbex object.
-490        """
-491        return self._add(f"(?:[{chargroup}])")
-492
-493    @re_escape
-494    @beartype
-495    def not_any_of(self, text: CharClassOrChars) -> Verbex:
-496        """Find anything but this group of chars or char class.
-497
-498        Arguments:
-499            text -- The characters to not look for.
+488        Arguments:
+489            text -- The characters to look for.
+490
+491        Returns:
+492            Modified Verbex object.
+493        """
+494        return self._add(f"(?:[{chargroup}])")
+495
+496    @re_escape
+497    @beartype
+498    def not_any_of(self, text: CharClassOrChars) -> Verbex:
+499        """Find anything but this group of chars or char class.
 500
-501        Returns:
-502            Modified Verbex object.
-503        """
-504        return self._add(f"(?:[^{text}])")
-505
-506    @re_escape
-507    def anything_but(self, chargroup: EscapedCharClassOrSpecial) -> Verbex:
-508        """Find anything one or more times but this group of chars or char class.
-509
-510        Arguments:
-511            text -- The characters to not look for.
+501        Arguments:
+502            text -- The characters to not look for.
+503
+504        Returns:
+505            Modified Verbex object.
+506        """
+507        return self._add(f"(?:[^{text}])")
+508
+509    @re_escape
+510    def anything_but(self, chargroup: EscapedCharClassOrSpecial) -> Verbex:
+511        """Find anything one or more times but this group of chars or char class.
 512
-513        Returns:
-514            Modified Verbex object.
-515        """
-516        return self._add(f"[^{chargroup}]+")
-517
-518    # no text input
-519
-520    def start_of_line(self) -> Verbex:
-521        """Find the start of the line.
+513        Arguments:
+514            text -- The characters to not look for.
+515
+516        Returns:
+517            Modified Verbex object.
+518        """
+519        return self._add(f"[^{chargroup}]+")
+520
+521    # no text input
 522
-523        Returns:
-524            Modified Verbex object.
-525        """
-526        return self.find(SpecialChar.START_OF_LINE)
-527
-528    def end_of_line(self) -> Verbex:
-529        """Find the end of the line.
+523    def start_of_line(self) -> Verbex:
+524        """Find the start of the line.
+525
+526        Returns:
+527            Modified Verbex object.
+528        """
+529        return self.find(SpecialChar.START_OF_LINE)
 530
-531        Returns:
-532            Modified Verbex object.
-533        """
-534        return self.find(SpecialChar.END_OF_LINE)
-535
-536    def line_break(self) -> Verbex:
-537        """Find a line break.
+531    def end_of_line(self) -> Verbex:
+532        """Find the end of the line.
+533
+534        Returns:
+535            Modified Verbex object.
+536        """
+537        return self.find(SpecialChar.END_OF_LINE)
 538
-539        Returns:
-540            Modified Verbex object.
-541        """
-542        return self.find(SpecialChar.LINEBREAK)
-543
-544    def tab(self) -> Verbex:
-545        """Find a tab.
+539    def line_break(self) -> Verbex:
+540        """Find a line break.
+541
+542        Returns:
+543            Modified Verbex object.
+544        """
+545        return self.find(SpecialChar.LINEBREAK)
 546
-547        Returns:
-548            Modified Verbex object.
-549        """
-550        return self.find(SpecialChar.TAB)
-551
-552    def anything(self) -> Verbex:
-553        """Find anything one or more time.
+547    def tab(self) -> Verbex:
+548        """Find a tab.
+549
+550        Returns:
+551            Modified Verbex object.
+552        """
+553        return self.find(SpecialChar.TAB)
 554
-555        Returns:
-556            Modified Verbex object.
-557        """
-558        return self._add(".+")
-559
-560    def as_few(self) -> Verbex:
-561        """Modify previous search to not be greedy.
+555    def anything(self) -> Verbex:
+556        """Find anything one or more time.
+557
+558        Returns:
+559            Modified Verbex object.
+560        """
+561        return self._add(".+")
 562
-563        Returns:
-564            Modified Verbex object.
-565        """
-566        return self._add("?")
-567
-568    @beartype
-569    def number_range(self, start: int, end: int) -> Verbex:
-570        """Generate a range of numbers.
-571
-572        Arguments:
-573            start -- Start of the range
-574            end -- End of the range
-575
-576        Returns:
-577            Modified Verbex object.
-578        """
-579        return self._add("(?:" + "|".join(str(i) for i in range(start, end + 1)) + ")")
-580
-581    @beartype
-582    def letter_range(self, start: Char, end: Char) -> Verbex:
-583        """Generate a range of letters.
-584
-585        Arguments:
-586            start -- Start of the range
-587            end -- End of the range
-588
-589        Returns:
-590            Modified Verbex object.
-591        """
-592        return self._add(f"[{start}-{end}]")
-593
-594    def word(self) -> Verbex:
-595        """Find a word on word boundary.
+563    def as_few(self) -> Verbex:
+564        """Modify previous search to not be greedy.
+565
+566        Returns:
+567            Modified Verbex object.
+568        """
+569        return self._add("?")
+570
+571    @beartype
+572    def number_range(self, start: int, end: int) -> Verbex:
+573        """Generate a range of numbers.
+574
+575        Arguments:
+576            start -- Start of the range
+577            end -- End of the range
+578
+579        Returns:
+580            Modified Verbex object.
+581        """
+582        return self._add("(?:" + "|".join(str(i) for i in range(start, end + 1)) + ")")
+583
+584    @beartype
+585    def letter_range(self, start: Char, end: Char) -> Verbex:
+586        """Generate a range of letters.
+587
+588        Arguments:
+589            start -- Start of the range
+590            end -- End of the range
+591
+592        Returns:
+593            Modified Verbex object.
+594        """
+595        return self._add(f"[{start}-{end}]")
 596
-597        Returns:
-598            Modified Verbex object.
-599        """
-600        return self._add("(\\b\\w+\\b)")
-601
-602    # # --------------- modifiers ------------------------
-603
-604    def with_any_case(self) -> Verbex:
-605        """Modify Verbex object to be case insensitive.
+597    def word(self) -> Verbex:
+598        """Find a word on word boundary.
+599
+600        Returns:
+601            Modified Verbex object.
+602        """
+603        return self._add("(\\b\\w+\\b)")
+604
+605    # # --------------- modifiers ------------------------
 606
-607        Returns:
-608            Modified Verbex object.
-609        """
-610        self._modifiers |= re.IGNORECASE
-611        return self
-612
-613    def search_by_line(self) -> Verbex:
-614        """Search each line, ^ and $ match begining and end of line respectively.
+607    def with_any_case(self) -> Verbex:
+608        """Modify Verbex object to be case insensitive.
+609
+610        Returns:
+611            Modified Verbex object.
+612        """
+613        self._modifiers |= re.IGNORECASE
+614        return self
 615
-616        Returns:
-617            Modified Verbex object.
-618        """
-619        self._modifiers |= re.MULTILINE
-620        return self
-621
-622    def with_ascii(self) -> Verbex:
-623        """Match ascii instead of unicode.
+616    def search_by_line(self) -> Verbex:
+617        """Search each line, ^ and $ match begining and end of line respectively.
+618
+619        Returns:
+620            Modified Verbex object.
+621        """
+622        self._modifiers |= re.MULTILINE
+623        return self
 624
-625        Returns:
-626            Modified Verbex object.
-627        """
-628        self._modifiers |= re.ASCII
-629        return self
+625    def with_ascii(self) -> Verbex:
+626        """Match ascii instead of unicode.
+627
+628        Returns:
+629            Modified Verbex object.
+630        """
+631        self._modifiers |= re.ASCII
+632        return self
 
@@ -1967,17 +1970,17 @@
Inherited Members
View Source -
206    @re_escape
-207    @beartype
-208    def __init__(self, modifiers: re.RegexFlag = EMPTY_REGEX_FLAG):
-209        """Create a Verbex object; setting any needed flags.
-210
-211        Keyword Arguments:
-212            modifiers -- Regex modifying flags (default: {re.RegexFlag(0)})
-213        """
-214        # self._parts: List[str] = [text]
-215        self._parts: List[str] = []
-216        self._modifiers = modifiers
+            
209    @re_escape
+210    @beartype
+211    def __init__(self, modifiers: re.RegexFlag = EMPTY_REGEX_FLAG):
+212        """Create a Verbex object; setting any needed flags.
+213
+214        Keyword Arguments:
+215            modifiers -- Regex modifying flags (default: {re.RegexFlag(0)})
+216        """
+217        # self._parts: List[str] = [text]
+218        self._parts: List[str] = []
+219        self._modifiers = modifiers
 
@@ -2025,12 +2028,12 @@
Inherited Members
View Source -
244    def regex(self) -> Pattern[str]:
-245        """Get a regular expression object."""
-246        return re.compile(
-247            str(self),
-248            self._modifiers,
-249        )
+            
247    def regex(self) -> Pattern[str]:
+248        """Get a regular expression object."""
+249        return re.compile(
+250            str(self),
+251            self._modifiers,
+252        )
 
@@ -2056,35 +2059,35 @@
Inherited Members
View Source -
270    @re_escape
-271    @beartype
-272    @_poseur_decorator("self")
-273    def capture_group(
-274        self,
-275        name_or_text: Union[Optional[str], VerbexEscapedCharClassOrSpecial] = None,
-276        text: Optional[VerbexEscapedCharClassOrSpecial] = None,
-277    ) -> Verbex:
-278        """Create a capture group.
-279
-280        Name is optional if not specified then the first argument is the text.
-281
-282        Keyword Arguments:
-283            name_or_text -- The name of the group / text to search for (default: {None})
-284            text -- The text to search for (default: {None})
-285
-286        Raises:
-287            ValueError: If name is specified then text must be as well.
+            
273    @re_escape
+274    @beartype
+275    @_poseur_decorator("self")
+276    def capture_group(
+277        self,
+278        name_or_text: Union[Optional[str], VerbexEscapedCharClassOrSpecial] = None,
+279        text: Optional[VerbexEscapedCharClassOrSpecial] = None,
+280    ) -> Verbex:
+281        """Create a capture group.
+282
+283        Name is optional if not specified then the first argument is the text.
+284
+285        Keyword Arguments:
+286            name_or_text -- The name of the group / text to search for (default: {None})
+287            text -- The text to search for (default: {None})
 288
-289        Returns:
-290            Verbex with added capture group.
-291        """
-292        if name_or_text is not None:
-293            if text is None:
-294                _text = name_or_text
-295                return self._capture_group_without_name(_text)
-296            if isinstance(name_or_text, str):
-297                return self._capture_group_with_name(name_or_text, text)
-298        raise ValueError("text must be specified with optional name")
+289        Raises:
+290            ValueError: If name is specified then text must be as well.
+291
+292        Returns:
+293            Verbex with added capture group.
+294        """
+295        if name_or_text is not None:
+296            if text is None:
+297                _text = name_or_text
+298                return self._capture_group_without_name(_text)
+299            if isinstance(name_or_text, str):
+300                return self._capture_group_with_name(name_or_text, text)
+301        raise ValueError("text must be specified with optional name")
 
@@ -2121,18 +2124,18 @@
Inherited Members
View Source -
300    @re_escape
-301    @beartype
-302    def OR(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:  # noqa N802
-303        """`or` is a python keyword so we use `OR` instead.
-304
-305        Arguments:
-306            text -- Text to find or a Verbex object.
+            
303    @re_escape
+304    @beartype
+305    def OR(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:  # noqa: N802
+306        """`or` is a python keyword so we use `OR` instead.
 307
-308        Returns:
-309            Modified Verbex object.
-310        """
-311        return self._add("|").find(text)
+308        Arguments:
+309            text -- Text to find or a Verbex object.
+310
+311        Returns:
+312            Modified Verbex object.
+313        """
+314        return self._add("|").find(text)
 
@@ -2163,18 +2166,18 @@
Inherited Members
View Source -
313    @re_escape
-314    @beartype
-315    def zero_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-316        """Find the text or Verbex object zero or more times.
-317
-318        Arguments:
-319            text -- The text / Verbex object to look for.
+            
316    @re_escape
+317    @beartype
+318    def zero_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+319        """Find the text or Verbex object zero or more times.
 320
-321        Returns:
-322            Modified Verbex object.
-323        """
-324        return self._add(f"(?:{str(text)})*")
+321        Arguments:
+322            text -- The text / Verbex object to look for.
+323
+324        Returns:
+325            Modified Verbex object.
+326        """
+327        return self._add(f"(?:{str(text)})*")
 
@@ -2205,18 +2208,18 @@
Inherited Members
View Source -
326    @re_escape
-327    @beartype
-328    def one_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-329        """Find the text or Verbex object one or more times.
-330
-331        Arguments:
-332            text -- The text / Verbex object to look for.
+            
329    @re_escape
+330    @beartype
+331    def one_or_more(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+332        """Find the text or Verbex object one or more times.
 333
-334        Returns:
-335            Modified Verbex object.
-336        """
-337        return self._add(f"(?:{str(text)})+")
+334        Arguments:
+335            text -- The text / Verbex object to look for.
+336
+337        Returns:
+338            Modified Verbex object.
+339        """
+340        return self._add(f"(?:{str(text)})+")
 
@@ -2248,22 +2251,22 @@
Inherited Members
View Source -
339    @re_escape
-340    @beartype
-341    def n_times(
-342        self,
-343        text: VerbexEscapedCharClassOrSpecial,
-344        n: int,  # noqa: VNE001
-345    ) -> Verbex:
-346        """Find the text or Verbex object n or more times.
-347
-348        Arguments:
-349            text -- The text / Verbex object to look for.
+            
342    @re_escape
+343    @beartype
+344    def n_times(
+345        self,
+346        text: VerbexEscapedCharClassOrSpecial,
+347        n: int,  # noqa: VNE001
+348    ) -> Verbex:
+349        """Find the text or Verbex object n or more times.
 350
-351        Returns:
-352            Modified Verbex object.
-353        """
-354        return self._add(f"(?:{str(text)}){{{n}}}")
+351        Arguments:
+352            text -- The text / Verbex object to look for.
+353
+354        Returns:
+355            Modified Verbex object.
+356        """
+357        return self._add(f"(?:{str(text)}){{{n}}}")
 
@@ -2295,22 +2298,22 @@
Inherited Members
View Source -
356    @re_escape
-357    @beartype
-358    def n_times_or_more(
-359        self,
-360        text: VerbexEscapedCharClassOrSpecial,
-361        n: int,  # noqa: VNE001
-362    ) -> Verbex:
-363        """Find the text or Verbex object at least n times.
-364
-365        Arguments:
-366            text -- The text / Verbex object to look for.
+            
359    @re_escape
+360    @beartype
+361    def n_times_or_more(
+362        self,
+363        text: VerbexEscapedCharClassOrSpecial,
+364        n: int,  # noqa: VNE001
+365    ) -> Verbex:
+366        """Find the text or Verbex object at least n times.
 367
-368        Returns:
-369            Modified Verbex object.
-370        """
-371        return self._add(f"(?:{str(text)}){{{n},}}")
+368        Arguments:
+369            text -- The text / Verbex object to look for.
+370
+371        Returns:
+372            Modified Verbex object.
+373        """
+374        return self._add(f"(?:{str(text)}){{{n},}}")
 
@@ -2343,23 +2346,23 @@
Inherited Members
View Source -
373    @re_escape
-374    @beartype
-375    def n_to_m_times(
-376        self,
-377        text: VerbexEscapedCharClassOrSpecial,
-378        n: int,  # noqa: VNE001
-379        m: int,  # noqa: VNE001
-380    ) -> Verbex:
-381        """Find the text or Verbex object between n and m times.
-382
-383        Arguments:
-384            text -- The text / Verbex object to look for.
+            
376    @re_escape
+377    @beartype
+378    def n_to_m_times(
+379        self,
+380        text: VerbexEscapedCharClassOrSpecial,
+381        n: int,  # noqa: VNE001
+382        m: int,  # noqa: VNE001
+383    ) -> Verbex:
+384        """Find the text or Verbex object between n and m times.
 385
-386        Returns:
-387            Modified Verbex object.
-388        """
-389        return self._add(f"(?:{str(text)}){{{n},{m}}}")
+386        Arguments:
+387            text -- The text / Verbex object to look for.
+388
+389        Returns:
+390            Modified Verbex object.
+391        """
+392        return self._add(f"(?:{str(text)}){{{n},{m}}}")
 
@@ -2390,18 +2393,18 @@
Inherited Members
View Source -
391    @re_escape
-392    @beartype
-393    def maybe(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-394        """Possibly find the text / Verbex object.
-395
-396        Arguments:
-397            text -- The text / Verbex object to possibly find.
+            
394    @re_escape
+395    @beartype
+396    def maybe(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+397        """Possibly find the text / Verbex object.
 398
-399        Returns:
-400            Modified Verbex object.
-401        """
-402        return self._add(f"(?:{str(text)})?")
+399        Arguments:
+400            text -- The text / Verbex object to possibly find.
+401
+402        Returns:
+403            Modified Verbex object.
+404        """
+405        return self._add(f"(?:{str(text)})?")
 
@@ -2432,18 +2435,18 @@
Inherited Members
View Source -
404    @re_escape
-405    @beartype
-406    def find(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-407        """Find the text or Verbex object.
-408
-409        Arguments:
-410            text -- The text / Verbex object to look for.
+            
407    @re_escape
+408    @beartype
+409    def find(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+410        """Find the text or Verbex object.
 411
-412        Returns:
-413            Modified Verbex object.
-414        """
-415        return self._add(str(text))
+412        Arguments:
+413            text -- The text / Verbex object to look for.
+414
+415        Returns:
+416            Modified Verbex object.
+417        """
+418        return self._add(str(text))
 
@@ -2474,18 +2477,18 @@
Inherited Members
View Source -
417    @re_escape
-418    @beartype
-419    def then(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-420        """Synonym for find.
-421
-422        Arguments:
-423            text -- The text / Verbex object to look for.
+            
420    @re_escape
+421    @beartype
+422    def then(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+423        """Synonym for find.
 424
-425        Returns:
-426            Modified Verbex object.
-427        """
-428        return self.find(text)
+425        Arguments:
+426            text -- The text / Verbex object to look for.
+427
+428        Returns:
+429            Modified Verbex object.
+430        """
+431        return self.find(text)
 
@@ -2516,17 +2519,17 @@
Inherited Members
View Source -
430    @re_escape
-431    @beartype
-432    def followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-433        """Match if string is followed by text.
-434
-435        Positive lookahead
-436
-437        Returns:
-438            Modified Verbex object.
-439        """
-440        return self._add(f"(?={text})")
+            
433    @re_escape
+434    @beartype
+435    def followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+436        """Match if string is followed by text.
+437
+438        Positive lookahead
+439
+440        Returns:
+441            Modified Verbex object.
+442        """
+443        return self._add(f"(?={text})")
 
@@ -2556,17 +2559,17 @@
Inherited Members
View Source -
442    @re_escape
-443    @beartype
-444    def not_followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-445        """Match if string is not followed by text.
-446
-447        Negative lookahead
-448
-449        Returns:
-450            Modified Verbex object.
-451        """
-452        return self._add(f"(?!{text})")
+            
445    @re_escape
+446    @beartype
+447    def not_followed_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+448        """Match if string is not followed by text.
+449
+450        Negative lookahead
+451
+452        Returns:
+453            Modified Verbex object.
+454        """
+455        return self._add(f"(?!{text})")
 
@@ -2596,17 +2599,17 @@
Inherited Members
View Source -
454    @re_escape
-455    @beartype
-456    def preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-457        """Match if string is not preceded by text.
-458
-459        Positive lookbehind
-460
-461        Returns:
-462            Modified Verbex object.
-463        """
-464        return self._add(f"(?<={text})")
+            
457    @re_escape
+458    @beartype
+459    def preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+460        """Match if string is not preceded by text.
+461
+462        Positive lookbehind
+463
+464        Returns:
+465            Modified Verbex object.
+466        """
+467        return self._add(f"(?<={text})")
 
@@ -2636,17 +2639,17 @@
Inherited Members
View Source -
466    @re_escape
-467    @beartype
-468    def not_preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
-469        """Match if string is not preceded by text.
-470
-471        Negative Lookbehind
-472
-473        Returns:
-474            Modified Verbex object.
-475        """
-476        return self._add(f"(?<!{text})")
+            
469    @re_escape
+470    @beartype
+471    def not_preceded_by(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex:
+472        """Match if string is not preceded by text.
+473
+474        Negative Lookbehind
+475
+476        Returns:
+477            Modified Verbex object.
+478        """
+479        return self._add(f"(?<!{text})")
 
@@ -2676,18 +2679,18 @@
Inherited Members
View Source -
480    @re_escape
-481    @beartype
-482    def any_of(self, chargroup: CharClassOrChars) -> Verbex:
-483        """Find anything in this group of chars or char class.
-484
-485        Arguments:
-486            text -- The characters to look for.
+            
483    @re_escape
+484    @beartype
+485    def any_of(self, chargroup: CharClassOrChars) -> Verbex:
+486        """Find anything in this group of chars or char class.
 487
-488        Returns:
-489            Modified Verbex object.
-490        """
-491        return self._add(f"(?:[{chargroup}])")
+488        Arguments:
+489            text -- The characters to look for.
+490
+491        Returns:
+492            Modified Verbex object.
+493        """
+494        return self._add(f"(?:[{chargroup}])")
 
@@ -2718,18 +2721,18 @@
Inherited Members
View Source -
493    @re_escape
-494    @beartype
-495    def not_any_of(self, text: CharClassOrChars) -> Verbex:
-496        """Find anything but this group of chars or char class.
-497
-498        Arguments:
-499            text -- The characters to not look for.
+            
496    @re_escape
+497    @beartype
+498    def not_any_of(self, text: CharClassOrChars) -> Verbex:
+499        """Find anything but this group of chars or char class.
 500
-501        Returns:
-502            Modified Verbex object.
-503        """
-504        return self._add(f"(?:[^{text}])")
+501        Arguments:
+502            text -- The characters to not look for.
+503
+504        Returns:
+505            Modified Verbex object.
+506        """
+507        return self._add(f"(?:[^{text}])")
 
@@ -2759,17 +2762,17 @@
Inherited Members
View Source -
506    @re_escape
-507    def anything_but(self, chargroup: EscapedCharClassOrSpecial) -> Verbex:
-508        """Find anything one or more times but this group of chars or char class.
-509
-510        Arguments:
-511            text -- The characters to not look for.
+            
509    @re_escape
+510    def anything_but(self, chargroup: EscapedCharClassOrSpecial) -> Verbex:
+511        """Find anything one or more times but this group of chars or char class.
 512
-513        Returns:
-514            Modified Verbex object.
-515        """
-516        return self._add(f"[^{chargroup}]+")
+513        Arguments:
+514            text -- The characters to not look for.
+515
+516        Returns:
+517            Modified Verbex object.
+518        """
+519        return self._add(f"[^{chargroup}]+")
 
@@ -2795,13 +2798,13 @@
Inherited Members
View Source -
520    def start_of_line(self) -> Verbex:
-521        """Find the start of the line.
-522
-523        Returns:
-524            Modified Verbex object.
-525        """
-526        return self.find(SpecialChar.START_OF_LINE)
+            
523    def start_of_line(self) -> Verbex:
+524        """Find the start of the line.
+525
+526        Returns:
+527            Modified Verbex object.
+528        """
+529        return self.find(SpecialChar.START_OF_LINE)
 
@@ -2824,13 +2827,13 @@
Inherited Members
View Source -
528    def end_of_line(self) -> Verbex:
-529        """Find the end of the line.
-530
-531        Returns:
-532            Modified Verbex object.
-533        """
-534        return self.find(SpecialChar.END_OF_LINE)
+            
531    def end_of_line(self) -> Verbex:
+532        """Find the end of the line.
+533
+534        Returns:
+535            Modified Verbex object.
+536        """
+537        return self.find(SpecialChar.END_OF_LINE)
 
@@ -2853,13 +2856,13 @@
Inherited Members
View Source -
536    def line_break(self) -> Verbex:
-537        """Find a line break.
-538
-539        Returns:
-540            Modified Verbex object.
-541        """
-542        return self.find(SpecialChar.LINEBREAK)
+            
539    def line_break(self) -> Verbex:
+540        """Find a line break.
+541
+542        Returns:
+543            Modified Verbex object.
+544        """
+545        return self.find(SpecialChar.LINEBREAK)
 
@@ -2882,13 +2885,13 @@
Inherited Members
View Source -
544    def tab(self) -> Verbex:
-545        """Find a tab.
-546
-547        Returns:
-548            Modified Verbex object.
-549        """
-550        return self.find(SpecialChar.TAB)
+            
547    def tab(self) -> Verbex:
+548        """Find a tab.
+549
+550        Returns:
+551            Modified Verbex object.
+552        """
+553        return self.find(SpecialChar.TAB)
 
@@ -2911,13 +2914,13 @@
Inherited Members
View Source -
552    def anything(self) -> Verbex:
-553        """Find anything one or more time.
-554
-555        Returns:
-556            Modified Verbex object.
-557        """
-558        return self._add(".+")
+            
555    def anything(self) -> Verbex:
+556        """Find anything one or more time.
+557
+558        Returns:
+559            Modified Verbex object.
+560        """
+561        return self._add(".+")
 
@@ -2940,13 +2943,13 @@
Inherited Members
View Source -
560    def as_few(self) -> Verbex:
-561        """Modify previous search to not be greedy.
-562
-563        Returns:
-564            Modified Verbex object.
-565        """
-566        return self._add("?")
+            
563    def as_few(self) -> Verbex:
+564        """Modify previous search to not be greedy.
+565
+566        Returns:
+567            Modified Verbex object.
+568        """
+569        return self._add("?")
 
@@ -2970,18 +2973,18 @@
Inherited Members
View Source -
568    @beartype
-569    def number_range(self, start: int, end: int) -> Verbex:
-570        """Generate a range of numbers.
-571
-572        Arguments:
-573            start -- Start of the range
-574            end -- End of the range
-575
-576        Returns:
-577            Modified Verbex object.
-578        """
-579        return self._add("(?:" + "|".join(str(i) for i in range(start, end + 1)) + ")")
+            
571    @beartype
+572    def number_range(self, start: int, end: int) -> Verbex:
+573        """Generate a range of numbers.
+574
+575        Arguments:
+576            start -- Start of the range
+577            end -- End of the range
+578
+579        Returns:
+580            Modified Verbex object.
+581        """
+582        return self._add("(?:" + "|".join(str(i) for i in range(start, end + 1)) + ")")
 
@@ -3013,18 +3016,18 @@
Inherited Members
View Source -
581    @beartype
-582    def letter_range(self, start: Char, end: Char) -> Verbex:
-583        """Generate a range of letters.
-584
-585        Arguments:
-586            start -- Start of the range
-587            end -- End of the range
-588
-589        Returns:
-590            Modified Verbex object.
-591        """
-592        return self._add(f"[{start}-{end}]")
+            
584    @beartype
+585    def letter_range(self, start: Char, end: Char) -> Verbex:
+586        """Generate a range of letters.
+587
+588        Arguments:
+589            start -- Start of the range
+590            end -- End of the range
+591
+592        Returns:
+593            Modified Verbex object.
+594        """
+595        return self._add(f"[{start}-{end}]")
 
@@ -3051,13 +3054,13 @@
Inherited Members
View Source -
594    def word(self) -> Verbex:
-595        """Find a word on word boundary.
-596
-597        Returns:
-598            Modified Verbex object.
-599        """
-600        return self._add("(\\b\\w+\\b)")
+            
597    def word(self) -> Verbex:
+598        """Find a word on word boundary.
+599
+600        Returns:
+601            Modified Verbex object.
+602        """
+603        return self._add("(\\b\\w+\\b)")
 
@@ -3080,14 +3083,14 @@
Inherited Members
View Source -
604    def with_any_case(self) -> Verbex:
-605        """Modify Verbex object to be case insensitive.
-606
-607        Returns:
-608            Modified Verbex object.
-609        """
-610        self._modifiers |= re.IGNORECASE
-611        return self
+            
607    def with_any_case(self) -> Verbex:
+608        """Modify Verbex object to be case insensitive.
+609
+610        Returns:
+611            Modified Verbex object.
+612        """
+613        self._modifiers |= re.IGNORECASE
+614        return self
 
@@ -3110,14 +3113,14 @@
Inherited Members
View Source -
613    def search_by_line(self) -> Verbex:
-614        """Search each line, ^ and $ match begining and end of line respectively.
-615
-616        Returns:
-617            Modified Verbex object.
-618        """
-619        self._modifiers |= re.MULTILINE
-620        return self
+            
616    def search_by_line(self) -> Verbex:
+617        """Search each line, ^ and $ match begining and end of line respectively.
+618
+619        Returns:
+620            Modified Verbex object.
+621        """
+622        self._modifiers |= re.MULTILINE
+623        return self
 
@@ -3140,14 +3143,14 @@
Inherited Members
View Source -
622    def with_ascii(self) -> Verbex:
-623        """Match ascii instead of unicode.
-624
-625        Returns:
-626            Modified Verbex object.
-627        """
-628        self._modifiers |= re.ASCII
-629        return self
+            
625    def with_ascii(self) -> Verbex:
+626        """Match ascii instead of unicode.
+627
+628        Returns:
+629            Modified Verbex object.
+630        """
+631        self._modifiers |= re.ASCII
+632        return self
 
diff --git a/verbex/verbex.py b/verbex/verbex.py index d47fd4d..1a2d9ac 100644 --- a/verbex/verbex.py +++ b/verbex/verbex.py @@ -16,7 +16,10 @@ except ImportError: from typing_extensions import TypeAlias, Protocol, Annotated, ParamSpec, runtime_checkable # type: ignore # <--- if Python < 3.9.0 # noqa E501 -from typing import Pattern, TypeVar +from typing import TYPE_CHECKING, Pattern, TypeVar + +if TYPE_CHECKING: + from typing import Protocol # noqa: F811 from beartype import beartype # type: ignore from beartype.typing import ( # type: ignore @@ -40,8 +43,8 @@ def _string_len_is_1(text: object) -> bool: Char = Annotated[str, Is[_string_len_is_1]] -P = ParamSpec("P") # noqa VNE001 -R = TypeVar("R") # noqa VNE001 +P = ParamSpec("P") # noqa: VNE001 +R = TypeVar("R") # noqa: VNE001 # work around for bug https://github.com/python/mypy/issues/12660 @@ -299,7 +302,7 @@ def capture_group( @re_escape @beartype - def OR(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: # noqa N802 + def OR(self, text: VerbexEscapedCharClassOrSpecial) -> Verbex: # noqa: N802 """`or` is a python keyword so we use `OR` instead. Arguments: