deepfos 1.1.60__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 (175) hide show
  1. deepfos/__init__.py +6 -0
  2. deepfos/_version.py +21 -0
  3. deepfos/algo/__init__.py +0 -0
  4. deepfos/algo/graph.py +171 -0
  5. deepfos/algo/segtree.py +31 -0
  6. deepfos/api/V1_1/__init__.py +0 -0
  7. deepfos/api/V1_1/business_model.py +119 -0
  8. deepfos/api/V1_1/dimension.py +599 -0
  9. deepfos/api/V1_1/models/__init__.py +0 -0
  10. deepfos/api/V1_1/models/business_model.py +1033 -0
  11. deepfos/api/V1_1/models/dimension.py +2768 -0
  12. deepfos/api/V1_2/__init__.py +0 -0
  13. deepfos/api/V1_2/dimension.py +285 -0
  14. deepfos/api/V1_2/models/__init__.py +0 -0
  15. deepfos/api/V1_2/models/dimension.py +2923 -0
  16. deepfos/api/__init__.py +0 -0
  17. deepfos/api/account.py +167 -0
  18. deepfos/api/accounting_engines.py +147 -0
  19. deepfos/api/app.py +626 -0
  20. deepfos/api/approval_process.py +198 -0
  21. deepfos/api/base.py +983 -0
  22. deepfos/api/business_model.py +160 -0
  23. deepfos/api/consolidation.py +129 -0
  24. deepfos/api/consolidation_process.py +106 -0
  25. deepfos/api/datatable.py +341 -0
  26. deepfos/api/deep_pipeline.py +61 -0
  27. deepfos/api/deepconnector.py +36 -0
  28. deepfos/api/deepfos_task.py +92 -0
  29. deepfos/api/deepmodel.py +188 -0
  30. deepfos/api/dimension.py +486 -0
  31. deepfos/api/financial_model.py +319 -0
  32. deepfos/api/journal_model.py +119 -0
  33. deepfos/api/journal_template.py +132 -0
  34. deepfos/api/memory_financial_model.py +98 -0
  35. deepfos/api/models/__init__.py +3 -0
  36. deepfos/api/models/account.py +483 -0
  37. deepfos/api/models/accounting_engines.py +756 -0
  38. deepfos/api/models/app.py +1338 -0
  39. deepfos/api/models/approval_process.py +1043 -0
  40. deepfos/api/models/base.py +234 -0
  41. deepfos/api/models/business_model.py +805 -0
  42. deepfos/api/models/consolidation.py +711 -0
  43. deepfos/api/models/consolidation_process.py +248 -0
  44. deepfos/api/models/datatable_mysql.py +427 -0
  45. deepfos/api/models/deep_pipeline.py +55 -0
  46. deepfos/api/models/deepconnector.py +28 -0
  47. deepfos/api/models/deepfos_task.py +386 -0
  48. deepfos/api/models/deepmodel.py +308 -0
  49. deepfos/api/models/dimension.py +1576 -0
  50. deepfos/api/models/financial_model.py +1796 -0
  51. deepfos/api/models/journal_model.py +341 -0
  52. deepfos/api/models/journal_template.py +854 -0
  53. deepfos/api/models/memory_financial_model.py +478 -0
  54. deepfos/api/models/platform.py +178 -0
  55. deepfos/api/models/python.py +221 -0
  56. deepfos/api/models/reconciliation_engine.py +411 -0
  57. deepfos/api/models/reconciliation_report.py +161 -0
  58. deepfos/api/models/role_strategy.py +884 -0
  59. deepfos/api/models/smartlist.py +237 -0
  60. deepfos/api/models/space.py +1137 -0
  61. deepfos/api/models/system.py +1065 -0
  62. deepfos/api/models/variable.py +463 -0
  63. deepfos/api/models/workflow.py +946 -0
  64. deepfos/api/platform.py +199 -0
  65. deepfos/api/python.py +90 -0
  66. deepfos/api/reconciliation_engine.py +181 -0
  67. deepfos/api/reconciliation_report.py +64 -0
  68. deepfos/api/role_strategy.py +234 -0
  69. deepfos/api/smartlist.py +69 -0
  70. deepfos/api/space.py +582 -0
  71. deepfos/api/system.py +372 -0
  72. deepfos/api/variable.py +154 -0
  73. deepfos/api/workflow.py +264 -0
  74. deepfos/boost/__init__.py +6 -0
  75. deepfos/boost/py_jstream.py +89 -0
  76. deepfos/boost/py_pandas.py +20 -0
  77. deepfos/cache.py +121 -0
  78. deepfos/config.py +6 -0
  79. deepfos/core/__init__.py +27 -0
  80. deepfos/core/cube/__init__.py +10 -0
  81. deepfos/core/cube/_base.py +462 -0
  82. deepfos/core/cube/constants.py +21 -0
  83. deepfos/core/cube/cube.py +408 -0
  84. deepfos/core/cube/formula.py +707 -0
  85. deepfos/core/cube/syscube.py +532 -0
  86. deepfos/core/cube/typing.py +7 -0
  87. deepfos/core/cube/utils.py +238 -0
  88. deepfos/core/dimension/__init__.py +11 -0
  89. deepfos/core/dimension/_base.py +506 -0
  90. deepfos/core/dimension/dimcreator.py +184 -0
  91. deepfos/core/dimension/dimension.py +472 -0
  92. deepfos/core/dimension/dimexpr.py +271 -0
  93. deepfos/core/dimension/dimmember.py +155 -0
  94. deepfos/core/dimension/eledimension.py +22 -0
  95. deepfos/core/dimension/filters.py +99 -0
  96. deepfos/core/dimension/sysdimension.py +168 -0
  97. deepfos/core/logictable/__init__.py +5 -0
  98. deepfos/core/logictable/_cache.py +141 -0
  99. deepfos/core/logictable/_operator.py +663 -0
  100. deepfos/core/logictable/nodemixin.py +673 -0
  101. deepfos/core/logictable/sqlcondition.py +609 -0
  102. deepfos/core/logictable/tablemodel.py +497 -0
  103. deepfos/db/__init__.py +36 -0
  104. deepfos/db/cipher.py +660 -0
  105. deepfos/db/clickhouse.py +191 -0
  106. deepfos/db/connector.py +195 -0
  107. deepfos/db/daclickhouse.py +171 -0
  108. deepfos/db/dameng.py +101 -0
  109. deepfos/db/damysql.py +189 -0
  110. deepfos/db/dbkits.py +358 -0
  111. deepfos/db/deepengine.py +99 -0
  112. deepfos/db/deepmodel.py +82 -0
  113. deepfos/db/deepmodel_kingbase.py +83 -0
  114. deepfos/db/edb.py +214 -0
  115. deepfos/db/gauss.py +83 -0
  116. deepfos/db/kingbase.py +83 -0
  117. deepfos/db/mysql.py +184 -0
  118. deepfos/db/oracle.py +131 -0
  119. deepfos/db/postgresql.py +192 -0
  120. deepfos/db/sqlserver.py +99 -0
  121. deepfos/db/utils.py +135 -0
  122. deepfos/element/__init__.py +89 -0
  123. deepfos/element/accounting.py +348 -0
  124. deepfos/element/apvlprocess.py +215 -0
  125. deepfos/element/base.py +398 -0
  126. deepfos/element/bizmodel.py +1269 -0
  127. deepfos/element/datatable.py +2467 -0
  128. deepfos/element/deep_pipeline.py +186 -0
  129. deepfos/element/deepconnector.py +59 -0
  130. deepfos/element/deepmodel.py +1806 -0
  131. deepfos/element/dimension.py +1254 -0
  132. deepfos/element/fact_table.py +427 -0
  133. deepfos/element/finmodel.py +1485 -0
  134. deepfos/element/journal.py +840 -0
  135. deepfos/element/journal_template.py +943 -0
  136. deepfos/element/pyscript.py +412 -0
  137. deepfos/element/reconciliation.py +553 -0
  138. deepfos/element/rolestrategy.py +243 -0
  139. deepfos/element/smartlist.py +457 -0
  140. deepfos/element/variable.py +756 -0
  141. deepfos/element/workflow.py +560 -0
  142. deepfos/exceptions/__init__.py +239 -0
  143. deepfos/exceptions/hook.py +86 -0
  144. deepfos/lazy.py +104 -0
  145. deepfos/lazy_import.py +84 -0
  146. deepfos/lib/__init__.py +0 -0
  147. deepfos/lib/_javaobj.py +366 -0
  148. deepfos/lib/asynchronous.py +879 -0
  149. deepfos/lib/concurrency.py +107 -0
  150. deepfos/lib/constant.py +39 -0
  151. deepfos/lib/decorator.py +310 -0
  152. deepfos/lib/deepchart.py +778 -0
  153. deepfos/lib/deepux.py +477 -0
  154. deepfos/lib/discovery.py +273 -0
  155. deepfos/lib/edb_lexer.py +789 -0
  156. deepfos/lib/eureka.py +156 -0
  157. deepfos/lib/filterparser.py +751 -0
  158. deepfos/lib/httpcli.py +106 -0
  159. deepfos/lib/jsonstreamer.py +80 -0
  160. deepfos/lib/msg.py +394 -0
  161. deepfos/lib/nacos.py +225 -0
  162. deepfos/lib/patch.py +92 -0
  163. deepfos/lib/redis.py +241 -0
  164. deepfos/lib/serutils.py +181 -0
  165. deepfos/lib/stopwatch.py +99 -0
  166. deepfos/lib/subtask.py +572 -0
  167. deepfos/lib/sysutils.py +703 -0
  168. deepfos/lib/utils.py +1003 -0
  169. deepfos/local.py +160 -0
  170. deepfos/options.py +670 -0
  171. deepfos/translation.py +237 -0
  172. deepfos-1.1.60.dist-info/METADATA +33 -0
  173. deepfos-1.1.60.dist-info/RECORD +175 -0
  174. deepfos-1.1.60.dist-info/WHEEL +5 -0
  175. deepfos-1.1.60.dist-info/top_level.txt +1 -0
