跳转至

介绍

Pait是一个轻量级的Python Api开发工具,拥有参数类型检查, 类型转换,提供文档输出和gRPC GateWay等功能,非常适合用于后端的接口开发, 它被设计成可以用于多个Python的Web应用开发框架(目前适配了Flask, Starlette, Sanic, Tornado),Pait设计灵感见文章《给python接口加上一层类型检》

Note

type hint check 100%

test coverage 95%+ (排除api_doc)

python version >= 3.7 (支持延迟注释)

以下代码没有特别说明, 都默认以starlette框架为例

愿景

  • 1.代码即文档。

  • 2.使开发者可以通过最少的代码实现最全的功能。

功能

  • 参数校验和自动转化(参数校验依赖于Pydantic)
  • 参数关系依赖校验
  • 自动生成openapi文件
  • 支持swagger,redoc路由
  • 支持mock响应
  • TestClient支持, 支持测试用例的响应结果校验
  • 支持插件拓展
  • 支持gRPC GateWay路由
  • 本地api文档管理

要求

Python3.7+

在项目中使用TypeHints

安装

pip3 install pait

示例

参数校验与文档生成

Pait使用方法很简单, 以starlette框架为例子:

from typing import Type
import uvicorn  # type: ignore
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route

from pait.app.starlette import pait, add_doc_route
from pait.field import Body
from pait.model.response import PaitJsonResponseModel 
from pydantic import BaseModel, Field


class DemoResponseModel(PaitJsonResponseModel):
    """响应结构体模型,可以供Pait使用"""
    class ResponseModel(BaseModel):
        uid: int = Field()
        user_name: str = Field()

    description: str = "demo response"
    response_data: Type[BaseModel] = ResponseModel


# 使用pait装饰器装饰函数
@pait(response_model_list=[DemoResponseModel])
async def demo_post(
    uid: int = Body.i(description="user id", gt=10, lt=1000),
    user_name: str = Body.i(description="user name", min_length=2, max_length=4)
) -> JSONResponse:
    # 获取对应的值进行返回
    return JSONResponse({'uid': uid, 'user_name': user_name})


app = Starlette(routes=[Route('/api', demo_post, methods=['POST'])])
# 注册OpenAPI接口
add_doc_route(app)
uvicorn.run(app)
这段代码添加高亮部分的代码,就完成了一个简单的Pait的使用,其中第24行使用了pait装饰器,这样Pait就可以管理到路由函数的输入和输出了。其中response_model_list参数声明这个路由函数的响应对象是DemoResponseModel,它继承于PaitJsonResponseModel,这代表被Pait管理的路由函数将会返回一个Json响应,同时DemoResponseModel对象的descriptionresponse_data分别是用于描述路由函数的响应对象文档和响应对象的结构类型。 而第26,27行则声明这个路由需要的参数,以及他们的参数要从哪里获取以及参数的限制规则是什么,第35行则是注册了文档路由,接着运行代码,并在浏览器访问: http://127.0.0.1:8000/swagger ,就可以看到SwaggerUI的页面,目前这个页面显示了两组接口:

其中一组是Pait doc自带的3个接口,另外一组是default,里面有我们刚创建的/api接口,点开/api接口后会弹出该接口的详情:

详情里的数据是由Pait通过读取函数签名以及传入的DemoResponseModel生成的, 接着可以点击try it out,并输入参数并点击Excute,既可以看到Curl命令生成结果以及服务器响应结果:

从结果可以看出,路由函数正常工作,而路由函数的参数是Pait自动从Json Body中提取uid和user_name的值并传入的。

插件

除了参数校验和文档生成外,Pait还拥有一个插件系统,通过插件系统可以拓展其它功能,比如Mock响应功能,它能根据ResponseModel来自动返回数据,即使这个路由没有数据返回,比如下面的代码:

from typing import Type
import uvicorn  # type: ignore
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route

from pait.app.starlette import pait, add_doc_route
from pait.app.starlette.plugin.mock_response import MockPlugin 
from pait.field import Body
from pait.model.response import PaitJsonResponseModel
from pydantic import BaseModel, Field


class DemoResponseModel(PaitJsonResponseModel):
    """响应结构体模型,可以供Pait使用"""
    class ResponseModel(BaseModel):
        uid: int = Field(example=999)
        user_name: str = Field()

    description: str = "demo response"
    response_data: Type[BaseModel] = ResponseModel


# 使用pait装饰器装饰函数
@pait(
    post_plugin_list=[MockPlugin.build()],
    response_model_list=[DemoResponseModel]
)
async def demo_post(
    uid: int = Body.i(description="user id", gt=10, lt=1000),
    user_name: str = Body.i(description="user name", min_length=2, max_length=4)
) -> JSONResponse:
    pass


app = Starlette(routes=[Route('/api', demo_post, methods=['POST'])])
# 注册OpenAPI接口
add_doc_route(app)
uvicorn.run(app)
该代码是根据上面的代码进行更改,它移除了返回响应,同时引入了高亮部分的代码,其中第17行中的uid: int = Field(example=999)指定了响应结构中uid的example值为999,接着运行代码,并运行上面Swagger返回的Curl命令:
➜  ~ curl -X 'POST' \
  'http://127.0.0.1:8000/api' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "uid": 666,
  "user_name": "so1n"
}'
{"uid":999,"user_name":""}
可以看到,该接口仍然可以返回响应,该响应是由Mock插件自动生成的,响应中uid的值是999,与我们代码中uid: int = Field(example=999)设定的值一致,而user_name的值则是默认的空字符串。

除此之外,Pait还有其它的插件和其它功能,将在后续的文档中详细介绍。

性能

Pait是基于Python自带的inspect实现函数签名提取, 基于Pydantic实现参数校验和类型转换,同时还使用了很多预加载设计,所以Pait的运行时性能表现十分优越。不过目前的Pait还在成长中, 还有许多需要优化的地方,欢迎通过issues一起优化。

使用示例

Pait针对每一个支持的Web框架都有完善的代码示例, 可以通过访问示例代码了解最佳实践:

回到页面顶部