NEPattern
NEPattern
是 Arclet Project
下的负责类型转换、类型验证的模块.
NEPattern
旨在提供一种简单的方式, 使得开发者可以在不了解正则表达式的情况下, 也能够轻松地进行类型转换与类型验证.
- 通过传入的
converter
和validator
等实现了高效的类型转化与类型验证功能 - 提供了多种预置的实例, 例如常见的
INT
FLOAT
BOOL
等 - 提供了良好的
typing
支持, 使得开发者可以传入大多数typing
模块中的类型:
from nepattern import type_parser
from typing import List
pat = type_parser(List[int])
assert pat.validate([1, 2, 3]).success
2
3
4
5
NEPattern
引入了Patterns
与create_local_patterns
等函数, 使得开发者可以自由的控制当前环境下的Pattern
实例
from nepattern import BasePattern
pat = BasePattern.of(int)
assert pat.validate(13).success
assert not 13.0 >> pat
2
3
4
5
安装
pdm add "nepattern<1.0"
poetry add "nepattern<1.0"
pip install --upgrade "nepattern<1.0"
构造
一般而言,我们通过 nepattern.BasePattern
来构造一个 NEPattern
实例。
from nepattern import BasePattern, MatchMode
pat = BasePattern(mode=MatchMode.TYPE_CONVERT, origin=int, accept=str, convert=lambda _, x: int(x))
assert pat.validate("42").success
2
3
4
5
可以发现,我们通过 BasePattern
的 mode
参数来指定匹配模式。事实上,这里有五种匹配模式:
KEEP
:保持原样,不进行任何转换REGEX_MATCH
:使用正则表达式进行匹配REGEX_CONVERT
:使用正则表达式匹配并进行转换TYPE_CONVERT
:传入值直接进行转换VALUE_OPERATE
:传入值进行操作
对于每种模型,BasePattern
的构造参数会有所不同:
BasePattern(
origin, # 目标类型
alias, # 别名
accepts, # 接受的类型
addition_accepts, # 以其他 BasePattern 作为接受类型
previous, # 类型不匹配时的前置处理
validators, # 验证方法
)
2
3
4
5
6
7
8
BasePattern(
pattern, # 正则表达式
alias, # 别名
previous, # 类型不匹配时的前置处理
validators, # 验证方法
)
2
3
4
5
6
BasePattern(
pattern, # 正则表达式
origin, # 目标类型
alias, # 别名
converter, # 转换方法
previous, # 类型不匹配时的前置处理
validators, # 验证方法
)
2
3
4
5
6
7
8
BasePattern(
origin, # 目标类型
alias, # 别名
converter, # 转换方法
accepts, # 接受的类型
addition_accepts, # 以其他 BasePattern 作为接受类型
previous, # 类型不匹配时的前置处理
validators, # 验证方法
)
2
3
4
5
6
7
8
9
BasePattern(
origin, # 目标类型
alias, # 别名
converter, # 转换方法
previous, # 类型不匹配时的前置处理
validators, # 验证方法
)
2
3
4
5
6
7
on
和 of
方法
BasePattern.of
可以快捷创建一个只允许指定类的实例通过的 pattern
pat = BasePattern.of(int)
assert pat.validate(123).value() == 123
assert pat.validate("abc").failed
2
3
而 BasePattern.on
可以快捷创建一个只允许指定对象通过的 pattern
pat = BasePattern.on(123)
assert pat.validate(123).value() == 123
assert pat.validate(124).failed
2
3
converter
具体而言,converter
参数需要一个函数,其接受两个参数,分别为 BasePattern
实例自身和传入的值,并返回合法的值。该值在不同的模式下有不同的含义:
REGEX_CONVERT
模式下,传入值将是re.Match
对象,converter
函数需要返回类型转换后的值TYPE_CONVERT
模式下,传入值将是原始值,converter
函数需要返回类型转换后的值VALUE_OPERATE
模式下,传入值将是原始值,converter
函数需要返回修改后的值
previous
具体而言,previous
需要另一个匹配模式仅为 TYPE_CONVERT
或 VALUE_OPERATE
的 BasePattern
实例,将原来的值传入该实例进行处理,用返回值替换原来的输入值。
例如,若我们希望在 REGEX_MATCH
模式下,当传入值不是字符串时,将其转换为字符串再进行匹配,我们可以这样写:
from nepattern import BasePattern, MatchMode
pat = BasePattern(
"\d+",
mode=MatchMode.REGEX_MATCH,
previous=BasePattern(mode=MatchMode.TYPE_CONVERT, origin=str, convert=lambda _, x: str(x))
)
2
3
4
5
6
7
validators
validators
参数接受一个函数列表,每个函数接受一个参数,即传入的值,返回一个布尔值,表示是否通过验证。
匹配模式
KEEP
KEEP
模式下,BasePattern
不会对传入的值进行任何转换,只会进行类型验证
- 若没有指定
accepts
或addition_accepts
,则该模式下任意类型都可以通过(即不进行任何操作) - 若指定了
accepts
或addition_accepts
,则只有指定的类型可以通过
from nepattern import BasePattern, MatchMode
pat = BasePattern(mode=MatchMode.KEEP, accept=str)
assert pat.validate("42").success
assert pat.validate(42).failed
2
3
4
5
REGEX_MATCH
REGEX_MATCH
模式下,BasePattern
只接受符合正则表达式的字符串,返回的结果也为字符串
from nepattern import BasePattern, MatchMode
pat = BasePattern(mode=MatchMode.REGEX_MATCH, pattern=r"\d+")
assert pat.validate("42").success
assert pat.validate("abc").failed
2
3
4
5
在该模式下,即使正则表达式内声明了捕获组,BasePattern 的返回值也只会是整个字符串。
REGEX_CONVERT
REGEX_CONVERT
模式下,BasePattern
需要使用正则表达式验证传入的字符串,并通过 converter
方法进行转换
from nepattern import BasePattern, MatchMode
pat = BasePattern(mode=MatchMode.REGEX_CONVERT, pattern=r"\d+", origin=int, convert=lambda _, x: int(x[0]))
assert pat.validate("42").result() == 42
assert pat.validate("abc").failed
2
3
4
5
由于涉及到类型转换,因此 当输入类型不是字符串,但符合 origin
时,将直接作为结果返回
assert pat.validate(42).result() == 42
assert pat.validate([42]).failed
2
TYPE_CONVERT
TYPE_CONVERT
模式下,BasePattern
直接对传入的值进行转换
from nepattern import BasePattern, MatchMode
pat = BasePattern(mode=MatchMode.TYPE_CONVERT, origin=int, accept=str, convert=lambda _, x: int(x))
assert pat.validate("42").success
assert pat.validate(42).success
2
3
4
5
注意的是,该情况下 converter
返回 None
时,也将会视为转换失败。
VALUE_OPERATE
VALUE_OPERATE
模式下,BasePattern
对传入的值进行操作
from nepattern import BasePattern, MatchMode
pat = BasePattern(mode=MatchMode.VALUE_OPERATE, origin=int, convert=lambda _, x: x + 1)
assert pat.validate(42).result() == 43
2
3
4
继承 BasePattern
当一般的 BasePattern
无法满足需求时,我们可以继承 BasePattern
类,实现自定义的 match
方法。
from nepattern import BasePattern, MatchMode, MatchFailed
class MyPattern(BasePattern):
def __init__(self, value: int):
super().__init__(mode=MatchMode.TYPE_CONVERT, origin=int)
self.value = value
def match(self, value):
if value == self.value:
return value
raise MatchFailed
2
3
4
5
6
7
8
9
10
11
继承 BasePattern
时,虽然 MatchMode
附带的约束将失效,但我们仍然建议遵循各模式的范式。
内建表达式
NEPattern
提供了一些预置的 BasePattern
实例,方便开发者使用:
- 基础类型:
INTEGER
,FLOAT
,BOOLEAN
,STRING
,DICT
,LIST
,TUPLE
,SET
,BYTES
NUMBER
:INT
与FLOAT
的组合,若传入值为整数则返回整数,否则返回浮点数WILD_BOOLEAN
:BOOL
的扩展,接受0
1
yes
no
等值,并允许拓展DelimiterInt
: 能够接受以,
分隔的整数列表AnyString
: 接受任意对象并转换为字符串
- 字符串为基础的类型:
IP
,URL
,EMAIL
,HEX
,HEX_COLOR
- 特殊类型:
DATETIME
,PATH
,PathFile
,ANY
,NONE
内建 BasePattern
子类
同样的,NEPattern
也提供了一些预置的 BasePattern
子类,方便开发者使用:
DirectPattern
:KEEP
模式的特殊BasePattern
子类,相比于KEEP
模式,DirectPattern
进行的操作更少。RegexPattern
:REGEX_MATCH
模式的特殊BasePattern
子类,其返回值为re.Match
类型。UnionPattern
: 允许组合多个BasePattern
实例,只要有一个BasePattern
实例通过验证即可。SwitchPattern
: 依据构造时传入的字典,判断传入值是否是字典中的键并返回对应的值。AntiPattern
: 用来包装一个BasePattern
实例,以实现相反的匹配效果。CustomMatchPattern
: 快捷地 "继承" 一个BasePattern
实例,实现自定义的match
方法。