@@ -0,0 +1,239 @@
1
+ from .hook import eliminate_from_traceback
2
+
3
+
4
+ class DeepfosBaseException(Exception):
5
+ """deepfos自定义异常基类"""
6
+
7
+
8
+ # -----------------------------------------------------------------------------
9
+ # Option Error
10
+ class BaseOptionError(DeepfosBaseException):
11
+ """配置项异常基类"""
12
+
13
+
14
+ class OptionNotSetError(BaseOptionError):
15
+ """配置项未设置"""
16
+
17
+
18
+ class OptionTypeError(BaseOptionError):
19
+ """配置项类型错误"""
20
+
21
+
22
+ class OptionValueError(BaseOptionError):
23
+ """配置项值错误"""
24
+
25
+
26
+ # -----------------------------------------------------------------------------
27
+ # API Error
28
+ class APIError(DeepfosBaseException, OSError):
29
+ """API相关异常"""
30
+
31
+
32
+ class APIRequestError(APIError):
33
+ """调用API时请求异常"""
34
+
35
+
36
+ class APIResponseError(APIError):
37
+ """调用API返回异常"""
38
+ def __init__(self, msg, code=None):
39
+ super().__init__(msg)
40
+ self.code = code
41
+
42
+
43
+ # -----------------------------------------------------------------------------
44
+ # Element Error
45
+
46
+ class ElementError(DeepfosBaseException):
47
+ """元素相关异常"""
48
+
49
+
50
+ class ElementTypeMissingError(ElementError):
51
+ """无法获取元素类型"""
52
+
53
+
54
+ class ElementNotFoundError(ElementError):
55
+ """元素不存在"""
56
+
57
+
58
+ class ElementAmbiguousError(ElementError):
59
+ """无法锁定唯一元素"""
60
+
61
+
62
+ class ElementVersionIncompatibleError(ElementError):
63
+ """元素版本不兼容"""
64
+
65
+
66
+ class DimensionSaveError(ElementError):
67
+ """无法保存维度"""
68
+
69
+
70
+ class MemberNotFoundError(ElementError):
71
+ """维度成员不存在"""
72
+
73
+
74
+ class VariableUpdateError(ElementError):
75
+ """无法更新变量"""
76
+
77
+
78
+ class VariableCreateError(ElementError):
79
+ """无法新建变量"""
80
+
81
+
82
+ # -----------------------------------------------------------------------------
83
+ # RedisLock Error
84
+
85
+ class LockAcquireFailed(DeepfosBaseException):
86
+ """无法获取Redis锁"""
87
+
88
+
89
+ class BadFutureError(DeepfosBaseException):
90
+ """获取future property返回值过程出现错误"""
91
+ def __init__(self, msg, obj):
92
+ super().__init__(msg)
93
+ self.obj = obj
94
+
95
+
96
+ # -----------------------------------------------------------------------------
97
+ # Pyscript Error
98
+ class PyTaskError(DeepfosBaseException):
99
+ """执行脚本报错基类"""
100
+ base_msg = ''
101
+
102
+ def __init__(self, *reasons):
103
+ self.reasons = reasons
104
+
105
+ def __str__(self):
106
+ if self.base_msg and self.reasons:
107
+ return self.base_msg.format(*self.reasons)
108
+ return self.__class__.__doc__
109
+
110
+
111
+ class ResultTimeOutError(PyTaskError):
112
+ """等待python执行结果超时"""
113
+
114
+
115
+ class PyTaskInvalidError(PyTaskError):
116
+ """无效的python任务ID"""
117
+
118
+
119
+ class PyTaskRevokedError(PyTaskError):
120
+ """python脚本被中断执行"""
121
+
122
+
123
+ class PyTaskRunTimeError(PyTaskError):
124
+ """执行脚本出错"""
125
+ base_msg = 'python脚本执行时发生错误,错误信息:\n{}'
126
+
127
+
128
+ class PyTaskConcurrencyExceed(PyTaskError):
129
+ """任务并发数过高"""
130
+ base_msg = '当前节点[{}]尝试获取结果的python任务并发数[{}]过高,请稍后尝试获取结果'
131
+
132
+
133
+ class PyTaskTimeLimitExceed(PyTaskError):
134
+ """python脚本运行时间超过最大限制"""
135
+
136
+
137
+ # -----------------------------------------------------------------------------
138
+ # FinancialCube Error
139
+ class MDXExecuteTimeout(DeepfosBaseException):
140
+ """执行MDX任务超时"""
141
+
142
+
143
+ class MDXExecuteFail(DeepfosBaseException):
144
+ """执行MDX任务失败"""
145
+
146
+
147
+ # -----------------------------------------------------------------------------
148
+ # DeepModel Error
149
+ class DeepModelError(DeepfosBaseException):
150
+ """DeepModel相关报错基类"""
151
+
152
+
153
+ class ObjectNotExist(DeepModelError):
154
+ """DeepModel对象不存在"""
155
+
156
+
157
+ class RequiredFieldUnfilled(DeepModelError):
158
+ """缺少必填字段"""
159
+
160
+
161
+ class ExternalObjectReadOnly(DeepModelError):
162
+ """外部对象只可读"""
163
+
164
+
165
+ class RelationRequired(DeepModelError):
166
+ """multi link字段缺少relation信息"""
167
+
168
+
169
+ class SingleLinkInRelation(DeepModelError):
170
+ """single link字段出现在relation中"""
171
+
172
+
173
+ class MultiLinkTargetNotUnique(DeepModelError):
174
+ """relation信息source的target不唯一"""
175
+
176
+
177
+ # -----------------------------------------------------------------------------
178
+ # JournalModel Error
179
+ class JournalModelError(DeepfosBaseException):
180
+ """JournalModel相关报错基类"""
181
+
182
+
183
+ class JournalModelSaveError(JournalModelError, ValueError):
184
+ """JournalModel保存失败"""
185
+
186
+
187
+ class JournalModelCheckError(JournalModelError):
188
+ """JournalModel校验失败"""
189
+
190
+
191
+ class JournalModelPostingError(JournalModelError):
192
+ """JournalModel过账/取消过账失败"""
193
+
194
+
195
+ # -----------------------------------------------------------------------------
196
+ # MsgCenter Error
197
+ class MsgCenterError(DeepfosBaseException):
198
+ """消息中心推送失败"""
199
+ def __init__(self, *reasons):
200
+ self.reasons = reasons
201
+
202
+ def __str__(self):
203
+ return '推送失败,报错信息:' + '\n'.join([r.errorMsg for r in self.reasons])
204
+
205
+
206
+ # -----------------------------------------------------------------------------
207
+ # DeepPipeline Error
208
+ class DeepPipelineRunError(DeepfosBaseException):
209
+ """执行脚本报错基类"""
210
+ base_msg = ''
211
+
212
+ def __init__(self, *reasons):
213
+ self.reasons = reasons
214
+
215
+ def __str__(self):
216
+ if self.base_msg and self.reasons:
217
+ return self.base_msg.format(*self.reasons)
218
+ return self.__class__.__doc__
219
+
220
+
221
+ class RunIdInvalid(DeepPipelineRunError):
222
+ """执行ID无效"""
223
+
224
+
225
+ class RunTerminated(DeepPipelineRunError):
226
+ """数据流执行被取消"""
227
+
228
+
229
+ class ReleaseFlowTimeout(DeepPipelineRunError):
230
+ """获取结果等待超时"""
231
+
232
+
233
+ class RunFailedError(DeepPipelineRunError):
234
+ """数据流执行失败"""
235
+ base_msg = '数据流执行失败,报错信息:{}'
236
+
237
+
238
+ class ReleaseFlowNotExists(DeepPipelineRunError):
239
+ """暂无启用中状态的数据流版本"""
@@ -0,0 +1,86 @@
1
+ import sys
2
+ import inspect
3
+
4
+ from collections import defaultdict
5
+ from types import TracebackType
6
+ from typing import Type, NamedTuple, Dict, Set, Union, Optional
7
+
8
+
9
+ _builtin_exp_hook = sys.excepthook
10
+
11
+
12
+ class CodeSpot(NamedTuple):
13
+ filename: str
14
+ first_lineno: int
15
+ last_lineno: Union[int, float]
16
+
17
+
18
+ class CodeLocator:
19
+ spots: Dict[str, Set[CodeSpot]] = defaultdict(set)
20
+
21
+ @classmethod
22
+ def add_spot(cls, spot: CodeSpot):
23
+ cls.spots[spot.filename].add(spot)
24
+
25
+ @classmethod
26
+ def contains_tb(cls, tb: TracebackType):
27
+ frame = inspect.getframeinfo(tb.tb_frame)
28
+ if frame.filename not in cls.spots:
29
+ return False
30
+
31
+ return any(
32
+ spot.first_lineno <= frame.lineno < spot.last_lineno
33
+ for spot in cls.spots[frame.filename]
34
+ )
35
+
36
+
37
+ def eliminate_from_traceback(obj):
38
+ """将对象从错误栈中移除(可作为装饰器)
39
+
40
+ Args:
41
+ obj: 需要排除的对象,可以是文件名,函数(方法),类
42
+
43
+ Notes:
44
+
45
+ - 由于技术原因,第一个错误栈无法移除。
46
+ - 出于可读性考虑,最后一个错误栈也不会移除
47
+
48
+ """
49
+ if isinstance(obj, str):
50
+ filename = obj
51
+ first_lineno = 0
52
+ last_lineno = float('inf')
53
+ else:
54
+ code, first_lineno = inspect.getsourcelines(obj)
55
+ last_lineno = first_lineno + len(code)
56
+ filename = inspect.getfile(obj)
57
+ CodeLocator.add_spot(CodeSpot(
58
+ filename=filename,
59
+ first_lineno=first_lineno,
60
+ last_lineno=last_lineno
61
+ ))
62
+ return obj
63
+
64
+
65
+ def exception_hook(
66
+ exc_type: Type[BaseException],
67
+ exc_value: BaseException,
68
+ tb: Optional[TracebackType]
69
+ ):
70
+ if tb is not None:
71
+ contains_tb = CodeLocator.contains_tb
72
+ tb_last = tb
73
+
74
+ while (tb_next := tb_last.tb_next) is not None:
75
+ if (
76
+ contains_tb(tb_next)
77
+ and (next_tb := tb_next.tb_next) is not None
78
+ ):
79
+ tb_last.tb_next = next_tb
80
+ else:
81
+ tb_last = tb_next
82
+
83
+ return _builtin_exp_hook(exc_type, exc_value, tb)
84
+
85
+
86
+ sys.excepthook = exception_hook
deepfos/lazy.py ADDED
@@ -0,0 +1,104 @@
1
+ import sys
2
+ from importlib import import_module
3
+ from types import ModuleType
4
+ from typing import Dict, Sequence, Any
5
+
6
+ from deepfos.lib.constant import UNSET
7
+ from deepfos.local import Proxy
8
+
9
+
10
+ class LazyModule(ModuleType):
11
+
12
+ def __init__(self, module_name, parent_module_globals):
13
+ self._module_name = module_name
14
+ self._parent_module_globals = parent_module_globals
15
+
16
+ super(LazyModule, self).__init__(module_name)
17
+
18
+ def _load(self):
19
+ """Load the module and insert it into the parent's globals."""
20
+ # Import the target module and insert it into the parent's namespace
21
+ module = import_module(self.__name__)
22
+ self._parent_module_globals[self._module_name] = module
23
+
24
+ # Update this object's dict so that if someone keeps a reference to the
25
+ # LazyLoader, lookups are efficient
26
+ # (__getattr__ is only called on lookups that fail).
27
+ self.__dict__.update(module.__dict__)
28
+
29
+ return module
30
+
31
+ def __getattr__(self, attr):
32
+ module = self._load()
33
+ return getattr(module, attr)
34
+
35
+ def __dir__(self):
36
+ module = self._load()
37
+ return dir(module)
38
+
39
+
40
+ class LazyCallable(Proxy):
41
+ def __init__(self, module, local_name):
42
+ object.__setattr__(self, '_LazyCallable__module', module)
43
+ object.__setattr__(self, '_LazyCallable__local_name', local_name)
44
+ object.__setattr__(self, '_LazyCallable__callable', UNSET)
45
+
46
+ __module__ = Proxy.__module__
47
+
48
+ def _get_current_object(self):
49
+ if self.__callable is not UNSET:
50
+ return self.__callable
51
+
52
+ try:
53
+ mod = sys.modules[self.__module]
54
+ except KeyError:
55
+ mod = lazy_module(self.__module)
56
+
57
+ object.__setattr__(
58
+ self, '_LazyCallable__callable',
59
+ getattr(mod, self.__local_name)
60
+ )
61
+ return self.__callable
62
+
63
+ def __await__(self):
64
+ return self._get_current_object().__await__()
65
+
66
+
67
+ def lazy_module(modname):
68
+ """获得懒加载模块
69
+
70
+ Args:
71
+ modname: 模块名,形如aaa.bbb.ccc,将得到等效于from aaa.bbb import ccc的懒加载模块
72
+
73
+
74
+ """
75
+ return LazyModule(modname, globals())
76
+
77
+
78
+ def lazy_callable(modname, *names):
79
+ """获得对应模块里的若干方法/函数的懒加载代理
80
+
81
+ Args:
82
+ modname : 模块名,形如aaa.bbb.ccc
83
+ names : 方法/函数名
84
+
85
+ """
86
+ return tuple(LazyCallable(modname, cname) for cname in names)
87
+
88
+
89
+ def lazify(
90
+ target: Dict[str, Sequence[str]],
91
+ _globals: Dict[str, Any]
92
+ ):
93
+ """懒加载模块成员
94
+
95
+ Args:
96
+ target: module to module members
97
+ _globals: globals in caller scope
98
+ """
99
+
100
+ for modname, mbrs in target.items():
101
+ _globals.update(zip(
102
+ mbrs,
103
+ lazy_callable(modname, *mbrs)
104
+ ))
deepfos/lazy_import.py ADDED
@@ -0,0 +1,84 @@
1
+ import sys
2
+ from importlib import import_module
3
+ from types import ModuleType
4
+
5
+ from deepfos.lib.constant import UNSET
6
+ from deepfos.local import Proxy
7
+
8
+
9
+ class LazyModule(ModuleType):
10
+
11
+ def __init__(self, module_name, parent_module_globals):
12
+ self._module_name = module_name
13
+ self._parent_module_globals = parent_module_globals
14
+
15
+ super(LazyModule, self).__init__(module_name)
16
+
17
+ def _load(self):
18
+ """Load the module and insert it into the parent's globals."""
19
+ # Import the target module and insert it into the parent's namespace
20
+ module = import_module(self.__name__)
21
+ self._parent_module_globals[self._module_name] = module
22
+
23
+ # Update this object's dict so that if someone keeps a reference to the
24
+ # LazyLoader, lookups are efficient
25
+ # (__getattr__ is only called on lookups that fail).
26
+ self.__dict__.update(module.__dict__)
27
+
28
+ return module
29
+
30
+ def __getattr__(self, attr):
31
+ module = self._load()
32
+ return getattr(module, attr)
33
+
34
+ def __dir__(self):
35
+ module = self._load()
36
+ return dir(module)
37
+
38
+
39
+ class LazyCallable(Proxy):
40
+ def __init__(self, module, local_name):
41
+ object.__setattr__(self, '_LazyCallable__module', module)
42
+ object.__setattr__(self, '_LazyCallable__local_name', local_name)
43
+ object.__setattr__(self, '_LazyCallable__callable', UNSET)
44
+
45
+ __module__ = Proxy.__module__
46
+
47
+ def _get_current_object(self):
48
+ if self.__callable is not UNSET:
49
+ return self.__callable
50
+
51
+ try:
52
+ mod = sys.modules[self.__module]
53
+ except KeyError:
54
+ mod = lazy_module(self.__module)
55
+
56
+ object.__setattr__(self, '_LazyCallable__callable', getattr(mod, self.__local_name))
57
+ return self.__callable
58
+
59
+ def __await__(self):
60
+ return self._get_current_object().__await__()
61
+
62
+
63
+ def lazy_module(modname):
64
+ """获得懒加载模块
65
+
66
+ Args:
67
+ modname: 模块名,形如aaa.bbb.ccc,将得到等效于from aaa.bbb import ccc的懒加载模块
68
+
69
+
70
+ """
71
+ class _LazyModule(LazyModule):
72
+ pass
73
+ return _LazyModule(modname, globals())
74
+
75
+
76
+ def lazy_callable(modname, *names):
77
+ """获得对应模块里的若干方法/函数的懒加载代理
78
+
79
+ Args:
80
+ modname : 模块名,形如aaa.bbb.ccc
81
+ names : 方法/函数名
82
+
83
+ """
84
+ return tuple(LazyCallable(modname, cname) for cname in names)
File without changes