Skip to content

Commit

Permalink
✨ prefixed & suffixed
Browse files Browse the repository at this point in the history
  • Loading branch information
RF-Tar-Railt committed Oct 14, 2024
1 parent e2abfa4 commit 6dd516e
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 28 deletions.
3 changes: 1 addition & 2 deletions nepattern/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ class RegexPattern(_RegexPattern[Match[str]]):

def __init__(self, pattern: str | TPattern, alias: str | None = None):
super().__init__(pattern, Match[str], alias=alias or "regex[:group]")
self.regex_pattern = re.compile(pattern)

def match(self, input_: Any) -> Match[str]:
if not isinstance(input_, str):
Expand All @@ -104,7 +103,7 @@ def match(self, input_: Any) -> Match[str]:
type=input_.__class__, target=input_, expected="str"
)
)
if mat := self.regex_pattern.match(input_):
if mat := (re.match(self.pattern, input_) or re.search(self.pattern, input_)):
return mat
raise MatchFailed(
lang.require("nepattern", "error.content").format(target=input_, expected=self.pattern)
Expand Down
38 changes: 30 additions & 8 deletions nepattern/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ def regex_match(pattern: str | TPattern, alias: str | None = None):

@pat.convert
def _(self, x: str):
mat = re.match(pattern, x)
mat = re.match(self.pattern, x) or re.search(self.pattern, x)
if not mat:
raise MatchFailed(
lang.require("nepattern", "error.content").format(target=x, expected=pattern)
lang.require("nepattern", "error.content").format(target=x, expected=self.pattern)
)
return x
return mat[0]

return pat

Expand All @@ -88,10 +88,10 @@ def regex_convert(
def _(self, x):
if isinstance(x, origin):
return x
mat = re.match(pattern, x)
mat = re.match(self.pattern, x) or re.search(self.pattern, x)
if not mat:
raise MatchFailed(
lang.require("nepattern", "error.content").format(target=x, expected=pattern)
lang.require("nepattern", "error.content").format(target=x, expected=self.pattern)
)
return fn(mat)

Expand All @@ -100,10 +100,10 @@ def _(self, x):

@pat.convert
def _(self, x: str):
mat = re.match(pattern, x)
mat = re.match(self.pattern, x) or re.search(self.pattern, x)
if not mat:
raise MatchFailed(
lang.require("nepattern", "error.content").format(target=x, expected=pattern)
lang.require("nepattern", "error.content").format(target=x, expected=self.pattern)
)
return fn(mat)

Expand Down Expand Up @@ -213,4 +213,26 @@ def __eq__(self, other):
class _RegexPattern(Pattern[T]):
def __init__(self, pattern: str | TPattern, origin: type[T], alias: str | None = None):
super().__init__(origin, alias)
self.pattern = pattern
_pat = pattern if isinstance(pattern, str) else pattern.pattern
if _pat.startswith("^") or _pat.endswith("$"):
raise ValueError(lang.require("nepattern", "error.pattern_head_or_tail").format(target=pattern))
if isinstance(pattern, str):
self.pattern = f"^{pattern}$"
else:
self.pattern = re.compile(f"^{pattern.pattern}$", pattern.flags)

def prefixed(self):
new = self.copy()
if isinstance(self.pattern, str):
new.pattern = self.pattern[:-1]
else: # pragma: no cover
new.pattern = re.compile(self.pattern.pattern[:-1], self.pattern.flags)
return new

def suffixed(self):
new = self.copy()
if isinstance(self.pattern, str):
new.pattern = self.pattern[1:]
else: # pragma: no cover
new.pattern = re.compile(self.pattern.pattern[1:], self.pattern.flags)
return new
5 changes: 5 additions & 0 deletions nepattern/i18n/.lang.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
"title": "type",
"description": "value of lang item type 'type'",
"type": "string"
},
"pattern_head_or_tail": {
"title": "pattern_head_or_tail",
"description": "value of lang item type 'pattern_head_or_tail'",
"type": "string"
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion nepattern/i18n/.template.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"subtype": "error",
"types": [
"content",
"type"
"type",
"pattern_head_or_tail"
]
}
]
Expand Down
3 changes: 2 additions & 1 deletion nepattern/i18n/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"parse_reject": "validate {target} failed",
"error": {
"content": "parameter {target} is incorrect; expected {expected}",
"type": "type {type} of parameter {target} is incorrect; expected {expected}"
"type": "type {type} of parameter {target} is incorrect; expected {expected}",
"pattern_head_or_tail": "The head or tail of regular expression {target} is not allowed to use '^' or '$'"
}
}
}
3 changes: 2 additions & 1 deletion nepattern/i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"nepattern": {
"error": {
"content": "参数 {target!r} 不正确, 其应该符合 {expected!r}",
"type": "参数 {target!r} 的类型 {type} 不正确, 其应该是 {expected!r}"
"type": "参数 {target!r} 的类型 {type} 不正确, 其应该是 {expected!r}",
"pattern_head_or_tail": "不允许正则表达式 {target} 头尾部分使用 '^' 或 '$'"
},
"parse_reject": "{target} 校验失败"
}
Expand Down
38 changes: 23 additions & 15 deletions test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from typing import Union

