添加 常用校验方法,校验常见数据格式

目录

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

一、前置说明

1、总体目录

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

2、相关回顾

  • 基于 Validator 类实现 ParamValidator,用于校验函数参数
  • 优化 ParamValidator,让编辑器Pycharm智能提示校验方法

3、本节目标

  • 添加常用校验方法,校验常见数据格式

二、操作步骤

1、项目目录

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

2、代码实现

pyparamvalidate/core/validator.py

import functools
import inspect
import os
from typing import TypeVardef _error_prompt(value, exception_msg=None, rule_des=None, field=None):default = f'"{value}" is invalid.'prompt = exception_msg or rule_desprompt = f'{default} due to: {prompt}' if prompt else defaultprompt = f'{field} error: {prompt}' if field else promptreturn promptdef raise_exception(func):@functools.wraps(func)def wrapper(self, *args, **kwargs):bound_args = inspect.signature(func).bind(self, *args, **kwargs).argumentsexception_msg = kwargs.get('exception_msg', None) or bound_args.get('exception_msg', None)error_prompt = _error_prompt(self.value, exception_msg, self._rule_des, self._field)result = func(self, *args, **kwargs)if not result:raise ValueError(error_prompt)return selfreturn wrapperclass RaiseExceptionMeta(type):def __new__(cls, name, bases, dct):for key, value in dct.items():if isinstance(value, staticmethod):dct[key] = staticmethod(raise_exception(value.__func__))if isinstance(value, classmethod):dct[key] = classmethod(raise_exception(value.__func__))if inspect.isfunction(value) and not key.startswith("__"):dct[key] = raise_exception(value)return super().__new__(cls, name, bases, dct)'''
- TypeVar 是 Python 中用于声明类型变量的工具
- 声明一个类型变量,命名为 'Self', 意思为表示类的实例类型
- bound 参数指定泛型类型变量的上界,即限制 'Self' 必须是 'Validator' 类型或其子类型
'''
Self = TypeVar('Self', bound='Validator')class Validator(metaclass=RaiseExceptionMeta):def __init__(self, value, field=None, rule_des=None):self.value = valueself._field = fieldself._rule_des = rule_desdef is_string(self, exception_msg=None) -> Self:"""将返回类型注解定义为 Self, 支持编辑器如 pycharm 智能提示链式调用方法,如:Validator(input).is_string().is_not_empty()- 从 Python 3.5 版本开始支持类型注解- 在 Python 3.5 中引入了 PEP 484(Python Enhancement Proposal 484),其中包括了类型注解的概念,并引入了 typing 模块,用于支持类型提示和静态类型检查;- 类型注解允许开发者在函数参数、返回值和变量上添加类型信息,但是在运行时,Python 解释器不会检查这些注解是否正确;- 它们主要用于提供给静态类型检查器或代码编辑器进行,以提供更好的代码提示和错误检测;- Python 运行时并不强制执行这些注解,Python 依然是一门动态类型的语言。- 本方法中:- 返回值类型为 bool 类型,用于与装饰器函数 raise_exception 配合使用,校验 self.value 是否通过;- 为了支持编辑器如 pycharm 智能识别链式调用方法,将返回类型注解定义为 Self, 如:Validator(input).is_string().is_not_empty();- Self, 即 'Validator', 由 Self = TypeVar('Self', bound='Validator') 定义;- 如果返回类型不为 Self, 编辑器如 pycharm 在 Validator(input).is_string() 之后,不会智能提示 is_not_empty()"""return isinstance(self.value, str)def is_int(self, exception_msg=None):return isinstance(self.value, int)def is_positive(self, exception_msg=None):return self.value > 0def is_float(self, exception_msg=None):return isinstance(self.value, float)def is_list(self, exception_msg=None):return isinstance(self.value, list)def is_dict(self, exception_msg=None):return isinstance(self.value, dict)def is_set(self, exception_msg=None):return isinstance(self.value, set)def is_tuple(self, exception_msg=None):return isinstance(self.value, tuple)def is_not_none(self, exception_msg=None):return self.value is not Nonedef is_not_empty(self, exception_msg=None):return bool(self.value)def is_allowed_value(self, allowed_values, exception_msg=None):return self.value in allowed_valuesdef is_specific_value(self, specific_value, exception_msg=None):return self.value == specific_valuedef max_length(self, max_length, exception_msg=None):return len(self.value) <= max_lengthdef min_length(self, min_length, exception_msg=None):return len(self.value) >= min_lengthdef is_substring(self, super_string, exception_msg=None):return self.value in super_stringdef is_subset(self, superset, exception_msg=None):return self.value.issubset(superset)def is_sublist(self, superlist, exception_msg=None):return set(self.value).issubset(set(superlist))def contains_substring(self, substring, exception_msg=None):return substring in self.valuedef contains_subset(self, subset, exception_msg=None):return subset.issubset(self.value)def contains_sublist(self, sublist, exception_msg=None):return set(sublist).issubset(set(self.value))def is_file(self, exception_msg=None):return os.path.isfile(self.value)def is_dir(self, exception_msg=None):return os.path.isdir(self.value)def is_file_suffix(self, file_suffix, exception_msg=None):return self.value.endswith(file_suffix)def is_method(self, exception_msg=None):return callable(self.value)

3、测试代码

pyparamvalidate/tests/test_validator.py


import osimport pytestfrom pyparamvalidate.core.validator import Validatordef test_is_string():assert Validator("test").is_string(exception_msg='value must be string')with pytest.raises(ValueError) as exc_info:Validator(123).is_string(exception_msg='value must be string')assert "value must be string" in str(exc_info.value)def test_is_int():assert Validator(42).is_int(exception_msg='value must be integer')with pytest.raises(ValueError) as exc_info:Validator("test").is_int(exception_msg='value must be integer')assert "value must be integer" in str(exc_info.value)def test_is_positive():assert Validator(42).is_positive(exception_msg='value must be positive')with pytest.raises(ValueError) as exc_info:Validator(-1).is_positive(exception_msg='value must be positive')assert "value must be positive" in str(exc_info.value)def test_is_float():assert Validator(3.14).is_float(exception_msg='value must be float')with pytest.raises(ValueError) as exc_info:Validator("test").is_float(exception_msg='value must be float')assert "value must be float" in str(exc_info.value)def test_is_list():assert Validator([1, 2, 3]).is_list(exception_msg='value must be list')with pytest.raises(ValueError) as exc_info:Validator("test").is_list(exception_msg='value must be list')assert "value must be list" in str(exc_info.value)def test_is_dict():assert Validator({"key": "value"}).is_dict(exception_msg='value must be dict')with pytest.raises(ValueError) as exc_info:Validator([1, 2, 3]).is_dict(exception_msg='value must be dict')assert "value must be dict" in str(exc_info.value)def test_is_set():assert Validator({1, 2, 3}).is_set(exception_msg='value must be set')with pytest.raises(ValueError) as exc_info:Validator([1, 2, 3]).is_set(exception_msg='value must be set')assert "value must be set" in str(exc_info.value)def test_is_tuple():assert Validator((1, 2, 3)).is_tuple(exception_msg='value must be tuple')with pytest.raises(ValueError) as exc_info:Validator([1, 2, 3]).is_tuple(exception_msg='value must be tuple')assert "value must be tuple" in str(exc_info.value)def test_is_not_none():assert Validator("test").is_not_none(exception_msg='value must not be None')with pytest.raises(ValueError) as exc_info:Validator(None).is_not_none(exception_msg='value must not be None')assert "value must not be None" in str(exc_info.value)def test_is_not_empty():assert Validator("test").is_not_empty(exception_msg='value must not be empty')with pytest.raises(ValueError) as exc_info:Validator("").is_not_empty(exception_msg='value must not be empty')assert "value must not be empty" in str(exc_info.value)def test_is_allowed_value():assert Validator(3).is_allowed_value(allowed_values=[1, 2, 3, 4, 5],exception_msg='value must be in allowed_values')with pytest.raises(ValueError) as exc_info:Validator(6).is_allowed_value(allowed_values=[1, 2, 3, 4, 5],exception_msg='value must be in allowed_values')assert "value must be in allowed_values" in str(exc_info.value)def test_is_specific_value():assert Validator(3).is_specific_value(specific_value=3,exception_msg='value must be in allowed_values')with pytest.raises(ValueError) as exc_info:Validator(6).is_specific_value(specific_value=3,exception_msg='value must be in allowed_values')assert "value must be in allowed_values" in str(exc_info.value)def test_max_length():assert Validator("test").max_length(max_length=5,exception_msg='value length must be less than or equal to 5')with pytest.raises(ValueError) as exc_info:Validator("test").max_length(max_length=3,exception_msg='value length must be less than or equal to 3')assert "value length must be less than or equal to 3" in str(exc_info.value)def test_min_length():assert Validator("test").min_length(min_length=3,exception_msg='value length must be greater than or equal to 3')with pytest.raises(ValueError) as exc_info:Validator("test").min_length(min_length=5,exception_msg='value length must be greater than or equal to 5')assert "value length must be greater than or equal to 5" in str(exc_info.value)def test_is_substring():assert Validator("st").is_substring(super_string="test",exception_msg='sub_string must be a substring of super_string')with pytest.raises(ValueError) as exc_info:Validator("abc").is_substring(super_string="test",exception_msg='sub_string must be a substring of super_string')assert "sub_string must be a substring of super_string" in str(exc_info.value)def test_is_subset():assert Validator({1, 2}).is_subset(superset={1, 2, 3, 4},exception_msg='subset must be a subset of superset')with pytest.raises(ValueError) as exc_info:Validator({5, 6}).is_subset(superset={1, 2, 3, 4},exception_msg='subset must be a subset of superset')assert "subset must be a subset of superset" in str(exc_info.value)def test_is_sublist():assert Validator([1, 2]).is_sublist(superlist=[1, 2, 3, 4],exception_msg='sublist must be a sublist of superlist')with pytest.raises(ValueError) as exc_info:Validator([5, 6]).is_sublist(superlist=[1, 2, 3, 4],exception_msg='sublist must be a sublist of superlist')assert "sublist must be a sublist of superlist" in str(exc_info.value)def test_contains_substring():assert Validator("test").contains_substring(substring="es",exception_msg='superstring must contain substring')with pytest.raises(ValueError) as exc_info:Validator("test").contains_substring(substring="abc",exception_msg='superstring must contain substring')assert "superstring must contain substring" in str(exc_info.value)def test_contains_subset():assert Validator({1, 2, 3, 4}).contains_subset(subset={1, 2},exception_msg='superset must contain subset')with pytest.raises(ValueError) as exc_info:Validator({1, 2, 3, 4}).contains_subset(subset={5, 6},exception_msg='superset must contain subset')assert "superset must contain subset" in str(exc_info.value)def test_contains_sublist():assert Validator([1, 2, 3, 4]).contains_sublist(sublist=[1, 2],exception_msg='superlist must contain sublist')with pytest.raises(ValueError) as exc_info:Validator([1, 2, 3, 4]).contains_sublist(sublist=[5, 6],exception_msg='superlist must contain sublist')assert "superlist must contain sublist" in str(exc_info.value)def test_is_file_suffix():assert Validator("example.txt").is_file_suffix(file_suffix=".txt",exception_msg='path must have the specified file suffix')with pytest.raises(ValueError) as exc_info:Validator("example.txt").is_file_suffix(file_suffix=".csv",exception_msg='path must have the specified file suffix')assert "path must have the specified file suffix" in str(exc_info.value)def test_is_file():assert Validator(__file__).is_file(exception_msg='path must be an existing file')with pytest.raises(ValueError) as exc_info:Validator("path").is_file(exception_msg='path must be an existing file')assert "path must be an existing file" in str(exc_info.value)def test_is_dir():assert Validator(os.path.dirname(__file__)).is_dir(exception_msg='path must be an existing directory')with pytest.raises(ValueError) as exc_info:Validator(__file__).is_dir(exception_msg='path must be an existing directory')assert "path must be an existing directory" in str(exc_info.value)def test_is_method():assert Validator(print).is_method(exception_msg='value must be a callable method')with pytest.raises(ValueError) as exc_info:Validator("test").is_method(exception_msg='value must be a callable method')assert "value must be a callable method" in str(exc_info.value)

4、日志输出

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


============================= test session starts =============================
collecting ... collected 24 itemstest_validator.py::test_is_string PASSED                                 [  4%]
test_validator.py::test_is_int PASSED                                    [  8%]
test_validator.py::test_is_positive PASSED                               [ 12%]
test_validator.py::test_is_float PASSED                                  [ 16%]
test_validator.py::test_is_list PASSED                                   [ 20%]
test_validator.py::test_is_dict PASSED                                   [ 25%]
test_validator.py::test_is_set PASSED                                    [ 29%]
test_validator.py::test_is_tuple PASSED                                  [ 33%]
test_validator.py::test_is_not_none PASSED                               [ 37%]
test_validator.py::test_is_not_empty PASSED                              [ 41%]
test_validator.py::test_is_allowed_value PASSED                          [ 45%]
test_validator.py::test_is_specific_value PASSED                         [ 50%]
test_validator.py::test_max_length PASSED                                [ 54%]
test_validator.py::test_min_length PASSED                                [ 58%]
test_validator.py::test_is_substring PASSED                              [ 62%]
test_validator.py::test_is_subset PASSED                                 [ 66%]
test_validator.py::test_is_sublist PASSED                                [ 70%]
test_validator.py::test_contains_substring PASSED                        [ 75%]
test_validator.py::test_contains_subset PASSED                           [ 79%]
test_validator.py::test_contains_sublist PASSED                          [ 83%]
test_validator.py::test_is_file_suffix PASSED                            [ 87%]
test_validator.py::test_is_file PASSED                                   [ 91%]
test_validator.py::test_is_dir PASSED                                    [ 95%]
test_validator.py::test_is_method PASSED                                 [100%]============================= 24 passed in 0.02s ==============================

三、后置说明

1、要点小结

  • is_string:检查参数是否为字符串。
  • is_int:检查参数是否为整数。
  • is_positive:检查参数是否为正数。
  • is_float:检查参数是否为浮点数。
  • is_list:检查参数是否为列表。
  • is_dict:检查参数是否为字典。
  • is_set:检查参数是否为集合。
  • is_tuple:检查参数是否为元组。
  • is_not_none:检查参数是否不为None。
  • is_not_empty:检查参数是否不为空(对于字符串、列表、字典、集合等)。
  • is_allowed_value:检查参数是否在指定的允许值范围内。
  • max_length:检查参数的长度是否不超过指定的最大值。
  • min_length:检查参数的长度是否不小于指定的最小值。
  • is_substring:检查参数是否为指定字符串的子串。
  • is_subset:检查参数是否为指定集合的子集。
  • is_sublist:检查参数是否为指定列表的子列表。
  • contains_substring:检查参数是否包含指定字符串。
  • contains_subset:检查参数是否包含指定集合。
  • contains_sublist:检查参数是否包含指定列表。
  • is_file:检查参数是否为有效的文件。
  • is_dir:检查参数是否为有效的目录。
  • is_file_suffix:检查参数是否以指定文件后缀结尾。
  • is_method:检查参数是否为可调用的方法(函数)。

注意:要将在 Validator 类中添加的方法,复制粘贴至 ParameterValidator 类中,方便 Pycharm 智能提示。

2、下节准备

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

点击返回主目录

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PhpPythonC++圆类的实现(OOP)

哎......被投诉了 &#x1f62d;&#x1f62d;&#x1f62d;&#x1f62d;&#x1f62d; 其实也不是小编不更&#xff0c;这不是期末了吗&#xff08;zhaojiekou~~&#xff09;&#xff0c;而且最近学的信息收集和ctf感觉好像没找到啥能更的&#xff08;不过最经还是在考虑更一…

创建网格(Grid/GridItem)

目录 1、概述 2、布局与约束 3、设置排列方式 3.1设置行列数量与占比 3.2、设置子组件所占行列数 3.3、设置主轴方向 3.4、在网格布局中显示数据 3.5、设置行列间距 4、构建可滚动的网格布局 5、实现简单的日历功能 6、性能优化 1、概述 网格布局是由“行”和“列”分…

【算法分析与设计】三数之和

题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示例…

【LeetCode:49. 字母异位词分组 | 哈希表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

python 基础 面向对象

类 class Student:name Nonegender Nonenationality Nonenative_place Noneage Nonedef say_hi(self):print(self.name)def dowork(self,work):print(f"{self.name} {work}") student1 Student() student1.name "xxx" student1.gender "男&qu…

数据库开发工具Navicat Premium 15 mac软件特色

Navicat Premium 15 mac版是一款数据库开发工具&#xff0c;Navicat Premium 15 Mac版可以让你以单一程序同時连接到 MySQL、MariaDB、SQL Server、SQLite、Oracle 和 PostgreSQL 数据库。 Navicat Premium mac软件特色 无缝数据迁移 数据传输&#xff0c;数据同步和结构同步…

华为云AI:轻松实现图像识别调用

文章目录 前言一、环境配置关键步骤 二、图像识别实例媒资图像标签名人识别 总结 前言 基于华为云AI服务和java使用SDK实现图像识别&#xff0c;主要以媒资图像标签和名人识别为例。 一、环境配置 Maven&#xff08;没有直接下载华为的SDK包&#xff0c;而是使用Maven安装依赖…

cpolar 内网穿透 使用

cpolar 内网穿透 使用 官网地址&#xff1a;https://www.cpolar.com/ 官网文档&#xff1a;https://www.cpolar.com/blog/cpolar-quick-start-tutorial-centos-series 获取隧道Authtoken&#xff1a;https://dashboard.cpolar.com/auth 步骤 1、先去注册 在这个地方注册&…

[ 机器学习 ] 关于Jupyter Notebook中pytorch模块import失败的问题

0x01、问题描述 在使用WSL搭建Jupyter进行代码测试的时候 发现Miniconda&#xff08;虚拟环境均适用&#xff09;中安装的pytorch在Jupyter里面import失败 但在python解释器的命令模式里可以测试import成功 并且torch.cuda_available()打印True 以前用的是IDEA没怎么用Jup…

模仿Activiti工作流自动建表机制,实现Springboot项目启动后自动创建多表关联的数据库与表的方案

文/朱季谦 熬夜写完&#xff0c;尚有不足&#xff0c;但仍在努力学习与总结中&#xff0c;而您的点赞与关注&#xff0c;是对我最大的鼓励&#xff01; 在一些本地化项目开发当中&#xff0c;存在这样一种需求&#xff0c;即开发完成的项目&#xff0c;在第一次部署启动时&…

Qt之有趣的数字钟

一.效果 基于网络代码修改,支持时、分、秒;支持滑动、翻页和旋转。 二.实现 #include <QtCore> #include <QPainter> #include <QAction> #include <QWidget> #include <QMainWindow> #include <QTimer> #include <QKeyEvent> #…

【一竞技DOTA2】MinD_ContRoL加盟Tundra

1、近日Tundra战队正式官宣MinD_ContRoL加入队伍。他此前效力于Nigma战队,在离队不久后他便做出了加入Tundra战队的选择,借此他也成为了Tundra Esports战队已官宣了的阵容中的第四名选手。 2、Bleed战队正式官宣Mikoto和poloson加入战队。 Mikoto曾效力于东南亚赛区的Talon战队…