sanic-api 0.2.5__py3-none-any.whl → 0.2.7__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/api/model.py CHANGED
@@ -1,45 +1,45 @@
1
- from typing import Optional, Union
2
-
3
- from pydantic.fields import ModelField, ModelPrivateAttr
4
- from pydantic.main import BaseModel
5
-
6
-
7
- class ResponseModel(BaseModel):
8
- """
9
- 响应基础模型
10
- """
11
-
12
- def __new__(cls, *args, **kwargs):
13
- for _field, value in cls.__fields__.items():
14
- if not isinstance(value, ModelField):
15
- continue
16
- value.required = False
17
-
18
- return super().__new__(cls, *args, **kwargs)
19
-
20
-
21
- class ListRespModel(ResponseModel):
22
- """
23
- 列表格式的响应基础模型
24
- """
25
-
26
- _data_list: Optional[Union[ModelPrivateAttr, list]] = ModelPrivateAttr(default_factory=list)
27
-
28
- def add_data(self):
29
- """
30
- 当前模型下数据添加到列表中
31
- Returns:
32
-
33
- """
34
- data = self.dict()
35
- self._data_list.append(data)
36
- for attr in data.keys():
37
- self.__setattr__(attr, None)
38
-
39
- def to_list(self):
40
- """
41
- 返回列表响应数据
42
- Returns:
43
-
44
- """
45
- return self._data_list
1
+ from typing import Optional, Union
2
+
3
+ from pydantic.fields import ModelField, ModelPrivateAttr
4
+ from pydantic.main import BaseModel
5
+
6
+
7
+ class ResponseModel(BaseModel):
8
+ """
9
+ 响应基础模型
10
+ """
11
+
12
+ def __new__(cls, *args, **kwargs):
13
+ for _field, value in cls.__fields__.items():
14
+ if not isinstance(value, ModelField):
15
+ continue
16
+ value.required = False
17
+
18
+ return super().__new__(cls, *args, **kwargs)
19
+
20
+
21
+ class ListRespModel(ResponseModel):
22
+ """
23
+ 列表格式的响应基础模型
24
+ """
25
+
26
+ _data_list: Optional[Union[ModelPrivateAttr, list]] = ModelPrivateAttr(default_factory=list)
27
+
28
+ def add_data(self):
29
+ """
30
+ 当前模型下数据添加到列表中
31
+ Returns:
32
+
33
+ """
34
+ data = self.dict()
35
+ self._data_list.append(data)
36
+ for attr in data.keys():
37
+ self.__setattr__(attr, None)
38
+
39
+ def to_list(self):
40
+ """
41
+ 返回列表响应数据
42
+ Returns:
43
+
44
+ """
45
+ return self._data_list
@@ -1,76 +1,76 @@
1
- import inspect
2
-
3
- from sanic import Request
4
-
5
- from sanic_api.api import API
6
- from sanic_api.api.exception import ValidationInitError
7
- from sanic_api.enum import ParamEnum
8
-
9
-
10
- def _do_validation(param_enum: ParamEnum, api: API, data: dict):
11
- if param_enum == ParamEnum.JSON:
12
- req_data = data
13
- elif param_enum in [ParamEnum.QUERY, param_enum.FORM]:
14
- req_data = {}
15
- for k, v in data.items():
16
- if type(v) == list and len(v) == 1:
17
- req_data[k] = v[0]
18
- else:
19
- req_data[k] = v
20
- else:
21
- raise ValidationInitError("未知的验证器类型")
22
-
23
- api.validate_params(req_data, param_enum)
24
-
25
-
26
- def get_handler_param(handler):
27
- """
28
- 获取参数处理器的json、form、query参数
29
- Args:
30
- handler:
31
-
32
- Returns:
33
-
34
- """
35
- sig = inspect.signature(handler)
36
- api_parameter = sig.parameters.get("api")
37
- api_cls = api_parameter.annotation if api_parameter else None
38
- return api_cls
39
-
40
-
41
- async def validators(request: Request):
42
- """
43
- 校验请求参数中间件
44
- Args:
45
- request: 请求
46
-
47
- Returns:
48
-
49
- """
50
- # 如果执行中间价直接就发生了异常则直接抛出
51
- if hasattr(request.ctx, "exception"):
52
- raise request.ctx.exception
53
-
54
- _, handler, _ = request.app.router.get(
55
- request.path,
56
- request.method,
57
- request.headers.getone("host", None),
58
- )
59
-
60
- api_cls = get_handler_param(handler)
61
- if not api_cls:
62
- return
63
-
64
- api: API = api_cls()
65
- if api.json_req_type and api.query_req_type:
66
- raise ValidationInitError("不能同时存在json参数和form参数")
67
-
68
- if api.json_req_type and request.json:
69
- _do_validation(param_enum=ParamEnum.JSON, api=api, data=request.json)
70
- elif api.form_req_type and request.form:
71
- _do_validation(param_enum=ParamEnum.FORM, api=api, data=request.form)
72
- if api.query_req_type and request.query_args:
73
- _do_validation(param_enum=ParamEnum.QUERY, api=api, data=request.args)
74
-
75
- request.match_info.update({"api": api})
76
- request.ctx.api = api
1
+ import inspect
2
+
3
+ from sanic import Request
4
+
5
+ from sanic_api.api import API
6
+ from sanic_api.api.exception import ValidationInitError
7
+ from sanic_api.enum import ParamEnum
8
+
9
+
10
+ def _do_validation(param_enum: ParamEnum, api: API, data: dict):
11
+ if param_enum == ParamEnum.JSON:
12
+ req_data = data
13
+ elif param_enum in [ParamEnum.QUERY, param_enum.FORM]:
14
+ req_data = {}
15
+ for k, v in data.items():
16
+ if type(v) == list and len(v) == 1:
17
+ req_data[k] = v[0]
18
+ else:
19
+ req_data[k] = v
20
+ else:
21
+ raise ValidationInitError("未知的验证器类型")
22
+
23
+ api.validate_params(req_data, param_enum)
24
+
25
+
26
+ def get_handler_param(handler):
27
+ """
28
+ 获取参数处理器的json、form、query参数
29
+ Args:
30
+ handler:
31
+
32
+ Returns:
33
+
34
+ """
35
+ sig = inspect.signature(handler)
36
+ api_parameter = sig.parameters.get("api")
37
+ api_cls = api_parameter.annotation if api_parameter else None
38
+ return api_cls
39
+
40
+
41
+ async def validators(request: Request):
42
+ """
43
+ 校验请求参数中间件
44
+ Args:
45
+ request: 请求
46
+
47
+ Returns:
48
+
49
+ """
50
+ # 如果执行中间价直接就发生了异常则直接抛出
51
+ if hasattr(request.ctx, "exception"):
52
+ raise request.ctx.exception
53
+
54
+ _, handler, _ = request.app.router.get(
55
+ request.path,
56
+ request.method,
57
+ request.headers.getone("host", None),
58
+ )
59
+
60
+ api_cls = get_handler_param(handler)
61
+ if not api_cls:
62
+ return
63
+
64
+ api: API = api_cls()
65
+ if api.json_req_type and api.query_req_type:
66
+ raise ValidationInitError("不能同时存在json参数和form参数")
67
+
68
+ if api.json_req_type and request.json:
69
+ _do_validation(param_enum=ParamEnum.JSON, api=api, data=request.json)
70
+ elif api.form_req_type and request.form:
71
+ _do_validation(param_enum=ParamEnum.FORM, api=api, data=request.form)
72
+ if api.query_req_type and request.query_args:
73
+ _do_validation(param_enum=ParamEnum.QUERY, api=api, data=request.args)
74
+
75
+ request.match_info.update({"api": api})
76
+ request.ctx.api = api
@@ -1,2 +1,2 @@
1
- from .base import SettingsBase
2
- from .setting import DefaultSettings
1
+ from .base import SettingsBase
2
+ from .setting import DefaultSettings
sanic_api/config/base.py CHANGED
@@ -1,110 +1,110 @@
1
- import json
2
- from configparser import ConfigParser
3
- from pathlib import Path
4
- from typing import Any, Dict, Tuple
5
-
6
- import yaml
7
- from pydantic import BaseSettings
8
- from pydantic.env_settings import SettingsSourceCallable
9
-
10
- from sanic_api.utils import getpath_by_root
11
-
12
-
13
- class CustomSettingsSource:
14
- """
15
- 自定义的配置文件来源基类
16
- """
17
-
18
- def __init__(self, path: Path):
19
- self.path = path
20
-
21
- def __repr__(self) -> str:
22
- return f"{self.__class__.__name__}(path={self.path!r})"
23
-
24
-
25
- class JsonSettingsSource(CustomSettingsSource):
26
- """
27
- json文件来源导入配置项
28
- """
29
-
30
- def __call__(self, settings: BaseSettings) -> Dict[str, Any]:
31
- encoding = settings.__config__.env_file_encoding
32
- return json.loads(self.path.read_text(encoding))
33
-
34
-
35
- class IniSettingsSource(CustomSettingsSource):
36
- """
37
- ini文件来源导入配置项
38
- """
39
-
40
- def __call__(self, settings: BaseSettings) -> Dict[str, Any]:
41
- encoding = settings.__config__.env_file_encoding
42
- parser = ConfigParser()
43
- parser.read(self.path, encoding)
44
- return getattr(parser, "_sections", {}).get("settings", {})
45
-
46
-
47
- class YamlSettingsSource(CustomSettingsSource):
48
- """
49
- Yaml文件来源导入配置项
50
- """
51
-
52
- def __call__(self, settings: BaseSettings) -> Dict[str, Any]:
53
- encoding = settings.__config__.env_file_encoding
54
- return yaml.safe_load(self.path.read_text(encoding))
55
-
56
-
57
- class SettingsBase(BaseSettings):
58
- """
59
- 项目设置的基类
60
- """
61
-
62
- class Config:
63
- root_config_dir = getpath_by_root("../configs")
64
- env_file = root_config_dir / ".env"
65
- env_file_encoding = "utf-8"
66
- env_nested_delimiter = "__"
67
-
68
- @classmethod
69
- def customise_sources(
70
- cls,
71
- init_settings: SettingsSourceCallable,
72
- env_settings: SettingsSourceCallable,
73
- file_secret_settings: SettingsSourceCallable,
74
- ) -> Tuple[SettingsSourceCallable, ...]:
75
- """
76
- 自定义配置来源
77
- Args:
78
- init_settings: 初始化设置
79
- env_settings:环境变量设置
80
- file_secret_settings:加密文件设置
81
-
82
- Returns:
83
-
84
- """
85
- # 默认的设置
86
- default_settings = {
87
- init_settings,
88
- env_settings,
89
- file_secret_settings,
90
- }
91
-
92
- # json 配置文件
93
- json_file = cls.root_config_dir / "settings.json"
94
- if json_file.exists():
95
- json_settings_source = JsonSettingsSource(json_file)
96
- default_settings.add(json_settings_source)
97
-
98
- # ini配置文件
99
- ini_file = cls.root_config_dir / "settings.ini"
100
- if ini_file.exists():
101
- ini_settings_source = IniSettingsSource(ini_file)
102
- default_settings.add(ini_settings_source)
103
-
104
- # yaml配置文件
105
- yaml_file = cls.root_config_dir / "settings.yaml"
106
- if yaml_file.exists():
107
- yaml_settings_source = YamlSettingsSource(yaml_file)
108
- default_settings.add(yaml_settings_source)
109
-
110
- return tuple(default_settings)
1
+ import json
2
+ from configparser import ConfigParser
3
+ from pathlib import Path
4
+ from typing import Any, Dict, Tuple
5
+
6
+ import yaml
7
+ from pydantic import BaseSettings
8
+ from pydantic.env_settings import SettingsSourceCallable
9
+
10
+ from sanic_api.utils import getpath_by_root
11
+
12
+
13
+ class CustomSettingsSource:
14
+ """
15
+ 自定义的配置文件来源基类
16
+ """
17
+
18
+ def __init__(self, path: Path):
19
+ self.path = path
20
+
21
+ def __repr__(self) -> str:
22
+ return f"{self.__class__.__name__}(path={self.path!r})"
23
+
24
+
25
+ class JsonSettingsSource(CustomSettingsSource):
26
+ """
27
+ json文件来源导入配置项
28
+ """
29
+
30
+ def __call__(self, settings: BaseSettings) -> Dict[str, Any]:
31
+ encoding = settings.__config__.env_file_encoding
32
+ return json.loads(self.path.read_text(encoding))
33
+
34
+
35
+ class IniSettingsSource(CustomSettingsSource):
36
+ """
37
+ ini文件来源导入配置项
38
+ """
39
+
40
+ def __call__(self, settings: BaseSettings) -> Dict[str, Any]:
41
+ encoding = settings.__config__.env_file_encoding
42
+ parser = ConfigParser()
43
+ parser.read(self.path, encoding)
44
+ return getattr(parser, "_sections", {}).get("settings", {})
45
+
46
+
47
+ class YamlSettingsSource(CustomSettingsSource):
48
+ """
49
+ Yaml文件来源导入配置项
50
+ """
51
+
52
+ def __call__(self, settings: BaseSettings) -> Dict[str, Any]:
53
+ encoding = settings.__config__.env_file_encoding
54
+ return yaml.safe_load(self.path.read_text(encoding))
55
+
56
+
57
+ class SettingsBase(BaseSettings):
58
+ """
59
+ 项目设置的基类
60
+ """
61
+
62
+ class Config:
63
+ root_config_dir = getpath_by_root("./configs")
64
+ env_file = root_config_dir / ".env"
65
+ env_file_encoding = "utf-8"
66
+ env_nested_delimiter = "__"
67
+
68
+ @classmethod
69
+ def customise_sources(
70
+ cls,
71
+ init_settings: SettingsSourceCallable,
72
+ env_settings: SettingsSourceCallable,
73
+ file_secret_settings: SettingsSourceCallable,
74
+ ) -> Tuple[SettingsSourceCallable, ...]:
75
+ """
76
+ 自定义配置来源
77
+ Args:
78
+ init_settings: 初始化设置
79
+ env_settings:环境变量设置
80
+ file_secret_settings:加密文件设置
81
+
82
+ Returns:
83
+
84
+ """
85
+ # 默认的设置
86
+ default_settings = {
87
+ init_settings,
88
+ env_settings,
89
+ file_secret_settings,
90
+ }
91
+
92
+ # json 配置文件
93
+ json_file = cls.root_config_dir / "settings.json"
94
+ if json_file.exists():
95
+ json_settings_source = JsonSettingsSource(json_file)
96
+ default_settings.add(json_settings_source)
97
+
98
+ # ini配置文件
99
+ ini_file = cls.root_config_dir / "settings.ini"
100
+ if ini_file.exists():
101
+ ini_settings_source = IniSettingsSource(ini_file)
102
+ default_settings.add(ini_settings_source)
103
+
104
+ # yaml配置文件
105
+ yaml_file = cls.root_config_dir / "settings.yaml"
106
+ if yaml_file.exists():
107
+ yaml_settings_source = YamlSettingsSource(yaml_file)
108
+ default_settings.add(yaml_settings_source)
109
+
110
+ return tuple(default_settings)
sanic_api/config/sanic.py CHANGED
@@ -1,21 +1,19 @@
1
- from pydantic import Field
2
-
3
- from .base import SettingsBase
4
-
5
-
6
- class SanicConfig(SettingsBase):
7
- """
8
- sanic 框架本身的配置
9
- """
10
-
11
- # 是否开启OpenAPI规范文档生成
12
- oas: bool = Field(default=True)
13
-
14
- # 访问日志开关
15
- access_log: bool = Field(default=True, alias="ACCESS_LOG", env="ACCESS_LOG")
16
-
17
- # 后台日志记录器,开启可增加一些性能。见:https://sanic.dev/en/plugins/sanic-ext/logger.html
18
- background_log: bool = Field(default=True, alias="LOGGING", env="LOGGING")
19
-
20
- # OpenAPI规范文档的URL前缀
21
- oas_url_prefix: str = Field(default="docs", alias="OAS_URL_PREFIX", env="OAS_URL_PREFIX")
1
+ from pydantic import BaseModel, Field
2
+
3
+
4
+ class SanicConfig(BaseModel):
5
+ """
6
+ sanic 框架本身的配置
7
+ """
8
+
9
+ # 是否开启OpenAPI规范文档生成
10
+ oas: bool = Field(default=True)
11
+
12
+ # 访问日志开关
13
+ access_log: bool = Field(default=True, alias="ACCESS_LOG", env="ACCESS_LOG")
14
+
15
+ # 后台日志记录器,开启可增加一些性能。见:https://sanic.dev/en/plugins/sanic-ext/logger.html
16
+ background_log: bool = Field(default=True, alias="LOGGING", env="LOGGING")
17
+
18
+ # OpenAPI规范文档的URL前缀
19
+ oas_url_prefix: str = Field(default="docs", alias="OAS_URL_PREFIX", env="OAS_URL_PREFIX")
@@ -1,13 +1,11 @@
1
- from pydantic import Field
2
-
3
- from .base import SettingsBase
4
-
5
-
6
- class SanicApiConfig(SettingsBase):
7
- """
8
- sanic_api 框架需要的配置
9
- """
10
-
11
- data_tmp: str = Field(title="响应中data类型字段的key", default="data")
12
- code_tmp: str = Field(title="响应中data类型字段的key", default="code")
13
- msg_tmp: str = Field(title="响应中data类型字段的key", default="msg")
1
+ from pydantic import BaseModel, Field
2
+
3
+
4
+ class SanicApiConfig(BaseModel):
5
+ """
6
+ sanic_api 框架需要的配置
7
+ """
8
+
9
+ data_tmp: str = Field(title="响应中data类型字段的key", default="data")
10
+ code_tmp: str = Field(title="响应中data类型字段的key", default="code")
11
+ msg_tmp: str = Field(title="响应中data类型字段的key", default="msg")
@@ -1,30 +1,30 @@
1
- from pydantic import Field
2
-
3
- from sanic_api.config.base import SettingsBase
4
- from sanic_api.config.sanic import SanicConfig
5
- from sanic_api.config.sanic_api import SanicApiConfig
6
- from sanic_api.enum import RunModeEnum
7
-
8
-
9
- class DefaultSettings(SettingsBase):
10
- """
11
- 配置类
12
- """
13
-
14
- # 主机
15
- host: str = Field(default="127.0.0.1")
16
-
17
- # 端口
18
- port: int = Field(default=5798)
19
-
20
- # 运行模式
21
- mode: RunModeEnum = Field(default=RunModeEnum.DEV)
22
-
23
- # 工作进程的数量
24
- workers: int = Field(default=1)
25
-
26
- # sanic 自身的配置
27
- sanic: SanicConfig = Field(default_factory=SanicConfig)
28
-
29
- # sanic_api 扩展自身需要的配置
30
- sanic_api: SanicApiConfig = Field(default_factory=SanicApiConfig)
1
+ from pydantic import Field
2
+
3
+ from sanic_api.config.base import SettingsBase
4
+ from sanic_api.config.sanic import SanicConfig
5
+ from sanic_api.config.sanic_api import SanicApiConfig
6
+ from sanic_api.enum import RunModeEnum
7
+
8
+
9
+ class DefaultSettings(SettingsBase):
10
+ """
11
+ 配置类
12
+ """
13
+
14
+ # 主机
15
+ host: str = Field(default="127.0.0.1")
16
+
17
+ # 端口
18
+ port: int = Field(default=5798)
19
+
20
+ # 运行模式
21
+ mode: RunModeEnum = Field(default=RunModeEnum.DEV)
22
+
23
+ # 工作进程的数量
24
+ workers: int = Field(default=1)
25
+
26
+ # sanic 自身的配置
27
+ sanic: SanicConfig = Field(default_factory=SanicConfig)
28
+
29
+ # sanic_api 扩展自身需要的配置
30
+ sanic_api: SanicApiConfig = Field(default_factory=SanicApiConfig)