添加 自定义校验方法,让用户自定义校验规则

一、前置说明

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 库,自定义复杂的校验方法

点击进入《Python装饰器从入门到进阶》总目录

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kinder-balabala

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值