import pytest

from nepattern import *


Expand Down Expand Up @@ -92,10 +94,8 @@ def test_result():
res2 = NUMBER.execute([])
assert res2.error()
assert not res2.success
try:
with pytest.raises(RuntimeError):
res2.value()
except RuntimeError as e:
print(e)


def test_pattern_of():
Expand Down Expand Up @@ -128,11 +128,27 @@ def test_pattern_keep():

def test_pattern_regex():
"""测试 Pattern 的正则匹配模式, 仅正则匹配"""
import re

pat3 = Pattern.regex_match("abc[A-Z]+123")
assert pat3.execute("abcABC123").value() == "abcABC123"
assert pat3.execute("abcAbc123").failed
print(pat3)

with pytest.raises(ValueError):
Pattern.regex_match("^abc[A-Z]+123")

pat3_1 = Pattern.regex_match(re.compile(r"abc[A-Z]+123"))
assert pat3_1.execute("abcABC123").value() == "abcABC123"

pat3_2 = Pattern.regex_match("abc").prefixed()
assert pat3_2.execute("abc123").value() == "abc"
assert pat3_2.execute("123abc").failed

pat3_3 = Pattern.regex_match("abc").suffixed()
assert pat3_3.execute("123abc").value() == "abc"
assert pat3_3.execute("abc123").failed


def test_pattern_regex_convert():
"""测试 Pattern 的正则转换模式, 正则匹配成功后再进行类型转换"""
Expand Down Expand Up @@ -245,10 +261,8 @@ def my_func(x: int) -> str:

assert parser(complex, extra="ignore") == ANY

try:
with pytest.raises(TypeError):
parser(complex, extra="reject")
except TypeError as e:
print(e)

pat11_4 = parser(Annotated[int, lambda x: x < 10])
assert pat11_4.execute(11).failed
Expand Down Expand Up @@ -389,15 +403,11 @@ def test_patterns():
assert not local_patterns().get("b")
reset_local_patterns()

try:
with pytest.raises(ValueError):
create_local_patterns("$temp")
except ValueError as e:
print(e)

try:
with pytest.raises(ValueError):
switch_local_patterns("$temp")
except ValueError as e:
print(e)


def test_rawstr():
Expand All @@ -414,10 +424,8 @@ def test_direct():
assert pat20_1.execute(123).value() == 123
assert pat20_1.execute("123").failed
assert pat20_1.match(123) == 123
try:
with pytest.raises(MatchFailed):
pat20_1.match("123")
except MatchFailed as e:
print(e)
pat21 = DirectTypePattern(int)
assert pat21.execute(123).value() == 123
assert pat21.execute("123").failed
Expand Down

0 comments on commit 6dd516e

Please sign in to comment.