将Python类型注释转换为JSON模式的包
pytojsonschema的Python项目详细描述
皮托日森舍马
使用静态分析-ast
-将python3函数类型注释转换为JSON模式的包。在
这允许您为用Python编写的JSON-RPC后端函数自动生成验证模式。在
当前支持Python3.8+和JSON模式草稿7+。在
入门
安装
在python3.8+环境中,运行pip install pytojsonschema
。在
扫描包
安装包后,可以从repo的根目录打开python终端并运行:
importosimportpprintfrompytojsonschema.functionsimportprocess_packagepprint.pprint(process_package(os.path.join("test","example")))
将扫描示例包,并为它可以找到的所有顶级函数生成JSON模式。在
扫描文件
您也可以针对特定的文件,这些文件不会在结果值中包含包名称空间。 在同一终端上:
^{pr2}$包括和排除模式
Include和exclude类unix模式可用于筛选要允许/不允许的函数和模块名称 正在扫描。当您现在运行此选项时,可以看到不同之处:
pprint.pprint(process_package(os.path.join("test","example"),exclude_patterns=["_*"]))
类似地,但适用于特定文件:
pprint.pprint(process_file(os.path.join("test","example","service.py"),exclude_patterns=["_*"]))
需要考虑的事项:
- 排除模式匹配覆盖包含匹配项。在
__init__.py
文件不受模式规则的影响,并且总是被扫描。但是,您仍然可以过滤 内部功能。在
类型批注规则
将Python的类型模型调整为JSON意味着函数签名中不允许所有内容。 这是JSON数据序列化附带的一个自然限制。希望你需要的大部分有用的东西是 允许。在
允许的类型
基本类型
允许使用基本类型bool
、int
、float
、str
、None
和{typing.Union
、typing.Optional
、typing.Dict
(只允许str
键)和
typing.List
。所有这些类型在JSON和JSON模式中都有一个直接的、非歧义的表示。在
自定义类型
您的函数也可以使用自定义类型,例如使用typing.Union
,typing.List
赋值定义的类型,
typing.Dict
和{
ServicePort=typing.Union[int,float]ServiceConfig=typing.Dict[str,typing.Any]
您可以使用python3.8的一个新特性typing.TypedDict
,在dict-like上构建更强的验证
对象(仅基于类的语法)。如您所见,您可以无限制地链接类型:
classService(typing.TypedDict):address:strport:ServicePortconfig:ServiceConfigtags:typing.List[str]debug:bool=False
注意:虽然Python本身不会自动填充默认值,但是可以使用它们使属性不需要。
另外,如果需要限制类型的选择,可以使用Python枚举:
importenumclassHTTPMethod(enum.Enum):GET="GET"POST="POST"PATCH="PATCH"DELETE="DELETE"defmy_func(http_method:HTTPMethod):pass# My code
注意:枚举的所有属性必须是常量:None
,int
,float
,bool
,str
。
注意:结果验证使用不同的枚举值,例如HTTPMethod.GET.value
或简单地"GET"
,作为
有效的选择而不是枚举实例本身,例如HTTPMethod.GET
,因为这是JSON模式可以理解的。这个
可能导致与其他静态分析工具(如http://mypy-lang.org/)不兼容,
所以请记住这一点。
从其他文件导入类型
您可以在包中导入这些自定义类型,它们将被提取。但是,由于 无法遵循来自外部包的扫描、自定义类型,因此不受支持。换句话说,你可以 仅使用相对导入在包中共享这些类型。在
其他静态分析工具,如mypy
使用带有存根文件的存储库来解决此问题,请参阅
https://mypy.readthedocs.io/en/stable/stubs.html。这是不可能的
像这样一个小项目的范围,至少现在是这样。在
规则
- 在
需要对要扫描的函数进行类型注释。很明显的要求,对吧?在
在 - 在
只能使用上一节中定义的类型。他们是c安全地序列化为JSON。在
在 - 在
函数参数应该以键值格式传递,就像json对象一样。这有几个限制 关于*args、**kwargs、仅位置参数和仅关键字参数:
允许以下情况:
- **kwargs:
def func(**kwargs): pass
- keyword only参数:
def func(*, a): pass
不允许出现以下情况:
- *args:
def func(*args): pass
- 仅位置参数:
def func(a, /): pass
- **kwargs:
- 项目
标签: