一、前置说明
1、本节目标
- 添加 自定义校验方法,让用户自定义校验规则
2、相关回顾
二、操作步骤
1、项目目录
atme
:@me
用于存放临时的代码片断或其它内容。pyparamvalidate
: 新建一个与项目名称同名的package,为了方便发布至pypi
。core
: 用于存放核心代码。tests
: 用于存放测试代码。utils
: 用于存放一些工具类或方法。
2、代码实现
pyparamvalidate/core/validator.py
... class Validator(metaclass=RaiseExceptionMeta): def __init__(self, value, field=None, rule_des=None): self.value = value self._field = field self._rule_des = rule_des def customize(self, validate_method, *args, exception_msg=None, **kwargs) -> Self: """ 注意事项:请参考示例 3 示例 1:使用 lambda 函数 ''' Validator(4).customize(validate_method=lambda x: x % 2 == 0) ''' 示例 2:函数只有一个参数 ''' def even_number_validator(value): return value % 2 == 0 Validator(4).customize(validate_method=even_number_validator) ''' 示例 3:如果函数有多个参数,必须将 "待校验参数" 放在第一位 ''' # 方法定义注意事项:如果有多个参数,必须将 "待校验参数" 放在第一位 def even_number_validator(value, threshold): return value % 2 == 0 and value > threshold # 方法调用注意事项:第一个参数不要传值,exception_msg 必须以关键字参数传值。 Validator(12).customize(even_number_validator, 10, exception_msg='value must be an even number and greater than 10.') ''' """ try: return validate_method(self.value, *args, **kwargs) except TypeError as e: raise CallValidateMethodError( f''' Note: 1. Please do not send value to first argument in calling {validate_method.__name__}. 2. You must pass the value for "exception_msg" as a "keyword argument". 3. please refer to: def even_number_validator(value, threshold): return value % 2 == 0 and value > threshold Validator(12).customize(even_number_validator, 10, exception_msg='value must be an even number and greater than 10.') 4. origin error: {e}' ''') ...
3、测试代码
pyparamvalidate/tests/test_validator.py
def test_customize_validator_01(): Validator(4).customize(validate_method=lambda x: x % 2 == 0) with pytest.raises(ValueError) as exc_info: Validator(3).customize(validate_method=lambda x: x % 2 == 0, exception_msg='value must be an even number.') assert "value must be an even number." in str(exc_info.value) def test_customize_validator_02(): def even_number_validator(value): return value % 2 == 0 Validator(4).customize(validate_method=even_number_validator) with pytest.raises(ValueError) as exc_info: Validator(3).customize(validate_method=lambda x: x % 2 == 0, exception_msg='value must be an even number.') assert "value must be an even number." in str(exc_info.value) def test_customize_validator_03(): def even_number_validator(value, threshold): return value % 2 == 0 and value > threshold Validator(12).customize(even_number_validator, 10) Validator(12).customize(even_number_validator, 10, exception_msg='value must be an even number and greater than 10.') Validator(12).customize(even_number_validator, threshold=10, exception_msg='value must be an even number and greater than 10.') with pytest.raises(ValueError) as exc_info: Validator(2).customize(validate_method=even_number_validator, threshold=10, exception_msg='value must be an even number and greater than 10.') assert "value must be an even number and greater than 10." in str(exc_info.value) with pytest.raises(CallValidateMethodError) as exc_info: Validator(2).customize(even_number_validator, 2, 10, exception_msg='value must be an even number and greater than 10.') ...
4、日志输出
执行 test
的日志如下,验证通过:
test_validator.py::test_customize_validator_01 PASSED [ 3%] test_validator.py::test_customize_validator_02 PASSED [ 7%] test_validator.py::test_customize_validator_03 PASSED [ 11%]
三、后置说明
1、要点小结
- 自定义校验方法的定义和调用注意事项,见
customize
方法中的示例说明。
- 将
customize
方法,复制粘贴至ParameterValidator
类中并对方法注释进行适当修改,方便Pycharm
智能提示。
... def customize(self, validate_method, *args, exception_msg=None, **kwargs) -> Self: """ 注意事项:请参考示例 3 示例 1:使用 lambda 函数 ''' @ParameterValidator("param").customize(lambda x: x % 2 == 0, exception_msg="Value must be an even number") def example_function(param): return param ''' 示例 2:函数只有一个参数 ''' def even_number_validator(value): return value % 2 == 0 @ParameterValidator("param").customize(even_number_validator, exception_msg="Value must be an even number") def example_function(param): return param ''' 示例 3:如果函数有多个参数,必须将 "待校验参数" 放在第一位 ''' # 方法定义注意事项:如果有多个参数,必须将 "待校验参数" 放在第一位 def even_number_validator(value, threshold): return value % 2 == 0 and value > threshold # 方法调用注意事项:第一个参数不要传值,exception_msg 必须以关键字参数传值。 @ParameterValidator("param").customize(even_number_validator, 10, exception_msg="Value must be an even number") def example_function(param): return param ''' """ ... ...
2、下节准备
- 使用
schema
库,自定义复杂的校验方法