deepfos 1.1.60__py3-none-any.whl → 1.1.78__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.
- deepfos/_version.py +3 -3
- deepfos/api/V1_1/models/business_model.py +322 -322
- deepfos/api/V1_1/models/dimension.py +1075 -1075
- deepfos/api/V1_2/models/dimension.py +1119 -1116
- deepfos/api/account.py +1 -0
- deepfos/api/app.py +1 -0
- deepfos/api/base.py +70 -71
- deepfos/api/deep_pipeline.py +1 -1
- deepfos/api/deepconnector.py +3 -3
- deepfos/api/financial_model.py +12 -0
- deepfos/api/models/account.py +130 -130
- deepfos/api/models/accounting_engines.py +250 -250
- deepfos/api/models/app.py +355 -355
- deepfos/api/models/approval_process.py +231 -231
- deepfos/api/models/base.py +49 -209
- deepfos/api/models/business_model.py +239 -239
- deepfos/api/models/consolidation.py +196 -196
- deepfos/api/models/consolidation_process.py +31 -31
- deepfos/api/models/datatable_mysql.py +78 -78
- deepfos/api/models/deep_pipeline.py +20 -9
- deepfos/api/models/deepconnector.py +9 -8
- deepfos/api/models/deepfos_task.py +118 -118
- deepfos/api/models/deepmodel.py +120 -120
- deepfos/api/models/dimension.py +613 -610
- deepfos/api/models/financial_model.py +691 -663
- deepfos/api/models/journal_model.py +120 -120
- deepfos/api/models/journal_template.py +185 -185
- deepfos/api/models/memory_financial_model.py +131 -131
- deepfos/api/models/platform.py +16 -16
- deepfos/api/models/python.py +32 -32
- deepfos/api/models/reconciliation_engine.py +104 -104
- deepfos/api/models/reconciliation_report.py +29 -29
- deepfos/api/models/role_strategy.py +213 -213
- deepfos/api/models/smartlist.py +86 -86
- deepfos/api/models/space.py +312 -312
- deepfos/api/models/system.py +299 -297
- deepfos/api/models/variable.py +131 -131
- deepfos/api/models/workflow.py +290 -270
- deepfos/api/platform.py +3 -1
- deepfos/api/space.py +1 -0
- deepfos/api/system.py +1 -0
- deepfos/api/workflow.py +8 -0
- deepfos/cache.py +50 -4
- deepfos/element/bizmodel.py +2 -2
- deepfos/element/deep_pipeline.py +29 -16
- deepfos/element/deepconnector.py +36 -1
- deepfos/element/deepmodel.py +591 -332
- deepfos/element/dimension.py +30 -17
- deepfos/element/finmodel.py +542 -101
- deepfos/element/journal.py +20 -10
- deepfos/element/rolestrategy.py +4 -4
- deepfos/element/variable.py +23 -17
- deepfos/element/workflow.py +60 -3
- deepfos/exceptions/__init__.py +1 -1
- deepfos/lib/deepchart.py +14 -13
- deepfos/lib/deepux.py +11 -11
- deepfos/lib/discovery.py +3 -0
- deepfos/lib/filterparser.py +2 -2
- deepfos/lib/k8s.py +101 -0
- deepfos/lib/msg.py +34 -8
- deepfos/lib/serutils.py +34 -9
- deepfos/lib/sysutils.py +37 -18
- deepfos/lib/utils.py +62 -2
- deepfos/options.py +39 -8
- {deepfos-1.1.60.dist-info → deepfos-1.1.78.dist-info}/METADATA +7 -7
- {deepfos-1.1.60.dist-info → deepfos-1.1.78.dist-info}/RECORD +68 -67
- {deepfos-1.1.60.dist-info → deepfos-1.1.78.dist-info}/WHEEL +0 -0
- {deepfos-1.1.60.dist-info → deepfos-1.1.78.dist-info}/top_level.txt +0 -0
deepfos/api/models/base.py
CHANGED
|
@@ -1,234 +1,74 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from deepfos.lib.utils import to_version_tuple
|
|
2
|
+
import pydantic
|
|
3
3
|
|
|
4
|
-
from
|
|
5
|
-
from pydantic
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
from typing import Any, Dict, TypeVar, Type
|
|
5
|
+
from pydantic import BaseModel as PydanticBaseModel, ConfigDict
|
|
6
|
+
from pydantic import parse_obj_as
|
|
7
|
+
|
|
8
|
+
Pydantic_V2 = False
|
|
9
|
+
if to_version_tuple(pydantic.__version__, max_split=2) > (2, 0, 0):
|
|
10
|
+
from pydantic import TypeAdapter
|
|
11
|
+
Pydantic_V2 = True
|
|
12
|
+
else:
|
|
13
|
+
TypeAdapter = None
|
|
10
14
|
|
|
11
15
|
__all__ = [
|
|
12
|
-
"HeaderModel",
|
|
13
|
-
"Response",
|
|
14
16
|
"BaseModel",
|
|
15
|
-
"
|
|
16
|
-
"Group",
|
|
17
|
-
"AutoField",
|
|
18
|
-
"GenericResponse",
|
|
19
|
-
"GResponse",
|
|
17
|
+
"compat_parse_obj_as",
|
|
20
18
|
]
|
|
21
19
|
|
|
20
|
+
T = TypeVar('T')
|
|
22
21
|
|
|
23
|
-
class Group(FieldInfo):
|
|
24
|
-
def __init__(self, default, group_id, at_least=1, at_most=1, **kwargs):
|
|
25
|
-
"""
|
|
26
|
-
Args:
|
|
27
|
-
default: 默认值,同FieldInfo
|
|
28
|
-
group_id: 组ID,id相同并且属于同一个类的被视为同一组
|
|
29
|
-
at_least: 同组中至少需提供多少参数
|
|
30
|
-
at_most: 同组中至多可以提供多少参数
|
|
31
|
-
**kwargs: 同FieldInfo
|
|
32
|
-
"""
|
|
33
|
-
self.at_most = at_most
|
|
34
|
-
self.at_least = at_least
|
|
35
|
-
self.group_id = group_id
|
|
36
|
-
super().__init__(default, **kwargs)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class AutoField(FieldInfo):
|
|
40
|
-
pass
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def _enable_groupfield(group: Dict[str, Group]):
|
|
44
|
-
grp = list(group.values())[-1]
|
|
45
|
-
_field = list(group.keys())[-1]
|
|
46
|
-
at_least, at_most = grp.at_least, grp.at_most
|
|
47
|
-
restriction_msg = f"字段{list(group.keys())}至少需提供{at_least}个," \
|
|
48
|
-
f"至多{at_most}个。"
|
|
49
|
-
for g in group.values():
|
|
50
|
-
g.description = f"{g.description}({restriction_msg})"
|
|
51
|
-
|
|
52
|
-
# noinspection PyUnusedLocal
|
|
53
|
-
def _validator(cls, v, values, field):
|
|
54
|
-
assigned_fields = set(k for k, v in values.items() if v is not None)
|
|
55
|
-
if v is not None:
|
|
56
|
-
assigned_fields.add(field.name)
|
|
57
|
-
|
|
58
|
-
grp_assigned_fields = group.keys() & assigned_fields
|
|
59
|
-
if not at_least <= len(grp_assigned_fields) <= at_most:
|
|
60
|
-
if grp_assigned_fields:
|
|
61
|
-
field_info = f"实际赋值的字段为:{grp_assigned_fields}"
|
|
62
|
-
else:
|
|
63
|
-
field_info = "实际任何字段都未赋值。"
|
|
64
|
-
raise AssertionError(f"{restriction_msg}{field_info}")
|
|
65
|
-
|
|
66
|
-
return f"_validator_{grp.group_id}", \
|
|
67
|
-
validator(_field, always=True, allow_reuse=True)(_validator)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class MetaModel(ModelMetaclass):
|
|
71
|
-
@no_type_check # noqa C901
|
|
72
|
-
def __new__(mcs, name, bases, namespace, **kwargs): # noqa C901
|
|
73
|
-
groups = defaultdict(dict)
|
|
74
|
-
ann = namespace.get('__annotations__', {})
|
|
75
|
-
namespace['__autofields__'] = auto_fields = {}
|
|
76
22
|
|
|
77
|
-
|
|
78
|
-
if isinstance(v, Group):
|
|
79
|
-
groups[v.group_id][k] = v
|
|
80
|
-
if isinstance(v, AutoField):
|
|
81
|
-
auto_fields[k] = ann[k]
|
|
82
|
-
ann[k] = Any
|
|
83
|
-
|
|
84
|
-
for grp in groups.values():
|
|
85
|
-
k, v = _enable_groupfield(grp)
|
|
86
|
-
namespace[k] = v
|
|
87
|
-
|
|
88
|
-
cls = super().__new__(mcs, name, bases, namespace, **kwargs)
|
|
89
|
-
return cls
|
|
23
|
+
class BaseModel(PydanticBaseModel):
|
|
90
24
|
|
|
25
|
+
if Pydantic_V2:
|
|
26
|
+
model_config = ConfigDict(from_attributes=True)
|
|
91
27
|
|
|
92
|
-
class BaseModel(PydanticBaseModel):
|
|
93
28
|
@classmethod
|
|
94
29
|
def construct_from(cls, *models: 'BaseModel', **extra):
|
|
95
30
|
"""
|
|
96
31
|
基于PydanticBaseModel.contruct,删除不在_fields_set中的属性
|
|
97
32
|
"""
|
|
98
|
-
fields_set = set(cls.__fields__.keys())
|
|
99
33
|
attrs = {}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
34
|
+
if Pydantic_V2:
|
|
35
|
+
fields_set = set(cls.model_fields.keys())
|
|
36
|
+
for m in models:
|
|
37
|
+
attrs.update({
|
|
38
|
+
k: getattr(m, k)
|
|
39
|
+
for k in (m.model_fields_set & fields_set)
|
|
40
|
+
})
|
|
41
|
+
else:
|
|
42
|
+
fields_set = set(cls.__fields__.keys())
|
|
43
|
+
for m in models:
|
|
44
|
+
attrs.update({
|
|
45
|
+
k: getattr(m, k)
|
|
46
|
+
for k in (m.__fields_set__ & fields_set)
|
|
47
|
+
})
|
|
105
48
|
attrs.update({
|
|
106
49
|
k: extra[k] for
|
|
107
50
|
k in (fields_set & extra.keys())
|
|
108
51
|
})
|
|
109
|
-
|
|
52
|
+
if Pydantic_V2:
|
|
53
|
+
return cls.model_construct(fields_set, **attrs)
|
|
110
54
|
return cls.construct(fields_set, **attrs)
|
|
111
55
|
|
|
112
56
|
@classmethod
|
|
113
|
-
def
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
for field_name, value in fields.items():
|
|
118
|
-
if field_name not in cls.__fields__:
|
|
119
|
-
continue
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
class BaseModelPlus(BaseModel, metaclass=MetaModel):
|
|
123
|
-
"""
|
|
124
|
-
可支持使用Group定义字段, AutoField定义字段
|
|
125
|
-
|
|
126
|
-
Examples:
|
|
127
|
-
GroupA = functools.partial(Group, group_id='aaa', at_most=2)
|
|
128
|
-
GroupB = functools.partial(Group, group_id='bbb')
|
|
129
|
-
|
|
130
|
-
class TestModel(GroupBaseModel):
|
|
131
|
-
a: str = GroupA(None, description='hello a')
|
|
132
|
-
b: str = GroupA(None, description='hello b')
|
|
133
|
-
c: int = GroupA(None, description='hello c')
|
|
134
|
-
d: int = GroupB(None, description='hello d')
|
|
135
|
-
e: int = GroupB(None, description='hello e')
|
|
136
|
-
|
|
137
|
-
按照上述定义的TestModel,在实例化时,a,b,c字段至少需提供1个,至多2个.
|
|
138
|
-
d, e字段至少提供1个,至多1个。
|
|
139
|
-
并且会在openapi中添加相应描述
|
|
140
|
-
"""
|
|
141
|
-
|
|
142
|
-
def __getattribute__(self, item):
|
|
143
|
-
attr = super().__getattribute__(item)
|
|
144
|
-
|
|
145
|
-
if item.startswith('__'):
|
|
146
|
-
return attr
|
|
147
|
-
if item not in self.__autofields__:
|
|
148
|
-
return attr
|
|
149
|
-
if not isinstance(attr, str):
|
|
150
|
-
return attr
|
|
151
|
-
|
|
152
|
-
model = self.__autofields__[item]
|
|
153
|
-
new_attr = model.construct_from(**json.loads(attr))
|
|
154
|
-
setattr(self, item, new_attr)
|
|
155
|
-
return new_attr
|
|
57
|
+
def update_forward_refs(cls) -> None:
|
|
58
|
+
if Pydantic_V2:
|
|
59
|
+
return cls.model_rebuild(force=True)
|
|
60
|
+
return super().update_forward_refs()
|
|
156
61
|
|
|
157
62
|
def dict(
|
|
158
|
-
self,
|
|
159
|
-
|
|
160
|
-
):
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
for field in self.__autofields__:
|
|
171
|
-
if not isinstance(ori := ori_dict[field], str):
|
|
172
|
-
ori_dict[field] = json.dumps(ori)
|
|
173
|
-
return ori_dict
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
class HeaderModel(BaseModel):
|
|
177
|
-
app: str
|
|
178
|
-
space: str
|
|
179
|
-
user: str
|
|
180
|
-
language: str
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
class Response(BaseModel):
|
|
184
|
-
status: bool = Field(description='接口状态信息')
|
|
185
|
-
code: int = Field(None, description='接口错误码')
|
|
186
|
-
message: str = Field(None, description='接口错误信息')
|
|
187
|
-
data: Any = Field(None, description='接口返回值')
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
DataT = TypeVar('DataT')
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
class GenericResponse(GenericModel, Generic[DataT]):
|
|
194
|
-
status: bool = Field(description='接口状态信息')
|
|
195
|
-
code: int = Field(None, description='接口错误码')
|
|
196
|
-
message: str = Field(None, description='接口错误信息')
|
|
197
|
-
data: DataT = Field(None, description='接口返回值')
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
class GResponse:
|
|
201
|
-
"""
|
|
202
|
-
特殊的泛型响应模型类
|
|
203
|
-
用于更好地提供响应中data字段的文档信息
|
|
204
|
-
|
|
205
|
-
Examples:
|
|
206
|
-
``GResponse[str, description]`` 可以返回一个 GenericResponse[str] 类型,
|
|
207
|
-
并且description的内容可以展示在接口文档中。
|
|
208
|
-
"""
|
|
209
|
-
memo = {}
|
|
210
|
-
data_desc = Response.__fields__['data'].field_info.description
|
|
211
|
-
|
|
212
|
-
def __class_getitem__(cls, item):
|
|
213
|
-
model_key = (cls, item)
|
|
214
|
-
if model_key in cls.memo:
|
|
215
|
-
return cls.memo[model_key]
|
|
216
|
-
|
|
217
|
-
if isinstance(item, tuple):
|
|
218
|
-
*params, description = item
|
|
219
|
-
ann = item[0]
|
|
220
|
-
else:
|
|
221
|
-
params = (item, )
|
|
222
|
-
ann = item
|
|
223
|
-
description = cls.data_desc
|
|
224
|
-
|
|
225
|
-
model_name = f"Resp{GenericModel.__concrete_name__(params)}{description}"
|
|
226
|
-
|
|
227
|
-
data_field = Field(None, description=description)
|
|
228
|
-
|
|
229
|
-
model = type(model_name, (Response,), {
|
|
230
|
-
'__annotations__': {'data': ann},
|
|
231
|
-
'data': data_field
|
|
232
|
-
})
|
|
233
|
-
cls.memo[model_key] = model
|
|
234
|
-
return model
|
|
63
|
+
self,
|
|
64
|
+
**kwargs,
|
|
65
|
+
) -> Dict[str, Any]:
|
|
66
|
+
if Pydantic_V2:
|
|
67
|
+
return self.model_dump(**kwargs)
|
|
68
|
+
return super().dict(**kwargs)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def compat_parse_obj_as(cls: Type[T], data: Any) -> T:
|
|
72
|
+
if Pydantic_V2:
|
|
73
|
+
return TypeAdapter(cls).validate_python(data)
|
|
74
|
+
return parse_obj_as(cls, data)
|