Skip to content

Commit

Permalink
💥 remove prefixed and suffixed
Browse files Browse the repository at this point in the history
  • Loading branch information
RF-Tar-Railt committed Sep 23, 2023
1 parent 4e531fc commit 2e422d9
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 192 deletions.
1 change: 1 addition & 0 deletions nepattern/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from .base import HEX_COLOR as HEX_COLOR
from .base import INTEGER as INTEGER
from .base import IP as IP
from .base import IterMode as IterMode
from .base import LIST as LIST
from .base import MappingPattern as MappingPattern
from .base import NONE as NONE
Expand Down
164 changes: 38 additions & 126 deletions nepattern/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

from enum import Enum
from datetime import datetime
from pathlib import Path
import re
Expand All @@ -17,11 +18,10 @@
Union,
cast,
final,
overload,
overload, Generic,
)

from tarina import DateParser, Empty, lang
from typing_extensions import Self, Unpack, TypeVarTuple

from .core import BasePattern, MatchMode, ResultFlag, ValidateResult
from .exception import MatchFailed
Expand All @@ -31,7 +31,6 @@
TDefault = TypeVar("TDefault")
_T = TypeVar("_T")
_T1 = TypeVar("_T1")
Ts = TypeVarTuple("Ts")


class DirectPattern(BasePattern[TOrigin, TOrigin]):
Expand All @@ -43,16 +42,6 @@ def __init__(self, target: TOrigin, alias: str | None = None):
self.target = target
super().__init__(mode=MatchMode.KEEP, origin=type(target), alias=alias or str(target))

def prefixed(self):
if isinstance(self.target, str):
return BasePattern(self.target, MatchMode.REGEX_MATCH, alias=self.alias).prefixed()
return self

def suffixed(self):
if isinstance(self.target, str):
return BasePattern(self.target, MatchMode.REGEX_MATCH, alias=self.alias).suffixed()
return self

def match(self, input_: Any):
if input_ != self.target:
raise MatchFailed(
Expand Down Expand Up @@ -107,12 +96,6 @@ def match(self, input_: Any):
)
return input_

def prefixed(self):
return self

def suffixed(self):
return self

@overload
def validate(self, input_: TOrigin) -> ValidateResult[TOrigin, Literal[ResultFlag.VALID]]:
...
Expand Down Expand Up @@ -213,37 +196,28 @@ def _(cls, *types: type[_T1]) -> UnionPattern[_T1]:
def __calc_repr__(self):
return "|".join(repr(a) for a in (*self.for_validate, *self.for_equal))

def prefixed(self) -> Self:
from .main import parser

return UnionPattern(
[pat.prefixed() for pat in self.for_validate]
+ [parser(eq).prefixed() if isinstance(eq, str) else eq for eq in self.for_equal], # type: ignore
)

def suffixed(self) -> Self:
from .main import parser

return UnionPattern(
[pat.suffixed() for pat in self.for_validate]
+ [parser(eq).suffixed() if isinstance(eq, str) else eq for eq in self.for_equal], # type: ignore
)

def __or__(self, other: BasePattern[Any, _T1]) -> UnionPattern[Union[_T, _T1]]:
return UnionPattern([*self.base, other]) # type: ignore

TSeq = TypeVar("TSeq", list, tuple, set)
#TIterMode = TypeVar("TIterMode", bound=Literal["pre", "suf", "all"])

class IterMode(str, Enum):
PRE = "pre"
SUF = "suf"
ALL = "all"

class SequencePattern(BasePattern[TSeq, Union[str, TSeq]]):
TIterMode = TypeVar("TIterMode", bound=IterMode)

class SequencePattern(BasePattern[TSeq, Union[str, TSeq]], Generic[TSeq, TIterMode]):
"""匹配列表或者元组或者集合"""

base: BasePattern
_mode: Literal["pre", "suf", "all"]
itermode: TIterMode

def __init__(self, form: type[TSeq], base: BasePattern):
def __init__(self, form: type[TSeq], base: BasePattern, mode: TIterMode = IterMode.ALL):
self.base = base
self._mode = "all"
self.itermode = mode
if form is list:
super().__init__(r"\[(.+?)\]", MatchMode.REGEX_CONVERT, form, alias=f"list[{base}]")
elif form is tuple:
Expand All @@ -265,44 +239,44 @@ def match(self, text: Any):
fail.append((_max, MatchFailed(f"{s} is not matched with {self.base}")))

