param_validator 核心代码实现

news2025/5/24 16:06:20

目录

  • 一、前置说明
    • 1、总体目录
    • 2、相关回顾
    • 3、本节目标
  • 二、操作步骤
    • 1、项目目录
    • 2、代码实现
    • 3、测试代码
    • 4、日志输出
  • 三、后置说明
    • 1、要点小结
    • 2、下节预告

一、前置说明

1、总体目录

  • 《 pyparamvalidate 参数校验器,从编码到发布全过程》

2、相关回顾

  • pyparamvalidate 项目背景和需求分析

3、本节目标

  • param_validator 核心代码实现

二、操作步骤

1、项目目录

  • atme : @me 用于存放临时的代码片断或其它内容。
  • pyparamvalidate : 新建一个与项目名称同名的package,为了方便发布至 pypi
  • core : 用于存放核心代码。
  • tests : 用于存放测试代码。
  • utils : 用于存放一些工具类或方法。

2、代码实现

pyparamvalidate/core/param_validator.py

import functools
import inspect
import os.path


class ParameterValidationError(Exception):

    def __init__(self, func, parameter_name, parameter_value, param_rule_description=None, exception_msg=None):
        self.func_name = func.__name__
        self.parameter_name = parameter_name
        self.parameter_value = parameter_value
        self.param_rule_description = param_rule_description
        self.exception_msg = exception_msg

        super().__init__(self.error_message())

    def error_message(self):
        return (
            f"Parameter '{self.parameter_name}' in function '{self.func_name}' is invalid. "
            f"\t{'Error: ' + self.exception_msg if self.exception_msg else ''}"
            f"\t{'Please refer to: ' + self.param_rule_description if self.param_rule_description else ''}"
        )


class ParameterValidator:
    def __init__(self, param_name, param_rule_des=None):
        """
        :param param_name: 参数名
        :param param_rule_des: 该参数的规则描述
        """
        self.param_name = param_name
        self.param_rule_description = param_rule_des

        # 用于收集校验器
        self.validators = []

    def __call__(self, func):

        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 获取函数的参数和参数值
            bound_args = inspect.signature(func).bind(*args, **kwargs).arguments

            # 如果函数被装饰,且以关键字参数传值,则从 kwargs 中取参数值
            if self.param_name in kwargs:
                value = kwargs[self.param_name]

            # # 如果函数被装饰,且以位置参数传值,则从 bound_args 中取参数值
            elif self.param_name in bound_args:
                value = bound_args.get(self.param_name)

            # 如果函数没有被装饰,则直接执行返回结果
            else:
                return func(*args, **kwargs)

            # 使用验证器进行验证
            for validator, exception_msg in self.validators:

                # 如果没验证通过,则抛出异常
                if not validator(value):
                    raise ParameterValidationError(func, self.param_name, value,
                                                   self.param_rule_description, exception_msg)
            # 所有参数校验通过,则执行函数返回结果
            return func(*args, **kwargs)

        return wrapper

    def add_validator(self, validator_function, exception_msg=None):
        self.validators.append((validator_function, exception_msg))
        return self

    def is_string(self, exception_msg=None):
        return self.add_validator(lambda value: isinstance(value, str), exception_msg)

3、测试代码

pyparamvalidate/tests/test_param_validator.py

import os

import pytest

from pyparamvalidate.core.param_validator import ParameterValidator, ParameterValidationError


def test_is_string_validator_passing_01():
    """
    不描述参数规则
    """

    @ParameterValidator("param").is_string()
    def example_function(param):
        print(param)
        return param

    assert example_function(param="test") == "test"

    with pytest.raises(ParameterValidationError) as exc_info:
        example_function(param=123)

    print(exc_info.value)
    assert "invalid" in str(exc_info.value)


def test_is_string_validator_passing_02():
    """
    在校验器中描述参数规则
    """

    @ParameterValidator("param").is_string("Value must be a string")
    def example_function(param):
        print(param)
        return param

    assert example_function(param="test") == "test"

    with pytest.raises(ParameterValidationError) as exc_info:
        example_function(param=123)

    print(exc_info.value)
    assert "Value must be a string" in str(exc_info.value)


def test_is_string_validator_passing_03():
    """
    在 ParameterValidator 实例化时描述参数规则
    """

    @ParameterValidator("param", param_rule_des="Value must be a string").is_string()
    def example_function(param):
        print(param)
        return param

    assert example_function(param="test") == "test"

    with pytest.raises(ParameterValidationError) as exc_info:
        example_function(param=123)

    print(exc_info.value)
    assert "Value must be a string" in str(exc_info.value)

4、日志输出

执行 test 的日志如下,验证通过:

============================= test session starts =============================
collecting ... collected 3 items

test_param_validator.py::test_is_string_validator_passing_01 PASSED      [ 33%]test
Parameter 'param' in function 'example_function' is invalid. 		

test_param_validator.py::test_is_string_validator_passing_02 PASSED      [ 66%]test
Parameter 'param' in function 'example_function' is invalid. 	Error: Value must be a string	

test_param_validator.py::test_is_string_validator_passing_03 PASSED      [100%]test
Parameter 'param' in function 'example_function' is invalid. 		Please refer to: Value must be a string


============================== 3 passed in 0.01s ==============================

三、后置说明

1、要点小结

  • 使用 __call__ 方法,实现一个类装饰器;
  • 使用 inspect.signature(func).bind(*args, **kwargs).arguments 绑定参数名和参数值;
  • 如果是关键字参数,则使用 kwargs[self.param_name] 获取参数值;
  • 如果是位置参数,则使用 bound_args.get(self.param_name) 获取参数值;
  • 使用装饰器时,可以:不描述规则、在校验器中描述规则、在 ParameterValidator 实例化时描述参数规则。

2、下节预告

  • param_validator 常用校验器的实现

点击返回主目录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1355948.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

02. BI - Project Two, 男女声音识别

文章目录 Hi, 你好。我是茶桁。 上一节课,咱们用一个员工离职预测的案例来学习了LR和SVM。 那今天咱们还是来看案例,从案例来入手。那今天的例子会带着大家一起来做一个练习,是一个男男女声音识别的例子。数据集来自于3,168个录音的样本&…

力扣:62. 不同路径(动态规划,附python二维数组的定义)

题目: 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径&…

VScode安装ESP开发环境

VScode安装ESP开发环境 ESP-IDF 是乐鑫官方的物联网开发框架,适用于 ESP32、ESP32-S、ESP32-C 和 ESP32-H 系列 SoC。它基于 C/C 语言提供了一个自给自足的 SDK,方便用户在这些平台上开发通用应用程序,并集成了大量的软件组件,包…

牵绳遛狗你我他文明家园每一天,助力共建文明社区,基于YOLOv5开发构建公共场景下未牵绳遛狗检测识别系统

遛狗是每天要打卡的事情,狗狗生性活泼爱动,一天不遛就浑身难受,遛狗最重要的就是要拴绳了,牵紧文明绳是养犬人的必修课。外出遛狗时,主人手上的牵引绳更多是狗狗生命健康的一道重要屏障。每天的社区生活中,…

Zabbix 监控介绍

1、功能概述 通常所说的监控,会模糊地包含以上下个细分领域的内容: 应用性能监控(Application Performance Monitoring)业务交易监控(Business Transaction Monitoring)网络性能监控(Network …

ubuntu20快速搭建自己的git代码仓库环境

##安装docker groupadd docker apt install docker.io ##用户添加到docker组 sudo usermod -aG docker ${USER} ##用户添加sudo cat /etc/sudoers apt install vim ##sudoers文件权限可以写 chmod uw sudoers vim sudoers ##在root底下添加这行,yym改到自…

【C初阶——指针1】鹏哥C语言系列文章,基本语法知识全面讲解——指针(1)

长城之上是千亿的星空,星空之上是不畏的守望。 本文由睡觉待开机原创,转载请注明出处。 本内容在csdn网站首发 欢迎各位点赞—评论—收藏 如果存在不足之处请评论留言,共同进步! 文章目录 前言1.内存和地址2.指针变量和地址2.1指针…

Databend 的算力可扩展性

作者:尚卓燃(PsiACE) 澳门科技大学在读硕士,Databend 研发工程师实习生 Apache OpenDAL(Incubating) Committer PsiACE (Chojan Shang) GitHub 对于大规模分布式数据处理系统,为了更好应对数据、流量、和复杂性的增长…

[足式机器人]Part2 Dr. CAN学习笔记-Ch01自动控制原理

本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记-Ch01自动控制原理 1. 开环系统与闭环系统Open/Closed Loop System1.1 EG1: 烧水与控温水壶1.2 EG2: 蓄水与最终水位1.3 闭环控制系统 2. 稳定性分析Stability2.1 序言2.2 稳定的分类2.3 稳定的对…

SwiftUI 打造一款“可收缩”的 HStack(一):“原汤化原食”

概览 拥有雄心壮志(亦或是自我感觉良好)的秃头码农们都喜欢接受编程上各种颇有难度的挑战,比如刷刷力扣(LeetCode)或 codeforces 上难题啥的。 为了满足小伙伴们的“冒险精神”(亦或是“自虐癖”),加上这篇博文我们会用连续 4 篇系列文章通过不同的方式来解决同一道与…

【IDEA——连接MySQL数据库,创建库和表】

IDEA——连接MySQL数据库,创建库和表 1、打开idea数据库操作页面(两种打开方法都可以) 2、点击加号,选择Driver,方便导入连接数据库的驱动jar包 然后选择MySQL进行添加驱动 3、点击上一步页面的左上方的Data Sources连接本地数据…

保姆级教程:从0到1搭建web自动化测试环境

之前都是在linux上安装,第一次在windows上配置环境,加上距离上次配置环境有点久了,竟也花了点时间。特此记录下保姆级教程,给初学者一个有效的参考! 一. 环境搭建 工具清单 工具工具名版本Java开发工具包JDK1.8浏览…

揭秘Linux软链接:如何轻松创建、删除和修改

揭秘Linux软链接:如何轻松创建、删除和修改 一、简介二、创建软链接三、删除软链接四、修改软链接五、Linux软链接的高级用法六、总结 一、简介 在Linux中,软链接(Symbolic Link)是一种特殊的文件类型,它是一个指向另…

【DevOps-03】Build阶段-Maven安装配置

一、简要说明 下载安装JDK8下载安装Maven二、复制准备一台虚拟机 1、VM虚拟复制克隆一台机器 2、启动刚克隆的虚拟机,修改IP地址 刚刚克隆的虚拟机 ,IP地址和原虚拟的IP地址是一样的,需要修改克隆后的虚拟机IP地址,以免IP地址冲突。 # 编辑修改IP地址 $ vi /etc/sysconfig…

申请域名SSL证书并自动推送至阿里云 CDN

近期国外SSL证书厂商调整了免费证书的续签规则,一年期的证书全部取消,现在只能申请90天有效期的免费证书。普通web站点可以通过宝塔面板或部署acme.sh等证书自动管理工具来实现自动化申请和部署,但是阿里云之类的CDN服务就只能通过手动或Open…

Python split()方法详解:分割字符串

Python 中,除了可以使用一些内建函数获取字符串的相关信息外(例如 len() 函数获取字符串长度),字符串类型本身也拥有一些方法供我们使用。 注意,这里所说的方法,指的是字符串类型 str 本身所提供的&#x…

linux性能优化

文章目录 性能优化图CPU进程和cpu原理性能指标 性能优化图 CPU 进程和cpu原理 进程与线程: 进程是程序的执行实例,有自己的地址空间和系统资源。线程是进程内的执行单元,共享进程的资源。在多核系统中,使用多线程可以更好地利用多…

【四】CocosCreator-修改引擎源码

看源码的过程中,少不了得修修改改源码,做点实验。果断去找找源码在哪里,然后就可以快乐动手改源码了。 CocosCreator引擎源码主要就是js和原生C两类,分别在引擎目录的resources/engine和resources/cocos2d-x下,如图&am…

金色麦芒的2023

2023年即将过去,回首这一年,我深感自己在技术和职业生涯中取得了巨大的进步。这一年里,我不仅在技术层面有了更深入的掌握,也在个人成长和职业规划上有了更明确的方向。 首先,在技术层面,我今年最大的收获是…

Innosetup 调用c# dll 和 c# dll的函数导出

目标需求,基于现在安装包脚本。需要在用户安装和卸载成功时。进行数据记录,所以需要调用c#dll 主要涉及到的知识点 需要理解脚本的文件使用机制脚本的文件dll加载,和dll的调用c# dll的制作,和工具的使用 下面具体介绍 脚本的文件dll加载&…