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.
Files changed (68) hide show
  1. deepfos/_version.py +3 -3
  2. deepfos/api/V1_1/models/business_model.py +322 -322
  3. deepfos/api/V1_1/models/dimension.py +1075 -1075
  4. deepfos/api/V1_2/models/dimension.py +1119 -1116
  5. deepfos/api/account.py +1 -0
  6. deepfos/api/app.py +1 -0
  7. deepfos/api/base.py +70 -71
  8. deepfos/api/deep_pipeline.py +1 -1
  9. deepfos/api/deepconnector.py +3 -3
  10. deepfos/api/financial_model.py +12 -0
  11. deepfos/api/models/account.py +130 -130
  12. deepfos/api/models/accounting_engines.py +250 -250
  13. deepfos/api/models/app.py +355 -355
  14. deepfos/api/models/approval_process.py +231 -231
  15. deepfos/api/models/base.py +49 -209
  16. deepfos/api/models/business_model.py +239 -239
  17. deepfos/api/models/consolidation.py +196 -196
  18. deepfos/api/models/consolidation_process.py +31 -31
  19. deepfos/api/models/datatable_mysql.py +78 -78
  20. deepfos/api/models/deep_pipeline.py +20 -9
  21. deepfos/api/models/deepconnector.py +9 -8
  22. deepfos/api/models/deepfos_task.py +118 -118
  23. deepfos/api/models/deepmodel.py +120 -120
  24. deepfos/api/models/dimension.py +613 -610
  25. deepfos/api/models/financial_model.py +691 -663
  26. deepfos/api/models/journal_model.py +120 -120
  27. deepfos/api/models/journal_template.py +185 -185
  28. deepfos/api/models/memory_financial_model.py +131 -131
  29. deepfos/api/models/platform.py +16 -16
  30. deepfos/api/models/python.py +32 -32
  31. deepfos/api/models/reconciliation_engine.py +104 -104
  32. deepfos/api/models/reconciliation_report.py +29 -29
  33. deepfos/api/models/role_strategy.py +213 -213
  34. deepfos/api/models/smartlist.py +86 -86
  35. deepfos/api/models/space.py +312 -312
  36. deepfos/api/models/system.py +299 -297
  37. deepfos/api/models/variable.py +131 -131
  38. deepfos/api/models/workflow.py +290 -270
  39. deepfos/api/platform.py +3 -1
  40. deepfos/api/space.py +1 -0
  41. deepfos/api/system.py +1 -0
  42. deepfos/api/workflow.py +8 -0
  43. deepfos/cache.py +50 -4
  44. deepfos/element/bizmodel.py +2 -2
  45. deepfos/element/deep_pipeline.py +29 -16
  46. deepfos/element/deepconnector.py +36 -1
  47. deepfos/element/deepmodel.py +591 -332
  48. deepfos/element/dimension.py +30 -17
  49. deepfos/element/finmodel.py +542 -101
  50. deepfos/element/journal.py +20 -10
  51. deepfos/element/rolestrategy.py +4 -4
  52. deepfos/element/variable.py +23 -17
  53. deepfos/element/workflow.py +60 -3
  54. deepfos/exceptions/__init__.py +1 -1
  55. deepfos/lib/deepchart.py +14 -13
  56. deepfos/lib/deepux.py +11 -11
  57. deepfos/lib/discovery.py +3 -0
  58. deepfos/lib/filterparser.py +2 -2
  59. deepfos/lib/k8s.py +101 -0
  60. deepfos/lib/msg.py +34 -8
  61. deepfos/lib/serutils.py +34 -9
  62. deepfos/lib/sysutils.py +37 -18
  63. deepfos/lib/utils.py +62 -2
  64. deepfos/options.py +39 -8
  65. {deepfos-1.1.60.dist-info → deepfos-1.1.78.dist-info}/METADATA +7 -7
  66. {deepfos-1.1.60.dist-info → deepfos-1.1.78.dist-info}/RECORD +68 -67
  67. {deepfos-1.1.60.dist-info → deepfos-1.1.78.dist-info}/WHEEL +0 -0
  68. {deepfos-1.1.60.dist-info → deepfos-1.1.78.dist-info}/top_level.txt +0 -0
@@ -1,234 +1,74 @@
1
- import json
2
- from collections import defaultdict
1
+ from deepfos.lib.utils import to_version_tuple
2
+ import pydantic
3
3
 
4
- from pydantic import BaseModel as PydanticBaseModel, Field, validator
5
- from pydantic.fields import FieldInfo
6
- # noinspection PyProtectedMember
7
- from pydantic.main import ModelMetaclass
8
- from pydantic.generics import GenericModel
9
- from typing import Any, TypeVar, Generic, no_type_check, Dict
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
- "BaseModelPlus",
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
- for k, v in namespace.items():
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
- for m in models:
101
- attrs.update({
102
- k: getattr(m, k)
103
- for k in (m.__fields_set__ & fields_set)
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 quick_parse(cls, **fields):
114
- # todo recursive parse dict to model
115
- valid_fields = {}
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, *, include=None, exclude=None, by_alias=False, skip_defaults=None,
159
- exclude_unset=False, exclude_defaults=False, exclude_none=False,
160
- ):
161
- ori_dict = super().dict(
162
- include=include,
163
- exclude=exclude,
164
- skip_defaults=skip_defaults,
165
- by_alias=by_alias,
166
- exclude_unset=exclude_unset,
167
- exclude_defaults=exclude_defaults,
168
- exclude_none=exclude_none,
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)