if (
(self._mode == "all" and fail)
or (self._mode == "pre" and fail and fail[0][0] == 0)
or (self._mode == "suf" and fail and fail[-1][0] == _max)
(self.itermode == IterMode.ALL and fail)
or (self.itermode == IterMode.PRE and fail and fail[0][0] == 0)
or (self.itermode == IterMode.SUF and fail and fail[-1][0] == _max)
):
raise fail[0][1]
if self._mode == "pre" and fail:
if self.itermode == IterMode.PRE and fail:
return self.origin(i[1] for i in success if i[0] < fail[0][0])
if self._mode == "suf" and fail:
if self.itermode == IterMode.SUF and fail:
return self.origin(i[1] for i in success if i[0] > fail[-1][0])
return self.origin(i[1] for i in success)

def __calc_repr__(self):
return f"{self.origin.__name__}[{self.base}]"

def prefixed(self) -> Self:
self._mode = "pre"
return super().prefixed()

def suffixed(self) -> Self:
self._mode = "suf"
return super().suffixed()


TKey = TypeVar("TKey")
TVal = TypeVar("TVal")


class MappingPattern(BasePattern[Dict[TKey, TVal], Union[str, Dict[TKey, TVal]]]):
class MappingPattern(
BasePattern[Dict[TKey, TVal], Union[str, Dict[TKey, TVal]]],
Generic[TKey, TVal, TIterMode],
):
"""匹配字典或者映射表"""

key: BasePattern[TKey, Any]
value: BasePattern[TVal, Any]
_mode: Literal["pre", "suf", "all"]
itermode: TIterMode


def __init__(self, arg_key: BasePattern[TKey, Any], arg_value: BasePattern[TVal, Any]):
def __init__(
self,
arg_key: BasePattern[TKey, Any],
arg_value: BasePattern[TVal, Any],
mode: TIterMode = IterMode.ALL
):
self.key = arg_key
self.value = arg_value
self._mode = "all"
self.itermode = mode
super().__init__(
r"\{(.+?)\}",
MatchMode.REGEX_CONVERT,
Expand All @@ -311,8 +285,8 @@ def __init__(self, arg_key: BasePattern[TKey, Any], arg_value: BasePattern[TVal,
)
self.converter = lambda _, x: x[1]

def match(self, text: Any):
_res = self._MATCHES[MatchMode.REGEX_CONVERT](self, text) # type: ignore
def match(self, input_: str | dict):
_res = self._MATCHES[MatchMode.REGEX_CONVERT](self, input_) # type: ignore
success: list[tuple[int, Any, Any]] = []
fail: list[tuple[int, MatchFailed]] = []
_max = 0
Expand All @@ -336,28 +310,20 @@ def _generator_items(res: str | dict):
)
)
if (
(self._mode == "all" and fail)
or (self._mode == "pre" and fail and fail[0][0] == 0)
or (self._mode == "suf" and fail and fail[-1][0] == _max)
(self.itermode == IterMode.ALL and fail)
or (self.itermode == IterMode.PRE and fail and fail[0][0] == 0)
or (self.itermode == IterMode.SUF and fail and fail[-1][0] == _max)
):
raise fail[0][1]
if self._mode == "pre" and fail:
if self.itermode == IterMode.PRE and fail:
return {i[1]: i[2] for i in success if i[0] < fail[0][0]}
if self._mode == "suf" and fail:
if self.itermode == IterMode.SUF and fail:
return {i[1]: i[2] for i in success if i[0] > fail[-1][0]}
return {i[1]: i[2] for i in success}

def __calc_repr__(self):
return f"dict[{self.key.origin.__name__}, {self.value}]"

def prefixed(self) -> Self:
self._mode = "pre"
return super().prefixed()

def suffixed(self) -> Self:
self._mode = "suf"
return super().suffixed()


_TCase = TypeVar("_TCase")
_TSwtich = TypeVar("_TSwtich")
Expand Down Expand Up @@ -515,15 +481,6 @@ def match(self, input_: Union[str, int]) -> int:
lang.require("nepattern", "content_error").format(target=input_, expected="int")
) from e

def prefixed(self):
return BasePattern(
r"(\-?\d+)", MatchMode.REGEX_CONVERT, int, lambda _, x: int(x[1]), "int"
).prefixed()

def suffixed(self):
return BasePattern(
r"(\-?\d+)", MatchMode.REGEX_CONVERT, int, lambda _, x: int(x[1]), "int"
).suffixed()


INTEGER = IntPattern()
Expand Down Expand Up @@ -551,15 +508,6 @@ def match(self, input_: Union[str, float, int]) -> float:
lang.require("nepattern", "content_error").format(target=input_, expected="float")
) from e

def prefixed(self): # pragma: no cover
return BasePattern(
r"(\-?\d+\.?\d*)", MatchMode.REGEX_CONVERT, float, lambda _, x: float(x[1]), "float"
).prefixed()

def suffixed(self): # pragma: no cover
return BasePattern(
r"(\-?\d+\.?\d*)", MatchMode.REGEX_CONVERT, float, lambda _, x: float(x[1]), "float"
).suffixed()


FLOAT = FloatPattern()
Expand Down Expand Up @@ -588,23 +536,6 @@ def match(self, input_: Union[str, float]) -> float:
lang.require("nepattern", "content_error").format(target=input_, expected="int | float")
) from e

def prefixed(self): # pragma: no cover
return BasePattern(
r"(\-?\d+(?P<float>\.\d*)?)",
MatchMode.REGEX_CONVERT,
Union[int, float],
lambda _, x: float(x[1]) if x["float"] else int(x[1]),
"number",
).prefixed()

def suffixed(self): # pragma: no cover
return BasePattern(
r"(\-?\d+(?P<float>\.\d*)?)",
MatchMode.REGEX_CONVERT,
Union[int, float],
lambda _, x: float(x[1]) if x["float"] else int(x[1]),
"number",
).suffixed()


NUMBER = NumberPattern()
Expand All @@ -631,15 +562,6 @@ def match(self, input_: Union[str, bool]) -> bool:
return self._BOOL[input_]
raise MatchFailed(lang.require("nepattern", "content_error").format(target=input_, expected="bool"))

def prefixed(self): # pragma: no cover
return BasePattern(
r"(?i:True|False)", MatchMode.REGEX_CONVERT, bool, lambda _, x: x[0].lower() == "true", "bool"
).prefixed()

def suffixed(self): # pragma: no cover
return BasePattern(
r"(?i:True|False)", MatchMode.REGEX_CONVERT, bool, lambda _, x: x[0].lower() == "true", "bool"
).suffixed()


BOOLEAN = BoolPattern()
Expand Down Expand Up @@ -687,16 +609,6 @@ def match(self, input_: str) -> int:
lang.require("nepattern", "content_error").format(target=input_, expected="hex")
) from e

def prefixed(self): # pragma: no cover
return BasePattern(
r"((?:0x)?[0-9a-fA-F]+)", MatchMode.REGEX_CONVERT, int, lambda _, x: int(x[1], 16), "hex"
).prefixed()

def suffixed(self): # pragma: no cover
return BasePattern(
r"((?:0x)?[0-9a-fA-F]+)", MatchMode.REGEX_CONVERT, int, lambda _, x: int(x[1], 16), "hex"
).suffixed()


HEX = HexPattern()
"""匹配16进制数的表达式"""
Expand Down
14 changes: 0 additions & 14 deletions nepattern/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,20 +340,6 @@ def to(content: Any):
res = parser(content, "allow")
return res if isinstance(res, BasePattern) else parser(Any)

def prefixed(self):
"""让表达式能在某些场景下实现前缀匹配; 返回自身的拷贝"""
cp_self = deepcopy(self)
if self.mode in (MatchMode.REGEX_MATCH, MatchMode.REGEX_CONVERT):
cp_self.regex_pattern = re.compile(f"^{self.pattern}")
return cp_self # pragma: no cover

def suffixed(self):
"""让表达式能在某些场景下实现后缀匹配; 返回自身的拷贝"""
cp_self = deepcopy(self)
if self.mode in (MatchMode.REGEX_MATCH, MatchMode.REGEX_CONVERT):
cp_self.regex_pattern = re.compile(f"{self.pattern}$")
return cp_self # pragma: no cover

def validate(self, input_: Any, default: TDefault | Empty = Empty) -> ValidateResult[TOrigin | TDefault, ResultFlag]: # type: ignore
"""
对传入的值进行正向验证,返回可能的匹配与转化结果。
Expand Down
2 changes: 0 additions & 2 deletions nepattern/core.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,6 @@ class BasePattern(Generic[TOrigin, TInput]):
def to(content: Any) -> BasePattern:
"""便捷的使用 type_parser 的方法"""
...
def prefixed(self) -> Self: ...
def suffixed(self) -> Self: ...
@overload
def validate(self, input_: TInput) -> ValidateResult[TOrigin, Literal[ResultFlag.VALID]]: ...
@overload
Expand Down

0 comments on commit 2e422d9

Please sign in to comment.