sanic-api 0.2.9__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sanic_api/__init__.py +2 -20
- sanic_api/api/__init__.py +17 -2
- sanic_api/api/model.py +0 -46
- sanic_api/api/request.py +157 -0
- sanic_api/api/response.py +34 -0
- sanic_api/app.py +306 -0
- sanic_api/config/__init__.py +1 -1
- sanic_api/config/setting.py +69 -14
- sanic_api/logger/__init__.py +0 -1
- sanic_api/logger/config.py +74 -52
- sanic_api/logger/extension.py +130 -0
- sanic_api/openapi/__init__.py +0 -7
- sanic_api/utils/__init__.py +0 -0
- sanic_api/{enum.py → utils/enum.py} +1 -31
- sanic_api-0.3.0.dist-info/METADATA +160 -0
- sanic_api-0.3.0.dist-info/RECORD +19 -0
- {sanic_api-0.2.9.dist-info → sanic_api-0.3.0.dist-info}/WHEEL +1 -1
- example/__main__.py +0 -19
- example/api/__init__.py +0 -1
- example/api/t1/__init__.py +0 -2
- example/api/t1/t1_1.py +0 -22
- example/api/t1/t1_2.py +0 -9
- example/api/t2/__init__.py +0 -1
- example/api/t2/t2.py +0 -9
- example/api/t2/t3/__init__.py +0 -1
- example/api/t2/t3/t3.py +0 -9
- example/api/user.py +0 -89
- example/api/validator.py +0 -97
- example/app.py +0 -62
- example/settings.py +0 -10
- sanic_api/api/api.py +0 -177
- sanic_api/api/exception.py +0 -46
- sanic_api/api/extend.py +0 -25
- sanic_api/api/handle_exception.py +0 -61
- sanic_api/api/validators.py +0 -76
- sanic_api/config/sanic.py +0 -19
- sanic_api/config/sanic_api.py +0 -11
- sanic_api/logger/extend.py +0 -71
- sanic_api/logger/sanic_http.py +0 -68
- sanic_api/openapi/openapi.py +0 -102
- sanic_api/utils.py +0 -112
- sanic_api-0.2.9.dist-info/METADATA +0 -96
- sanic_api-0.2.9.dist-info/RECORD +0 -38
- /example/__init__.py → /sanic_api/openapi/extension.py +0 -0
- {sanic_api-0.2.9.dist-info → sanic_api-0.3.0.dist-info}/licenses/LICENSE.txt +0 -0
sanic_api/logger/extend.py
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import logging.config
|
3
|
-
import sys
|
4
|
-
import time
|
5
|
-
|
6
|
-
from loguru import logger
|
7
|
-
|
8
|
-
# noinspection PyProtectedMember
|
9
|
-
from loguru._defaults import env
|
10
|
-
from sanic import HTTPResponse, Request
|
11
|
-
from sanic.application.constants import Mode
|
12
|
-
from sanic.server import HttpProtocol
|
13
|
-
from sanic_ext import Extension
|
14
|
-
|
15
|
-
from sanic_api.logger.config import InterceptHandler
|
16
|
-
from sanic_api.logger.sanic_http import SanicHttp
|
17
|
-
|
18
|
-
|
19
|
-
class LoggerExtend(Extension):
|
20
|
-
"""
|
21
|
-
处理日志的扩展
|
22
|
-
"""
|
23
|
-
|
24
|
-
name = "LoggerExtend"
|
25
|
-
|
26
|
-
def startup(self, bootstrap) -> None:
|
27
|
-
if not self.included():
|
28
|
-
return
|
29
|
-
|
30
|
-
log_level = logging.DEBUG if self.app.state.mode is Mode.DEBUG else logging.INFO
|
31
|
-
log_format = env(
|
32
|
-
"LOGURU_FORMAT",
|
33
|
-
str,
|
34
|
-
"<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
|
35
|
-
"<red>{extra[type]: <10}</red> | "
|
36
|
-
"<level>{level: <8}</level> | "
|
37
|
-
"<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - {extra[req_id]}<level>{message}</level>",
|
38
|
-
)
|
39
|
-
logger.remove()
|
40
|
-
logger.add(sys.stdout, colorize=True, format=log_format)
|
41
|
-
|
42
|
-
logging.basicConfig(handlers=[InterceptHandler()], level=log_level, force=True)
|
43
|
-
|
44
|
-
HttpProtocol.HTTP_CLASS = SanicHttp
|
45
|
-
self.app.on_request(self.proc_request, priority=999)
|
46
|
-
self.app.on_response(self.proc_response, priority=0)
|
47
|
-
|
48
|
-
async def proc_request(self, request: Request):
|
49
|
-
"""
|
50
|
-
处理请求的中间件
|
51
|
-
Args:
|
52
|
-
request:
|
53
|
-
|
54
|
-
Returns:
|
55
|
-
|
56
|
-
"""
|
57
|
-
request.ctx.st = time.perf_counter()
|
58
|
-
|
59
|
-
async def proc_response(self, request: Request, response: HTTPResponse):
|
60
|
-
"""
|
61
|
-
处理响应的中间件
|
62
|
-
Args:
|
63
|
-
request: 请求响应
|
64
|
-
response: 响应
|
65
|
-
|
66
|
-
Returns:
|
67
|
-
|
68
|
-
"""
|
69
|
-
request.ctx.et = time.perf_counter()
|
70
|
-
|
71
|
-
return response
|
sanic_api/logger/sanic_http.py
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
from sanic import Request
|
2
|
-
from sanic.http import Http
|
3
|
-
from sanic.log import access_logger
|
4
|
-
|
5
|
-
from sanic_api.utils import json_dumps
|
6
|
-
|
7
|
-
|
8
|
-
class SanicHttp(Http):
|
9
|
-
def log_response(self) -> None:
|
10
|
-
"""
|
11
|
-
自定义输出访问日志
|
12
|
-
Returns:
|
13
|
-
|
14
|
-
"""
|
15
|
-
req, res = self.request, self.response
|
16
|
-
|
17
|
-
dt = (req.ctx.et - req.ctx.st) * 1000
|
18
|
-
size = getattr(self, "response_bytes_left", getattr(self, "response_size", -1))
|
19
|
-
req_args = self.get_req_args(req)
|
20
|
-
extra = {
|
21
|
-
"status": getattr(res, "status", 0),
|
22
|
-
"byte": self.format_size(size),
|
23
|
-
"host": "UNKNOWN",
|
24
|
-
"request": "nil",
|
25
|
-
"time": f"{dt:.4f} ms",
|
26
|
-
"req_args": f" args: {req_args}" if req_args else "",
|
27
|
-
}
|
28
|
-
if req is not None:
|
29
|
-
if req.remote_addr or req.ip:
|
30
|
-
extra["host"] = f"{req.remote_addr or req.ip}:{req.port}"
|
31
|
-
extra["request"] = f"{req.method} {req.url}"
|
32
|
-
access_logger.info("", extra=extra)
|
33
|
-
|
34
|
-
def format_size(self, size: float):
|
35
|
-
"""
|
36
|
-
格式化输出大小
|
37
|
-
:param size: 大小
|
38
|
-
:return: 返回格式化的字符串
|
39
|
-
"""
|
40
|
-
for count in ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]:
|
41
|
-
if -1024.0 < size < 1024.0:
|
42
|
-
return f"{size:3.1f} {count}"
|
43
|
-
size /= 1024.0
|
44
|
-
return f"{size:3.1f} YB"
|
45
|
-
|
46
|
-
def get_req_args(self, request: Request) -> str:
|
47
|
-
"""
|
48
|
-
获取请求参数
|
49
|
-
Args:
|
50
|
-
request: 请求
|
51
|
-
|
52
|
-
Returns:
|
53
|
-
返回具有 json、query、form参数的json
|
54
|
-
"""
|
55
|
-
data = {}
|
56
|
-
for attr in ["args", "form"]:
|
57
|
-
attr_data = {}
|
58
|
-
for k, v in getattr(request, attr).items():
|
59
|
-
if type(v) == list and len(v) == 1:
|
60
|
-
attr_data[k] = v[0]
|
61
|
-
else:
|
62
|
-
attr_data[k] = v
|
63
|
-
if attr_data:
|
64
|
-
data[attr] = attr_data
|
65
|
-
if request.json:
|
66
|
-
data["json"] = request.json
|
67
|
-
|
68
|
-
return json_dumps(data) if data else ""
|
sanic_api/openapi/openapi.py
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
from pydantic import BaseModel
|
2
|
-
from sanic import Sanic
|
3
|
-
from sanic_ext.extensions.openapi.builders import (
|
4
|
-
OperationBuilder,
|
5
|
-
OperationStore,
|
6
|
-
SpecificationBuilder,
|
7
|
-
)
|
8
|
-
from sanic_ext.extensions.openapi.definitions import Schema
|
9
|
-
from sanic_ext.extensions.openapi.types import Array, Object
|
10
|
-
from sanic_ext.utils.route import get_all_routes
|
11
|
-
|
12
|
-
from sanic_api.api import API
|
13
|
-
from sanic_api.api.model import ListRespModel
|
14
|
-
from sanic_api.api.validators import get_handler_param
|
15
|
-
|
16
|
-
|
17
|
-
# noinspection PyProtectedMember
|
18
|
-
def auto_doc(app: Sanic):
|
19
|
-
config = app.config
|
20
|
-
specification = SpecificationBuilder()
|
21
|
-
|
22
|
-
for (
|
23
|
-
uri,
|
24
|
-
route_name,
|
25
|
-
_route_parameters,
|
26
|
-
method_handlers,
|
27
|
-
_host,
|
28
|
-
) in get_all_routes(app, config.OAS_URL_PREFIX):
|
29
|
-
uri = uri if uri == "/" else uri.rstrip("/")
|
30
|
-
|
31
|
-
for method, _handler in method_handlers:
|
32
|
-
if (
|
33
|
-
(method == "OPTIONS" and app.config.OAS_IGNORE_OPTIONS)
|
34
|
-
or (method == "HEAD" and app.config.OAS_IGNORE_HEAD)
|
35
|
-
or method == "TRACE"
|
36
|
-
):
|
37
|
-
continue
|
38
|
-
|
39
|
-
if hasattr(_handler, "view_class"):
|
40
|
-
_handler = getattr(_handler.view_class, method.lower())
|
41
|
-
operation: OperationBuilder = OperationStore()[_handler]
|
42
|
-
|
43
|
-
if operation._exclude or "openapi" in operation.tags:
|
44
|
-
continue
|
45
|
-
|
46
|
-
api_cls = get_handler_param(_handler)
|
47
|
-
if not api_cls:
|
48
|
-
continue
|
49
|
-
|
50
|
-
api: API = api_cls()
|
51
|
-
|
52
|
-
# 读取蓝图上面的 blueprint.ctx.desc 属性来代替name设置中文tag名
|
53
|
-
if len(route_name.split(".")) > 1:
|
54
|
-
blueprint = app.blueprints[route_name.split(".")[0]]
|
55
|
-
blueprint.ctx.desc = blueprint.ctx.desc or blueprint.name
|
56
|
-
api.tags.insert(0, blueprint.ctx.desc)
|
57
|
-
|
58
|
-
# 设置接口的标签和描述
|
59
|
-
tags = set(api.tags)
|
60
|
-
operation.tag(*tags)
|
61
|
-
tags_str = " ".join([f"[{tag}](/docs#tag/{tag})" for tag in tags])
|
62
|
-
operation.describe(description=f"### 标签: {tags_str}\n{api.description}")
|
63
|
-
|
64
|
-
if api.json_req_type:
|
65
|
-
body_type = api.json_req_type
|
66
|
-
mine_type = "application/json"
|
67
|
-
elif api.form_req_type:
|
68
|
-
body_type = api.form_req_type
|
69
|
-
mine_type = "application/x-www-form-urlencoded"
|
70
|
-
else:
|
71
|
-
body_type, mine_type, body_dict = ["", "", {}]
|
72
|
-
|
73
|
-
if body_type:
|
74
|
-
body_schema: dict = body_type.schema(ref_template="#/components/schemas/{model}")
|
75
|
-
body_dict = {
|
76
|
-
mine_type: Object(body_schema["properties"]),
|
77
|
-
}
|
78
|
-
for model_name, schema_model in body_schema.get("definitions", {}).items():
|
79
|
-
specification.add_component("schemas", model_name, schema_model)
|
80
|
-
body_dict[mine_type]._fields["required"] = body_schema.get("required", [])
|
81
|
-
operation.body(body_dict)
|
82
|
-
|
83
|
-
if api.query_req_type:
|
84
|
-
for k, v in api.query_req_type.schema()["properties"].items(): # type: (str, dict)
|
85
|
-
operation.parameter(k, Schema(**v))
|
86
|
-
|
87
|
-
if api.response_type and issubclass(api.response_type, BaseModel):
|
88
|
-
resp_schema = api.response_type.schema(ref_template="#/components/schemas/{model}")
|
89
|
-
schema: Schema = Object(resp_schema["properties"])
|
90
|
-
if issubclass(api.response_type, ListRespModel):
|
91
|
-
schema = Array(schema)
|
92
|
-
for model_name, schema_model in resp_schema.get("definitions", {}).items():
|
93
|
-
specification.add_component("schemas", model_name, schema_model)
|
94
|
-
operation.response(
|
95
|
-
status=200,
|
96
|
-
content={"application/json": schema},
|
97
|
-
description="成功",
|
98
|
-
)
|
99
|
-
specification.add_component("schemas", api.response_type.__name__, schema)
|
100
|
-
|
101
|
-
operation._app = app
|
102
|
-
specification.operation(uri, method, operation)
|
sanic_api/utils.py
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
from decimal import Decimal
|
2
|
-
from importlib import import_module
|
3
|
-
from pathlib import Path
|
4
|
-
from typing import Dict, List, Optional
|
5
|
-
|
6
|
-
import orjson
|
7
|
-
from sanic import Blueprint, Request, Sanic
|
8
|
-
from sanic.blueprint_group import BlueprintGroup
|
9
|
-
from sanic.exceptions import ServerError as SanicServerError
|
10
|
-
|
11
|
-
|
12
|
-
def getpath_by_root(path: str) -> Path:
|
13
|
-
"""
|
14
|
-
根据根目录获取路径
|
15
|
-
基于 os.getcwd() 的同级路径、父目录来获取
|
16
|
-
Args:
|
17
|
-
path: 相对server的子路径
|
18
|
-
|
19
|
-
Returns:
|
20
|
-
完整路径
|
21
|
-
"""
|
22
|
-
return (Path.cwd() / path).absolute()
|
23
|
-
|
24
|
-
|
25
|
-
def json_dumps(data: dict, default=None) -> str:
|
26
|
-
"""
|
27
|
-
调用orjson进行dumps
|
28
|
-
Args:
|
29
|
-
data: 数据
|
30
|
-
default: 数量处理方法
|
31
|
-
|
32
|
-
Returns:
|
33
|
-
返回json字符串
|
34
|
-
"""
|
35
|
-
|
36
|
-
def _default(item):
|
37
|
-
if isinstance(item, Decimal):
|
38
|
-
return float(item.to_eng_string())
|
39
|
-
|
40
|
-
json_bytes = orjson.dumps(
|
41
|
-
data,
|
42
|
-
default=default or _default,
|
43
|
-
option=orjson.OPT_APPEND_NEWLINE | orjson.OPT_INDENT_2,
|
44
|
-
)
|
45
|
-
return json_bytes.decode("utf-8")
|
46
|
-
|
47
|
-
|
48
|
-
def get_current_request() -> Optional[Request]:
|
49
|
-
""" "
|
50
|
-
获取当前请求
|
51
|
-
"""
|
52
|
-
try:
|
53
|
-
return Request.get_current()
|
54
|
-
except SanicServerError:
|
55
|
-
return None
|
56
|
-
|
57
|
-
|
58
|
-
def auto_blueprint(sanic_app: Sanic, base_api_module_name: str) -> None:
|
59
|
-
"""
|
60
|
-
自动生成蓝图
|
61
|
-
Args:
|
62
|
-
sanic_app: app
|
63
|
-
base_api_module_name: api层模块名称
|
64
|
-
|
65
|
-
Returns:
|
66
|
-
|
67
|
-
"""
|
68
|
-
# 导入base_api_module_name模块并获取其文件夹路径
|
69
|
-
base_api_dir: Path = Path.cwd() / base_api_module_name
|
70
|
-
|
71
|
-
# 创建根API蓝图组
|
72
|
-
root_group: BlueprintGroup = BlueprintGroup(base_api_module_name)
|
73
|
-
|
74
|
-
blueprint_group_map: Dict[str, BlueprintGroup] = {}
|
75
|
-
|
76
|
-
# 遍历所有__init__.py文件,查找蓝图并创建对应的蓝图组
|
77
|
-
init_files: List[Path] = list(base_api_dir.glob("**/__init__.py"))
|
78
|
-
for file in reversed(init_files):
|
79
|
-
# 忽略__init__.py
|
80
|
-
init_file: Path = file.parent
|
81
|
-
# 获取该蓝图所在的模块路径和名称
|
82
|
-
module_path: str = init_file.relative_to(base_api_dir.parent).with_suffix("").as_posix()
|
83
|
-
module_name: str = module_path.replace("/", ".")
|
84
|
-
|
85
|
-
# 导入蓝图所在的模块,并获取该模块下的所有蓝图
|
86
|
-
module = import_module(module_name, base_api_module_name)
|
87
|
-
blueprints = [getattr(module, attr) for attr in dir(module) if isinstance(getattr(module, attr), Blueprint)]
|
88
|
-
# 拆分模块路径,创建对应的蓝图组并添加到父级蓝图组中
|
89
|
-
parts = [path for path in module_path.split("/") if path not in [base_api_module_name, init_file.name]]
|
90
|
-
|
91
|
-
if len(blueprints) == 1:
|
92
|
-
blueprint = blueprints[0]
|
93
|
-
if not parts:
|
94
|
-
blueprint_group = blueprint_group_map.get(init_file.name)
|
95
|
-
if blueprint_group:
|
96
|
-
blueprint.url_prefix = ""
|
97
|
-
blueprint_group.append(blueprint)
|
98
|
-
root_group.append(blueprint_group)
|
99
|
-
else:
|
100
|
-
root_group.append(blueprint)
|
101
|
-
else:
|
102
|
-
for part in parts:
|
103
|
-
group = blueprint_group_map.get(part, BlueprintGroup(part))
|
104
|
-
group.append(blueprint)
|
105
|
-
blueprint_group_map[part] = group
|
106
|
-
else:
|
107
|
-
group = BlueprintGroup(init_file.name)
|
108
|
-
group.extend(blueprints)
|
109
|
-
root_group.append(group)
|
110
|
-
|
111
|
-
# 将根API蓝图组添加到应用中
|
112
|
-
sanic_app.blueprint(root_group)
|
@@ -1,96 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: sanic-api
|
3
|
-
Version: 0.2.9
|
4
|
-
Summary: Sanic 框架实用API工具集,拥有自动生成文档、参数校验、配置的导入、日志功能的优化等功能,更好的助力接口的开发
|
5
|
-
License: MIT
|
6
|
-
Author-email: 昊色居士 <xhrtxh@gmail.com>
|
7
|
-
Requires-Python: >=3.8,<3.12
|
8
|
-
Requires-Dist: hs-config>=0.1.0
|
9
|
-
Requires-Dist: loguru>=0.6.0
|
10
|
-
Requires-Dist: orjson>=3.8.6
|
11
|
-
Requires-Dist: pygments>=2.13.0
|
12
|
-
Requires-Dist: sanic[ext]>=23.6.0
|
13
|
-
Requires-Dist: setuptools>=68.0.0
|
14
|
-
Requires-Dist: ujson>=5.7.0
|
15
|
-
Description-Content-Type: text/markdown
|
16
|
-
|
17
|
-

|
18
|
-
|
19
|
-
[](https://choosealicense.com/licenses/mit/)
|
20
|
-
[]()
|
21
|
-
[](http://www.gnu.org/licenses/agpl-3.0)
|
22
|
-
[](https://github.com/psf/black)
|
23
|
-
|
24
|
-
# Sanic-API
|
25
|
-
|
26
|
-
让您的sanic服务程序更好的支持API文档、参数校验、日志打印、响应规范等
|
27
|
-
|
28
|
-
## 特性
|
29
|
-
|
30
|
-
- 无需任何多余改动,全自动生成openapi文档,使用更加方便
|
31
|
-
|
32
|
-
- 基于`pydantic`的参数校验器,让接口的请求及响应更符合你的预期
|
33
|
-
|
34
|
-
- 使用`loguru`库代替官方`logging`日志库,并对访问日志进行扩展,支持打印接口耗时、接口参数
|
35
|
-
|
36
|
-
- 使用`{code: 0, data: null, msg: ""}`样式的接口返回
|
37
|
-
|
38
|
-
- 对接口中的异常进行拦截,及自定义错误码
|
39
|
-
|
40
|
-
- 接口返回样式可自定义配置
|
41
|
-
|
42
|
-
## 截图
|
43
|
-
|
44
|
-
## 路线图
|
45
|
-
|
46
|
-
- 增加一键生成预设项目cli命令
|
47
|
-
|
48
|
-
- 编写详细文档
|
49
|
-
|
50
|
-
- API接口增加请求头、URL路径参数收集和校验:
|
51
|
-
|
52
|
-
## 安装
|
53
|
-
|
54
|
-
使用 pip 安装 sanic-api
|
55
|
-
|
56
|
-
```bash
|
57
|
-
pip install sanic-api
|
58
|
-
```
|
59
|
-
|
60
|
-
## 使用方法/示例
|
61
|
-
|
62
|
-
```python
|
63
|
-
from sanic import Sanic, text
|
64
|
-
from sanic_api import init_api
|
65
|
-
|
66
|
-
app = Sanic("Sanic-API")
|
67
|
-
|
68
|
-
|
69
|
-
@app.get('/')
|
70
|
-
async def index(request):
|
71
|
-
return text("Sanic-API Example")
|
72
|
-
|
73
|
-
|
74
|
-
def main():
|
75
|
-
init_api(app)
|
76
|
-
app.run(access_log=True)
|
77
|
-
|
78
|
-
|
79
|
-
if __name__ == '__main__':
|
80
|
-
main()
|
81
|
-
|
82
|
-
```
|
83
|
-
|
84
|
-
## 开发
|
85
|
-
|
86
|
-
要部署这个项目,请运行
|
87
|
-
|
88
|
-
```bash
|
89
|
-
pip install pdm
|
90
|
-
pdm sync
|
91
|
-
```
|
92
|
-
|
93
|
-
## 文档
|
94
|
-
|
95
|
-
[文档](https://linktodocumentation)
|
96
|
-
|
sanic_api-0.2.9.dist-info/RECORD
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
example/__main__.py,sha256=shOhgu0-e98nRuhXGzhi3rWsiZmpXZ9SDBLhgwvsFIY,605
|
3
|
-
example/api/__init__.py,sha256=itThNDyCx_NwzUqClx_8igf1FHakygEz9y2v8tJamkE,34
|
4
|
-
example/api/t1/__init__.py,sha256=KJ90I8L3UhOgUXA_uyoD06Rqz01mzhPeDqA7lpZXY38,66
|
5
|
-
example/api/t1/t1_1.py,sha256=78QCk_BwCs_6s9nnkuWPGoHaNosujvUcJVsCjvn_Xhg,634
|
6
|
-
example/api/t1/t1_2.py,sha256=071pQz-611GuY_DSKnZkRKdSh0J15fVPphTMvodexqc,233
|
7
|
-
example/api/t2/__init__.py,sha256=Ni_NSedOlsH73KmeW5nW4J26MhBmbHg_1NbrJ3d72Co,29
|
8
|
-
example/api/t2/t2.py,sha256=NqXZOKKZUmuLd2ce8TwtbBdIEkScbma8ngK5d_xxWXc,248
|
9
|
-
example/api/t2/t3/__init__.py,sha256=2PBSrojyYILtU7rVFTBh-ULIFmboXQTbBr1vJ7h7c50,29
|
10
|
-
example/api/t2/t3/t3.py,sha256=Kw7h0I43CMpan3tSmlecFHcQTao_X9dXVmYJUSd-Wz0,248
|
11
|
-
example/api/user.py,sha256=BwAKVaaCylu_RfwcmIs2459ojgI9_hjg5fA9Whytcog,1844
|
12
|
-
example/api/validator.py,sha256=-eZcXOIhaB-N-MlhVyHFzK6u6CnNBALKJsfC2nOyNho,1722
|
13
|
-
example/app.py,sha256=_MJrYtVxcUz2a_ULYlXmqwPzRwaDyx3OF3QIZhJDaL0,1202
|
14
|
-
example/settings.py,sha256=0HkZcxc7ArZfP_x31A9amL-cOw98XVjAxszOMj0PHII,134
|
15
|
-
sanic_api/__init__.py,sha256=U2PtA7oaz_UtUqNg40fnpTAwroxxUle4XaEfi1EqDJY,348
|
16
|
-
sanic_api/api/__init__.py,sha256=0Tb6LsOFscOqYCzgiZbR7UqP_cPGOOE-5is8YclWhI4,51
|
17
|
-
sanic_api/api/api.py,sha256=SmGoSS7bnhVNH_RYMLXS3dCUuZD2rWy7ZXXVbi_9MBc,5486
|
18
|
-
sanic_api/api/exception.py,sha256=hs4SpDLQjqGCKgQOa1WNocbTqheoIulr5Bplpm0Mc0w,1216
|
19
|
-
sanic_api/api/extend.py,sha256=So_X0KgkYeOhDwFIziU1Q8qkeoPeIRisBU5nOMpJaUw,706
|
20
|
-
sanic_api/api/handle_exception.py,sha256=Opq18Y1loRfBKtr_UTAyLMLT-C4vORnHFRhHKFNKX0o,1206
|
21
|
-
sanic_api/api/model.py,sha256=vdIBfkJzQpAKKG5LpdFlH9UlbrNhUlcrG0rmFgh6QUY,1071
|
22
|
-
sanic_api/api/validators.py,sha256=TCb0eRfKfTt11HN-x6u7Ci2j6cpH6UKDKGceaKU2TxE,2078
|
23
|
-
sanic_api/config/__init__.py,sha256=G59ZgoVTr9dSvjDKh6y3_CkFn_uwbKPi0C3wlvK37xw,37
|
24
|
-
sanic_api/config/sanic.py,sha256=BLKJgwsLVJvT1YlmW21FQXEwxSIHAhngu9Zwqe8Qh6M,636
|
25
|
-
sanic_api/config/sanic_api.py,sha256=jIgrlOizjh3eXxiUhQ9RFiG5noAuvjTju27a4mL-xgU,373
|
26
|
-
sanic_api/config/setting.py,sha256=oGvqkUhQVbPWhoPLPZ6uVOwwSpw8JWqJtzjvYa4YLFA,719
|
27
|
-
sanic_api/enum.py,sha256=bBbYeys4CHI22sD_My8EIewOOznXb0nQmuIPKzZn-EM,2040
|
28
|
-
sanic_api/logger/__init__.py,sha256=HPUhYmmzI-NHOo6uf8NGmMlSSN3gkGrmUN6TB5Qhxmc,33
|
29
|
-
sanic_api/logger/config.py,sha256=1eEEp3YpoTCywgOeE8OZp4X0ghF4E9W52FBEAlTCVfw,2511
|
30
|
-
sanic_api/logger/extend.py,sha256=rD7NxUFZE2esPUbpOlYul5ZNnDTjepPsu9iLgZ9JA00,1911
|
31
|
-
sanic_api/logger/sanic_http.py,sha256=Nl1dM54XLTRO99rmzUbpR_vi-wSN_eK_9pei1kNJ7UE,2102
|
32
|
-
sanic_api/openapi/__init__.py,sha256=_n-pklcQHcaor8WrJMGxc4HYNggZBfe3mmbkCN57fVI,146
|
33
|
-
sanic_api/openapi/openapi.py,sha256=2Y3J8CJeT5LTLJGsQoCS98QGAZcyE3HgRTKWT2LKoao,4147
|
34
|
-
sanic_api/utils.py,sha256=9dv_FWHb6ynuzoupOvIFPkar5Y0dlrFF977LjKIysHc,3564
|
35
|
-
sanic_api-0.2.9.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
|
36
|
-
sanic_api-0.2.9.dist-info/METADATA,sha256=T7Z6L2QAvzOSjG8PQ3c84ekwDew70rP3WKk60U8mi7w,2312
|
37
|
-
sanic_api-0.2.9.dist-info/licenses/LICENSE.txt,sha256=T20w-F8AfuFO9CHy2mSk_An6T9eV4X4rGA01i-gp4M4,1090
|
38
|
-
sanic_api-0.2.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|