#形态学是一个python数据验证库
morpholog的Python项目详细描述
形态学是一个python数据验证库
形态学是一个python数据验证库。它主要用于验证作为json传入python的数据, 山药等
它有三个目标:
- 简单。
- 支持复杂的数据结构。
- 提供有用的错误信息。
联系人
要归档错误,请在github上创建一个新问题,并提供一个如何复制该问题的简短示例。
文档
文档在这里提供。
更改日志
请参见changelog.md
给我举个例子
twitter的用户搜索api接受 查询URL,例如:
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
为了验证这一点,我们可以使用如下模式:
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })
这个模式非常简洁和粗略地描述了
API,会很好的工作。但也有一些问题。首先,它
不能完全表达api的约束。根据API,
每页
最多应限制为20,默认为5,对于
例子。为了更准确地描述api的语义,我们
架构需要更彻底地定义:
>>> frommorphologyimportRequired,All,Length,Range>>> schema=Schema({... Required('q'):All(str,Length(min=1)),... Required('per_page',default=5):All(int,Range(min=1,max=20)),... 'page':All(int,Range(min=0)),... })
这个模式完全强制执行twitter中定义的接口 文档,并进一步完善。
"Q"是必需的:
>>> frommorphologyimportMultipleInvalid,Invalid>>> try:... schema({})... raiseAssertionError('MultipleInvalid not raised')... exceptMultipleInvalidase:... exc=e>>> str(exc)=="required key not provided @ data['q']"True
…必须是字符串:
>>> try:... schema({'q':123})... raiseAssertionError('MultipleInvalid not raised')... exceptMultipleInvalidase:... exc=e>>> str(exc)=="expected str for dictionary value @ data['q']"True
…并且长度必须至少为一个字符:
>>> try:... schema({'q':''})... raiseAssertionError('MultipleInvalid not raised')... exceptMultipleInvalidase:... exc=e>>> str(exc)=="length of value must be at least 1 for dictionary value @ data['q']"True>>> schema({'q':'#topic'})=={'q':'#topic','per_page':5}True
"每页"是不大于20的正整数:
>>> try:... schema({'q':'#topic','per_page':900})... raiseAssertionError('MultipleInvalid not raised')... exceptMultipleInvalidase:... exc=e>>> str(exc)=="value must be at most 20 for dictionary value @ data['per_page']"True>>> try:... schema({'q':'#topic','per_page':-10})... raiseAssertionError('MultipleInvalid not raised')... exceptMultipleInvalidase:... exc=e>>> str(exc)=="value must be at least 1 for dictionary value @ data['per_page']"True
"page"是一个整数>;=0:
>>> try:... schema({'q':'#topic','per_page':'one'})... raiseAssertionError('MultipleInvalid not raised')... exceptMultipleInvalidase:... exc=e>>> str(exc)"expected int for dictionary value @ data['per_page']">>> schema({'q':'#topic','page':1})=={'q':'#topic','page':1,'per_page':5}True
定义模式
模式是由字典、列表和 标量和验证器。输入模式中的每个节点都是模式 与输入数据中的相应节点匹配。
文字
架构中的文本使用正常的相等检查进行匹配:
>>> schema=Schema(1)>>> schema(1)1>>> schema=Schema('a string')>>> schema('a string')'a string'
类型
通过检查对应的值是否匹配架构中的类型 是以下类型的实例:
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
0
网址
架构中的url通过使用urlparse库进行匹配。
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
1
列表
架构中的列表被视为一组有效值。每个元素 在模式列表中与输入数据中的每个值进行比较:
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
2
但是,空列表([]
)被视为原样。如果要指定一个可以
包含任何内容,将其指定为列表
:
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
3
验证功能
验证器是简单的可调用函数,当
它们遇到无效数据。确定有效性的标准是
完全取决于实现;它可以检查值是否有效
带有pwd.getpwnam()的用户名代码>,它可以检查值是否为
特定类型,依此类推。
最简单的验证程序是一个python函数,它引发 参数无效时出现valueerror。方便,许多内置 python函数具有此属性。下面是一个约会的例子 验证器:
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
4
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
5
除了简单地确定一个值是否有效之外,验证器还可以
将值变异为有效形式。这方面的一个例子是
强制(类型)
函数,它返回强制其
给定类型的参数:
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
6
这个例子还展示了一个常见的习惯用法,其中一个可选的人类可读的 可以提供消息。这可以大大提高 生成的错误消息。
词典
架构字典中的每个键值对都根据 对应数据字典中的键值对:
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
7
额外的字典键
默认情况下,数据中(而不是架构中)的任何其他键都将 触发异常:
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
8
此行为可以根据每个模式进行更改。允许
附加钥匙使用
架构(…,extra=allow_extra)
:
$ curl 'https://api.twitter.com/1.1/users/search.json?q=python&per_page=20&page=1'
9
要删除其他密钥,请使用
架构(…,extra=remove_extra)
:
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })0
也可以使用catch all标记覆盖每个字典
令牌额外的
作为密钥:
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })1
所需的字典键
默认情况下,架构中的键不需要在数据中:
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })2
类似于额外密钥的工作方式,可以重写此行为 每个架构:
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })3
每一个密钥,带有标记标记必需(密钥)
:
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })4
可选字典键
如果模式具有required=true
,则键可以单独标记为
可选使用标记符号可选(键)
:
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })5
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })6
递归/嵌套模式
您可以使用词法.self
定义嵌套模式:
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })7
扩展现有架构
通常,使用扩展了
要求。在这种情况下,可以使用schema.extend来创建新的
模式
:
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })8
原始的模式保持不变。
对象
架构字典中的每个键值对都根据 对应对象中的属性值对:
>>> frommorphologyimportSchema>>> schema=Schema({... 'q':str,... 'per_page':int,... 'page':int,... })9
不允许任何值
要同时允许value为none,请使用any:
>>> frommorphologyimportRequired,All,Length,Range>>> schema=Schema({... Required('q'):All(str,Length(min=1)),... Required('per_page',default=5):All(int,Range(min=1,max=20)),... 'page':All(int,Range(min=0)),... })0
错误报告
如果传递了无效数据,验证器必须抛出一个无效的
异常
对他们来说。所有其他异常都被视为验证器中的错误,并且
不会被捕获。
每个无效的
异常都有一个关联的路径
属性,表示
数据结构中指向当前验证值的路径,以及
作为包含原始消息的错误消息
属性
例外。当您想捕获无效的
异常并向用户提供一些反馈,例如
一个http api。
>>> frommorphologyimportRequired,All,Length,Range>>> schema=Schema({... Required('q'):All(str,Length(min=1)),... Required('per_page',default=5):All(int,Range(min=1,max=20)),... 'page':All(int,Range(min=0)),... })1
路径
属性在错误报告期间使用,但也在匹配期间使用
确定是否应将错误报告给用户,或者
应尝试匹配。这是通过比较
检查所在的路径,到发生错误的路径的深度。如果
据报告,错误深度超过一个级别。
其结果是匹配是深度优先的,并且失败速度很快
为了说明这一点,下面是一个模式示例:
>>> frommorphologyimportRequired,All,Length,Range>>> schema=Schema({... Required('q'):All(str,Length(min=1)),... Required('per_page',default=5):All(int,Range(min=1,max=20)),... 'page':All(int,Range(min=0)),... })2
顶级列表中的每个值都是按顺序首先匹配深度的。鉴于
输入[[6]]
的数据,内部列表将匹配
模式,但文本6
与
那个名单。此错误将报告给美国立刻。不
尝试回溯:
>>> frommorphologyimportRequired,All,Length,Range>>> schema=Schema({... Required('q'):All(str,Length(min=1)),... Required('per_page',default=5):All(int,Range(min=1,max=20)),... 'page':All(int,Range(min=0)),... })3
如果我们传递数据[6]
,则6
不是列表类型,因此不会
递归到架构的第一个元素中。匹配将继续
到架构中的第二个元素,并成功:
>>> frommorphologyimportRequired,All,Length,Range>>> schema=Schema({... Required('q'):All(str,Length(min=1)),... Required('per_page',default=5):All(int,Range(min=1,max=20)),... 'page':All(int,Range(min=0)),... })4
运行测试。
形态学正在使用鼻测试:
>>> frommorphologyimportRequired,All,Length,Range>>> schema=Schema({... Required('q'):All(str,Length(min=1)),... Required('per_page',default=5):All(int,Range(min=1,max=20)),... 'page':All(int,Range(min=0)),... })5
为什么在另一个验证库上使用形态学?
验证器是简单的可调用函数 :无需子类化任何内容,只需使用函数即可。
错误是简单的例外。
:验证器只需引发invalid(msg)
并期望用户获得
有用的信息。
模式是基本的python数据结构。
:您的数据应该是字符串的整数键字典吗?
{int:str}
做你所期望的。整数、浮点数或
串?[int,float,str]
从头开始设计,不仅用于验证表单。
:嵌套数据结构的处理方式与任何其他
类型。需要一份字典清单吗?[{}]
一致性。 :架构中的类型被检查为类型。数值比较如下 价值观。调用可调用项进行验证。简单,
沿袭
形态学几乎是这个库的直接分支。 此问题已打开,解决了不适当的 名字的性质,但被原作者草率地关闭了。不幸的是,这阻止了一个伟大的图书馆 在专业、包容的环境中使用,唯一的解决方案是使用fork来处理这个特定的 问题。重要的是要认识到亚历克托马斯和其他出资人应该得到 这里的功能。
在未来,我打算移植任何重要的升级,并将尝试保持版本同步,以便
可与另一个互换,只需简单地全部替换即可。由于各种建造的原因,形态小版本
相当于10x(父级次要版本)+c
,其中c
是0-9,只与集成修复有关。