deepfos 1.1.75__tar.gz → 1.1.77__tar.gz

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 (192) hide show
  1. {deepfos-1.1.75 → deepfos-1.1.77}/CHANGELOG.md +17 -0
  2. {deepfos-1.1.75 → deepfos-1.1.77}/PKG-INFO +1 -1
  3. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/_version.py +3 -3
  4. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/V1_2/models/dimension.py +1 -0
  5. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/account.py +1 -0
  6. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/app.py +1 -0
  7. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/base.py +12 -1
  8. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/dimension.py +1 -0
  9. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/platform.py +1 -0
  10. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/space.py +1 -0
  11. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/system.py +1 -0
  12. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/deepmodel.py +91 -38
  13. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/dimension.py +16 -3
  14. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/discovery.py +3 -0
  15. deepfos-1.1.77/deepfos/lib/k8s.py +101 -0
  16. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/options.py +19 -5
  17. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos.egg-info/PKG-INFO +1 -1
  18. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos.egg-info/SOURCES.txt +2 -0
  19. {deepfos-1.1.75 → deepfos-1.1.77}/.gitattributes +0 -0
  20. {deepfos-1.1.75 → deepfos-1.1.77}/.gitee/ISSUE_GUIDELINES.md +0 -0
  21. {deepfos-1.1.75 → deepfos-1.1.77}/.gitee/ISSUE_TEMPLATE.md +0 -0
  22. {deepfos-1.1.75 → deepfos-1.1.77}/.gitignore +0 -0
  23. {deepfos-1.1.75 → deepfos-1.1.77}/MANIFEST.in +0 -0
  24. {deepfos-1.1.75 → deepfos-1.1.77}/README.md +0 -0
  25. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/__init__.py +0 -0
  26. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/algo/__init__.py +0 -0
  27. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/algo/graph.py +0 -0
  28. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/V1_1/__init__.py +0 -0
  29. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/V1_1/business_model.py +0 -0
  30. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/V1_1/dimension.py +0 -0
  31. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/V1_1/models/__init__.py +0 -0
  32. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/V1_1/models/business_model.py +0 -0
  33. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/V1_1/models/dimension.py +0 -0
  34. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/V1_2/__init__.py +0 -0
  35. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/V1_2/dimension.py +0 -0
  36. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/V1_2/models/__init__.py +0 -0
  37. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/__init__.py +0 -0
  38. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/accounting_engines.py +0 -0
  39. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/approval_process.py +0 -0
  40. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/business_model.py +0 -0
  41. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/consolidation.py +0 -0
  42. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/consolidation_process.py +0 -0
  43. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/datatable.py +0 -0
  44. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/deep_pipeline.py +0 -0
  45. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/deepconnector.py +0 -0
  46. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/deepfos_task.py +0 -0
  47. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/deepmodel.py +0 -0
  48. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/dimension.py +0 -0
  49. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/financial_model.py +0 -0
  50. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/journal_model.py +0 -0
  51. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/journal_template.py +0 -0
  52. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/memory_financial_model.py +0 -0
  53. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/__init__.py +0 -0
  54. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/account.py +0 -0
  55. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/accounting_engines.py +0 -0
  56. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/app.py +0 -0
  57. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/approval_process.py +0 -0
  58. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/base.py +0 -0
  59. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/business_model.py +0 -0
  60. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/consolidation.py +0 -0
  61. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/consolidation_process.py +0 -0
  62. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/datatable_mysql.py +0 -0
  63. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/deep_pipeline.py +0 -0
  64. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/deepconnector.py +0 -0
  65. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/deepfos_task.py +0 -0
  66. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/deepmodel.py +0 -0
  67. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/financial_model.py +0 -0
  68. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/journal_model.py +0 -0
  69. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/journal_template.py +0 -0
  70. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/memory_financial_model.py +0 -0
  71. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/platform.py +0 -0
  72. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/python.py +0 -0
  73. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/reconciliation_engine.py +0 -0
  74. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/reconciliation_report.py +0 -0
  75. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/role_strategy.py +0 -0
  76. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/smartlist.py +0 -0
  77. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/space.py +0 -0
  78. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/system.py +0 -0
  79. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/variable.py +0 -0
  80. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/models/workflow.py +0 -0
  81. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/python.py +0 -0
  82. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/reconciliation_engine.py +0 -0
  83. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/reconciliation_report.py +0 -0
  84. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/role_strategy.py +0 -0
  85. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/smartlist.py +0 -0
  86. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/variable.py +0 -0
  87. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/api/workflow.py +0 -0
  88. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/boost/__init__.py +0 -0
  89. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/boost/jstream.c +0 -0
  90. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/boost/jstream.pyx +0 -0
  91. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/boost/pandas.c +0 -0
  92. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/boost/pandas.pyx +0 -0
  93. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/boost/py_jstream.py +0 -0
  94. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/boost/py_pandas.py +0 -0
  95. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/cache.py +0 -0
  96. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/config.py +0 -0
  97. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/__init__.py +0 -0
  98. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/cube/__init__.py +0 -0
  99. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/cube/_base.py +0 -0
  100. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/cube/constants.py +0 -0
  101. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/cube/cube.py +0 -0
  102. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/cube/formula.py +0 -0
  103. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/cube/syscube.py +0 -0
  104. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/cube/typing.py +0 -0
  105. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/cube/utils.py +0 -0
  106. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/dimension/__init__.py +0 -0
  107. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/dimension/_base.py +0 -0
  108. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/dimension/dimcreator.py +0 -0
  109. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/dimension/dimension.py +0 -0
  110. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/dimension/dimexpr.py +0 -0
  111. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/dimension/dimmember.py +0 -0
  112. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/dimension/eledimension.py +0 -0
  113. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/dimension/filters.py +0 -0
  114. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/dimension/sysdimension.py +0 -0
  115. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/logictable/__init__.py +0 -0
  116. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/logictable/_cache.py +0 -0
  117. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/logictable/_operator.py +0 -0
  118. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/logictable/nodemixin.py +0 -0
  119. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/logictable/sqlcondition.py +0 -0
  120. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/core/logictable/tablemodel.py +0 -0
  121. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/__init__.py +0 -0
  122. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/cipher.py +0 -0
  123. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/clickhouse.py +0 -0
  124. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/connector.py +0 -0
  125. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/daclickhouse.py +0 -0
  126. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/dameng.py +0 -0
  127. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/damysql.py +0 -0
  128. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/dbkits.py +0 -0
  129. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/deepengine.py +0 -0
  130. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/deepmodel.py +0 -0
  131. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/deepmodel_kingbase.py +0 -0
  132. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/edb.py +0 -0
  133. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/gauss.py +0 -0
  134. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/kingbase.py +0 -0
  135. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/mysql.py +0 -0
  136. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/oracle.py +0 -0
  137. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/postgresql.py +0 -0
  138. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/sqlserver.py +0 -0
  139. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/db/utils.py +0 -0
  140. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/__init__.py +0 -0
  141. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/accounting.py +0 -0
  142. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/apvlprocess.py +0 -0
  143. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/base.py +0 -0
  144. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/bizmodel.py +0 -0
  145. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/datatable.py +0 -0
  146. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/deep_pipeline.py +0 -0
  147. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/deepconnector.py +0 -0
  148. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/fact_table.py +0 -0
  149. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/finmodel.py +0 -0
  150. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/journal.py +0 -0
  151. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/journal_template.py +0 -0
  152. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/pyscript.py +0 -0
  153. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/reconciliation.py +0 -0
  154. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/rolestrategy.py +0 -0
  155. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/smartlist.py +0 -0
  156. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/variable.py +0 -0
  157. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/element/workflow.py +0 -0
  158. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/exceptions/__init__.py +0 -0
  159. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/exceptions/hook.py +0 -0
  160. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lazy.py +0 -0
  161. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/__init__.py +0 -0
  162. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/_javaobj.py +0 -0
  163. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/asynchronous.py +0 -0
  164. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/concurrency.py +0 -0
  165. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/constant.py +0 -0
  166. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/decorator.py +0 -0
  167. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/deepchart.py +0 -0
  168. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/deepux.py +0 -0
  169. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/edb_lexer.py +0 -0
  170. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/eureka.py +0 -0
  171. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/filterparser.py +0 -0
  172. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/httpcli.py +0 -0
  173. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/jsonstreamer.py +0 -0
  174. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/msg.py +0 -0
  175. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/nacos.py +0 -0
  176. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/patch.py +0 -0
  177. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/redis.py +0 -0
  178. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/serutils.py +0 -0
  179. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/stopwatch.py +0 -0
  180. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/subtask.py +0 -0
  181. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/sysutils.py +0 -0
  182. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/lib/utils.py +0 -0
  183. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/local.py +0 -0
  184. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos/translation.py +0 -0
  185. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos.egg-info/dependency_links.txt +0 -0
  186. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos.egg-info/not-zip-safe +0 -0
  187. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos.egg-info/requires.txt +0 -0
  188. {deepfos-1.1.75 → deepfos-1.1.77}/deepfos.egg-info/top_level.txt +0 -0
  189. {deepfos-1.1.75 → deepfos-1.1.77}/requirements.txt +0 -0
  190. {deepfos-1.1.75 → deepfos-1.1.77}/setup.cfg +0 -0
  191. {deepfos-1.1.75 → deepfos-1.1.77}/setup.py +0 -0
  192. {deepfos-1.1.75 → deepfos-1.1.77}/versioneer.py +0 -0
@@ -1,3 +1,20 @@
1
+ ## [1.1.77] - 2025-12-05
2
+
3
+ ### 新增
4
+
5
+ * 支持k8s作为服务发现
6
+ * 支持RootAPI从服务发现中获取url
7
+
8
+
9
+ ## [1.1.76] - 2025-11-06
10
+
11
+ ### 更新
12
+
13
+ * 维度增加dataTypeInfo字段
14
+ * DeepModel增加error_on_empty_link
15
+ * insert_df性能优化
16
+
17
+
1
18
  ## [1.1.75] - 2025-09-17
2
19
 
3
20
  ### 更新
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deepfos
3
- Version: 1.1.75
3
+ Version: 1.1.77
4
4
  Summary: Collecions of useful and handy tools for deepfos platform
5
5
  Home-page: http://py.deepfos.com
6
6
  Author: deepfos-python-team
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-09-18T10:14:56+0000",
11
+ "date": "2025-12-05T02:41:19+0000",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "874420bc37e43a0b78366335290be2dbff468540",
15
- "version": "1.1.75"
14
+ "full-revisionid": "bd3d3dac6c3b6e4d9a695174c9064820da0912b6",
15
+ "version": "1.1.77"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -877,6 +877,7 @@ class DimensionMemberNewDto(BaseModel):
877
877
 
878
878
 
879
879
  class DimensionMemberOperationDto(BaseModel):
880
+ dataTypeInfo: Optional[str] = None
880
881
  #: 变动类型
881
882
  moveType: Optional[str] = None
882
883
  #: 科目类型,科目类特有属性
@@ -120,6 +120,7 @@ class UserImport(ChildAPI):
120
120
  class AccountAPI(RootAPI):
121
121
  """账户中心"""
122
122
  prefix = lambda: OPTION.server.account
123
+ server_name = "seepln-account"
123
124
 
124
125
  def __init__(self, *args, **kwargs):
125
126
  super(self.__class__.__base__, self).__init__(*args, **kwargs)
@@ -580,6 +580,7 @@ class PermissionAPI(ChildAPI):
580
580
  class AppAPI(RootAPI):
581
581
  """应用服务接口"""
582
582
  prefix = lambda: OPTION.server.app
583
+ server_name = "app-server"
583
584
 
584
585
  @cached_property
585
586
  def element_info(self) -> AppElementInfoAPI:
@@ -722,6 +722,7 @@ class RootAPI:
722
722
  api_version = None
723
723
  cls_name = None
724
724
  module_name = None
725
+ server_name = None
725
726
  builtin = True
726
727
 
727
728
  if TYPE_CHECKING: # pragma: no cover
@@ -859,7 +860,17 @@ class RootAPI:
859
860
 
860
861
  """
861
862
  clz = cls.resolve_cls(sync, SyncAPIBase, AsyncAPIBase)
862
- ins = clz(header=header, prefix=cls.prefix())
863
+ if (
864
+ OPTION.discovery.enabled
865
+ and OPTION.discovery.take_over
866
+ and cls.server_name is not None
867
+ ):
868
+ discovery = ServiceDiscovery.instantiate()
869
+ prefix = discovery.sync_get_url(cls.server_name)
870
+ else:
871
+ prefix = cls.prefix()
872
+
873
+ ins = clz(header=header, prefix=prefix)
863
874
  ins.sync = sync
864
875
  ins.multi_version = cls.multi_version
865
876
  ins.default_version = cls.default_version
@@ -542,6 +542,7 @@ class DimensionMemberListDto(BaseModel):
542
542
 
543
543
 
544
544
  class DimensionMemberOperationSw(BaseModel):
545
+ dataTypeInfo: Optional[str] = None
545
546
  #: 变动类型
546
547
  moveType: Optional[str] = None
547
548
  #: 支付类型,科目类型特有
@@ -175,6 +175,7 @@ class FilePyAPI(ChildAPI):
175
175
  class PlatformAPI(RootAPI):
176
176
  """文件上传服务接口"""
177
177
  prefix = lambda: OPTION.server.platform_file
178
+ server_name = "platform-file-server"
178
179
 
179
180
  @cached_property
180
181
  def file(self) -> StdFileAPI:
@@ -522,6 +522,7 @@ class SpaceInternalAPI(ChildAPI):
522
522
  class SpaceAPI(RootAPI):
523
523
  """空间服务接口"""
524
524
  prefix = lambda: OPTION.server.space
525
+ server_name = "space-server"
525
526
 
526
527
  @cached_property
527
528
  def app(self) -> SpaceAppAPI:
@@ -312,6 +312,7 @@ class Space(ChildAPI):
312
312
  class SystemAPI(RootAPI):
313
313
  """系统服务接口"""
314
314
  prefix = lambda: OPTION.server.system
315
+ server_name = "system-server"
315
316
 
316
317
  @cached_property
317
318
  def data_source(self) -> SysDataSourceAPI:
@@ -304,20 +304,43 @@ class ObjectTypeFrame(BaseModel):
304
304
  return exclusive
305
305
 
306
306
 
307
- def _format_link(df: pd.DataFrame, link_name: str):
308
- if all(pd.isnull(df['target'])):
309
- return {'target': pd.NA}
307
+ def _format_link(link_df_fit: pd.DataFrame, link_name: str):
308
+ if link_df_fit.empty:
309
+ return pd.Series(dtype=object), False
310
310
 
311
- record = df.drop(columns=['source']).set_index('target')
312
-
313
- if not record.index.is_unique:
311
+ if link_df_fit.duplicated(subset=['source', 'target']).any():
314
312
  raise MultiLinkTargetNotUnique(
315
313
  f'Multi Link: [{link_name}] relation dataframe中'
316
314
  f'source与target对应存在不唯一性'
317
315
  )
318
316
 
319
- record = record.to_dict(orient='index')
320
- return {'prop': record, 'target': list(record.keys())}
317
+ prop_cols = [col for col in link_df_fit.columns if col not in ['source', 'target']]
318
+ has_props = bool(prop_cols)
319
+
320
+ if has_props:
321
+ sources = link_df_fit['source'].values
322
+ targets = link_df_fit['target'].values
323
+ unique_sources, source_indices = np.unique(sources, return_inverse=True)
324
+
325
+ prop_arrays = {col: link_df_fit[col].values for col in prop_cols}
326
+ result = {}
327
+
328
+ for i in range(len(unique_sources)):
329
+ idx = source_indices == i
330
+ source = unique_sources[i]
331
+ source_targets = targets[idx]
332
+
333
+ indices = np.where(idx)[0]
334
+ prop_dict = {
335
+ source_targets[j]: {col: prop_arrays[col][indices[j]] for col in prop_cols}
336
+ for j in range(len(source_targets))
337
+ }
338
+ result[source] = {'target': source_targets.tolist(), 'prop': prop_dict}
339
+ link = pd.Series(result, dtype=object)
340
+ else:
341
+ link = link_df_fit.groupby('source')['target'].agg(list)
342
+
343
+ return link, has_props
321
344
 
322
345
 
323
346
  class BaseField(PtrInfo):
@@ -486,7 +509,8 @@ def _iter_link_prop_assign(link, business_key, prop_name, prop_type, is_multi):
486
509
  def _iter_single_assign(
487
510
  field: PtrInfo,
488
511
  cast_type: str,
489
- target_main_field: Dict[str, MainField]
512
+ target_main_field: Dict[str, MainField],
513
+ error_on_empty_link: bool = False
490
514
  ) -> str:
491
515
  """
492
516
  生成单字段赋值语句
@@ -495,6 +519,7 @@ def _iter_single_assign(
495
519
  field: 字段信息
496
520
  cast_type: 字段类型
497
521
  target_main_field: 目标字段信息
522
+ error_on_empty_link: 链接字段值不存在时是否抛出异常
498
523
 
499
524
  Returns:
500
525
  赋值语句
@@ -517,30 +542,38 @@ def _iter_single_assign(
517
542
  main_field = target_main_field[link]
518
543
 
519
544
  if main_field.props:
520
- target = (
521
- cast_type + "{" +
522
- ",".join(
523
- _iter_link_prop_assign(link, main_field.business_key, name,
524
- field.prop_type[name], main_field.is_multi)
525
- for name in main_field.props
526
- ) + "}"
545
+ prop_assigns = ','.join(
546
+ _iter_link_prop_assign(link, main_field.business_key, name,
547
+ field.prop_type[name], main_field.is_multi)
548
+ for name in main_field.props
527
549
  )
550
+ prop_block = f" {{{prop_assigns}}}"
528
551
  else:
529
- target = cast_type
552
+ prop_block = ""
530
553
 
531
554
  if main_field.is_multi:
555
+ link_value = f"each_{link}"
556
+ else:
557
+ link_value = f"(json_get(item, '{link}'))"
558
+
559
+ if error_on_empty_link:
560
+ link_expr = f"(<{cast_type}><std::str>{link_value}){prop_block}"
561
+ else:
562
+ link_expr = f"(select detached {cast_type}{prop_block}\nfilter .{main_field.business_key} = <std::str>{link_value})"
563
+
564
+ if main_field.is_multi:
565
+ if main_field.props:
566
+ target_source = f"json_get(item, '{link}', 'target')"
567
+ else:
568
+ target_source = f"item['{link}']"
569
+
532
570
  assign += 'distinct (\n' + textwrap.indent(textwrap.dedent(f"""\
533
- for each_{link} in json_array_unpack(json_get(item, '{link}', 'target'))
571
+ for each_{link} in json_array_unpack({target_source})
534
572
  union (
535
- select detached {target}
536
- filter .{main_field.business_key} = <{main_field.type}>each_{link}
573
+ {link_expr}
537
574
  )"""), TAB) + '\n)'
538
575
  else:
539
- assign += textwrap.dedent(f"""\
540
- assert_single((
541
- select detached {target}
542
- filter .{main_field.business_key} = <{main_field.type}>(json_get(item, '{link}'))
543
- ))""")
576
+ assign += link_expr
544
577
 
545
578
  return assign
546
579
 
@@ -549,9 +582,10 @@ def bulk_insert_by_fields(
549
582
  object_name: str,
550
583
  field_type: List[PtrInfo],
551
584
  target_main_field: Dict[str, MainField],
585
+ error_on_empty_link: bool = False,
552
586
  ):
553
587
  insert_assign_body = ','.join([
554
- _iter_single_assign(field, field.type, target_main_field)
588
+ _iter_single_assign(field, field.type, target_main_field, error_on_empty_link)
555
589
  for field in field_type
556
590
  ])
557
591
  return textwrap.dedent(f"""
@@ -567,16 +601,17 @@ def bulk_upsert_by_fields(
567
601
  field_type: List[PtrInfo],
568
602
  target_main_field: Dict[str, MainField],
569
603
  exclusive_fields: Iterable[str],
570
- update_fields: Iterable[str]
604
+ update_fields: Iterable[str],
605
+ error_on_empty_link: bool = False,
571
606
  ):
572
607
  conflict_on_fields = map(lambda n: f'.{n}', exclusive_fields)
573
608
  insert_assign_body = ','.join([
574
- _iter_single_assign(field, field.type, target_main_field)
609
+ _iter_single_assign(field, field.type, target_main_field, error_on_empty_link)
575
610
  for field in field_type
576
611
  ])
577
612
  update_assign_body = ','.join(
578
613
  [
579
- _iter_single_assign(field, field.type, target_main_field)
614
+ _iter_single_assign(field, field.type, target_main_field, error_on_empty_link)
580
615
  for field in field_type if field.name in update_fields
581
616
  ]
582
617
  )
@@ -599,9 +634,10 @@ def bulk_update_by_fields(
599
634
  target_main_field: Dict[str, MainField],
600
635
  match_fields: Iterable[str],
601
636
  update_fields: Iterable[str],
637
+ error_on_empty_link: bool = False,
602
638
  ):
603
639
  update_assign_body = ','.join([
604
- _iter_single_assign(field, field.type, target_main_field)
640
+ _iter_single_assign(field, field.type, target_main_field, error_on_empty_link)
605
641
  for field in field_type if field.name in update_fields
606
642
  ])
607
643
 
@@ -1374,9 +1410,20 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1374
1410
  ]
1375
1411
  )
1376
1412
  link_df = temp_structure.fit(link_df)
1377
- link = link_df.groupby('source').apply(_format_link, link_name=name)
1378
- data = data.drop(columns=[name], errors='ignore')
1379
- data = data.join(link.to_frame(name), on=bkey)
1413
+ link, has_props = _format_link(link_df, name)
1414
+
1415
+ if not has_props:
1416
+ data = data.drop(columns=[name], errors='ignore')
1417
+ data = data.join(link.to_frame(name), on=bkey, how='left')
1418
+ mask = data[name].isna()
1419
+ if mask.any():
1420
+ empty_series = pd.Series([[]] * mask.sum(), index=data[mask].index, dtype=object)
1421
+ data.loc[mask, name] = empty_series
1422
+ else:
1423
+ bkey_values = data[bkey].values
1424
+ mapped_values = np.array([link.get(key, []) for key in bkey_values], dtype=object)
1425
+ data[name] = mapped_values
1426
+
1380
1427
  return data
1381
1428
 
1382
1429
  async def _collect_bulk_qls(
@@ -1389,7 +1436,8 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1389
1436
  update_fields: Iterable[str] = None,
1390
1437
  exclusive_fields: Iterable[str] = None,
1391
1438
  match_fields: Iterable[str] = None,
1392
- insert: bool = True
1439
+ insert: bool = True,
1440
+ error_on_empty_link: bool = False
1393
1441
  ) -> List[List[QueryWithArgs]]:
1394
1442
  if object_name in self.objects:
1395
1443
  obj = self.objects[object_name]
@@ -1425,10 +1473,10 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1425
1473
  if enable_upsert and update_fields:
1426
1474
  bulk_ql = bulk_upsert_by_fields(
1427
1475
  object_name, field_info, tgt_main_field,
1428
- exclusive_fields, update_fields
1476
+ exclusive_fields, update_fields, error_on_empty_link
1429
1477
  )
1430
1478
  else:
1431
- bulk_ql = bulk_insert_by_fields(object_name, field_info, tgt_main_field)
1479
+ bulk_ql = bulk_insert_by_fields(object_name, field_info, tgt_main_field, error_on_empty_link)
1432
1480
  else:
1433
1481
  if missing := (set(match_fields or [bkey]) - set(field_names)):
1434
1482
  raise ValueError(f"match fields: {missing} 不在提供的数据中")
@@ -1437,7 +1485,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1437
1485
  if to_upd := (field_names - match_fields):
1438
1486
  bulk_ql = bulk_update_by_fields(
1439
1487
  object_name, field_info, tgt_main_field,
1440
- match_fields, to_upd
1488
+ match_fields, to_upd, error_on_empty_link
1441
1489
  )
1442
1490
  else:
1443
1491
  bulk_ql = None
@@ -1473,6 +1521,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1473
1521
  update_fields: Iterable[str] = None,
1474
1522
  exclusive_fields: Iterable[str] = None,
1475
1523
  commit_per_chunk: bool = False,
1524
+ error_on_empty_link: bool = False,
1476
1525
  ) -> None:
1477
1526
  """以事务执行基于DataFrame字段信息的批量插入数据
1478
1527
 
@@ -1496,6 +1545,9 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1496
1545
  commit_per_chunk: 每次插入后是否提交事务,
1497
1546
  默认为False,即所有数据插入后再提交事务
1498
1547
  该参数仅在非start transaction上下文中生效
1548
+ error_on_empty_link: 链接字段值不存在时是否抛出异常,
1549
+ 默认为False,即不检查链接目标是否存在
1550
+ 当设置为True时,会检查链接目标是否存在,不存在则抛出异常
1499
1551
 
1500
1552
  Notes:
1501
1553
 
@@ -1571,7 +1623,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1571
1623
  qls = await self._collect_bulk_qls(
1572
1624
  object_name, data, relation, chunksize,
1573
1625
  enable_upsert, update_fields, exclusive_fields,
1574
- insert=True
1626
+ insert=True, error_on_empty_link=error_on_empty_link
1575
1627
  )
1576
1628
  if commit_per_chunk:
1577
1629
  for ql_chunk in qls:
@@ -1918,6 +1970,7 @@ class DeepModel(AsyncDeepModel, metaclass=SyncMeta):
1918
1970
  update_fields: Iterable[str] = None,
1919
1971
  exclusive_fields: Iterable[str] = None,
1920
1972
  commit_per_chunk: bool = False,
1973
+ error_on_empty_link: bool = False,
1921
1974
  ) -> None:
1922
1975
  ...
1923
1976
 
@@ -1162,12 +1162,25 @@ def _validate_df_for_dimension(df: pd.DataFrame):
1162
1162
  f"You have null value in dataframe. "
1163
1163
  f"column: [{DFLT_NAME_COLUMN}], index: {null_index}.")
1164
1164
 
1165
- if DFLT_PNAME_COLUMN not in df.columns:
1166
- raise ValueError(f"Missing column [{DFLT_PNAME_COLUMN}] in dataframe.")
1165
+ col_parent_name = None
1166
+ col_shared_member = None
1167
+
1168
+ if DFLT_PNAME_COLUMN in df.columns:
1169
+ col_parent_name = DFLT_PNAME_COLUMN
1170
+ elif DFLT_PNAME_COLUMN_V12 in df.columns:
1171
+ col_parent_name = DFLT_PNAME_COLUMN_V12
1167
1172
 
1168
1173
  if SHAREDMEMBER in df.columns:
1174
+ col_shared_member = SHAREDMEMBER
1175
+ elif SHAREDMEMBERV12 in df.columns:
1176
+ col_shared_member = SHAREDMEMBERV12
1177
+
1178
+ if col_parent_name is None:
1179
+ raise ValueError(f"Missing column [{DFLT_PNAME_COLUMN}] or [{DFLT_PNAME_COLUMN_V12}] in dataframe.")
1180
+
1181
+ if col_shared_member is not None:
1169
1182
  unique_df = df.groupby(
1170
- [DFLT_NAME_COLUMN, DFLT_PNAME_COLUMN, SHAREDMEMBER],
1183
+ [DFLT_NAME_COLUMN, col_parent_name, col_shared_member],
1171
1184
  as_index=False
1172
1185
  ).size()
1173
1186
  duplicated = unique_df[unique_df['size'] > 1]
@@ -256,6 +256,9 @@ class ServiceDiscovery(ABC):
256
256
  elif impl == 'nacos':
257
257
  from deepfos.lib.nacos import Nacos
258
258
  cls.__ins__[impl] = Nacos
259
+ elif impl == 'k8s':
260
+ from deepfos.lib.k8s import K8s
261
+ cls.__ins__[impl] = K8s
259
262
 
260
263
  return cls.__ins__[impl]
261
264
 
@@ -0,0 +1,101 @@
1
+ import asyncio
2
+ from collections import defaultdict
3
+ from functools import cached_property
4
+ from typing import TypedDict, Literal, Type, Dict, FrozenSet
5
+
6
+ from loguru import logger
7
+ from kubernetes_asyncio import client, config
8
+ from kubernetes_asyncio.client import (
9
+ V1ServiceList,
10
+ V1Endpoints,
11
+ V1EndpointSubset,
12
+ V1EndpointAddress,
13
+ CoreV1EndpointPort,
14
+ )
15
+ from deepfos.lib.discovery import ServiceDiscovery
16
+ from deepfos import OPTION
17
+
18
+
19
+ class K8s(ServiceDiscovery):
20
+ def __init__(self):
21
+ super().__init__()
22
+ self._instance_lock: Dict[str, asyncio.Lock] = defaultdict(asyncio.Lock)
23
+ self._server_lock = asyncio.Lock()
24
+ self._cares = set()
25
+ self._ns = OPTION.k8s.namespace
26
+
27
+ async def on_close(self):
28
+ self._cares.clear()
29
+ self.server_cache.clear()
30
+ self._instance_lock.clear()
31
+
32
+ async def on_startup(self):
33
+ config.load_incluster_config()
34
+
35
+ @cached_property
36
+ def _api(self):
37
+ return client.CoreV1Api()
38
+
39
+ async def on_interval(self):
40
+ await self._update_cache()
41
+
42
+ async def _update_cache(self):
43
+ logger.opt(lazy=True).debug(f"Update cache for instance: {self._cares}")
44
+ await asyncio.gather(*(
45
+ self.update_instance_for_service(sn)
46
+ for sn in self._cares
47
+ ))
48
+
49
+ async def update_service_cache(self, server_name: str):
50
+ async with self._server_lock:
51
+ if server_name not in self.server_cache:
52
+ await self.update_services()
53
+
54
+ async def update_instance_cache(self, server_name):
55
+ self._cares.add(server_name)
56
+ await self.update_instance_for_service(server_name)
57
+
58
+
59
+ async def _list_all_service_names(self) -> FrozenSet[str]:
60
+ svcs: V1ServiceList = await self._api.list_namespaced_service(self._ns)
61
+ return frozenset(svc.metadata.name for svc in svcs.items)
62
+
63
+ async def update_services(self):
64
+ new_services = await self._list_all_service_names()
65
+ cur_services = frozenset(self.server_cache.keys())
66
+
67
+ if added := new_services - cur_services:
68
+ for srv in added:
69
+ self.server_cache.__getitem__(srv)
70
+ logger.debug(f"Added services: {added}")
71
+
72
+ if removed := cur_services - new_services:
73
+ for srv in removed:
74
+ self.server_cache.pop(srv)
75
+ self._instance_lock.pop(srv, None) # noqa
76
+ logger.debug(f"Removed servieces: {removed}")
77
+
78
+ async def update_instance_for_service(self, server_name: str):
79
+ endpoints: V1Endpoints = await self._api.read_namespaced_endpoints(
80
+ server_name,
81
+ self._ns,
82
+ )
83
+
84
+ no_active_nodes = True
85
+ async with self._instance_lock[server_name]:
86
+ cache = self.server_cache[server_name]
87
+
88
+ for subset in endpoints.subsets or []:
89
+ subset: V1EndpointSubset
90
+ for addr in subset.addresses or []:
91
+ addr: V1EndpointAddress
92
+ no_active_nodes = False
93
+ for port in subset.ports:
94
+ port: CoreV1EndpointPort
95
+ url = f"{port.name}://{addr.ip}:{port.port}"
96
+ cache.add(url)
97
+
98
+ if no_active_nodes:
99
+ logger.debug(f"{server_name} has no active endpoint, clear invalid...")
100
+ for item in list(cache):
101
+ cache.delete(item)
@@ -115,7 +115,8 @@ def _ensure_discovery_server_is_set(value):
115
115
  impl = OPTION.discovery.implementation
116
116
  server_opt = {
117
117
  'eureka': OPTION.server.eureka,
118
- 'nacos': OPTION.nacos.server
118
+ 'nacos': OPTION.nacos.server,
119
+ 'k8s': OPTION.k8s.namespace,
119
120
  }[impl]
120
121
 
121
122
  if server_opt is None:
@@ -379,9 +380,9 @@ class _Category:
379
380
  class _Server(_Category):
380
381
  __id__ = 'server_url'
381
382
 
382
- base = _Option('http://', val_type=str)
383
+ base = _Option('http://web-gateway', val_type=str)
383
384
  app = _Option('http://app-server', val_type=str)
384
- account = _Option('http://account-server', val_type=str)
385
+ account = _Option('http://seepln-account', val_type=str)
385
386
  system = _Option('http://system-server', val_type=str)
386
387
  space = _Option('http://space-server', val_type=str)
387
388
  platform_file = _Option('http://platform-file-server', val_type=str)
@@ -484,16 +485,18 @@ class _Boost(_Category):
484
485
  class _ServiceDiscovery(_Category):
485
486
  __id__ = 'service_discovery'
486
487
 
487
- #: 是否使用服务发现功能
488
+ #: 是否使用服务发现功能(仅影响DynamicAPI)
488
489
  enabled = _Option(False, val_type=bool, on_set=_ensure_discovery_server_is_set)
489
490
  #: 服务注册发现使用的实现
490
- implementation = _Option('eureka', val_type=str, val_choices=('eureka', 'nacos'))
491
+ implementation = _Option('eureka', val_type=str, val_choices=('eureka', 'nacos', 'k8s'))
491
492
  #: 服务注册发现使用的缓存策略
492
493
  cache_strategy = _Option(
493
494
  'ranked',
494
495
  val_type=str,
495
496
  val_choices=('ranked', 'roundrobin', 'random')
496
497
  )
498
+ #: 是否完全使用服务发现获取请求地址(包括Root API)
499
+ take_over = _Option(False, val_type=bool)
497
500
 
498
501
  def __get__(self, instance, owner) -> '_ServiceDiscovery':
499
502
  """defined to help ide"""
@@ -513,6 +516,16 @@ class _Nacos(_Category):
513
516
  return super().__get__(instance, owner)
514
517
 
515
518
 
519
+ class _Kubernets(_Category):
520
+ """Nacos 相关配置"""
521
+
522
+ namespace = _Option(None, val_type=str)
523
+
524
+ def __get__(self, instance, owner) -> '_Kubernets':
525
+ """defined to help ide"""
526
+ return super().__get__(instance, owner)
527
+
528
+
516
529
  # -----------------------------------------------------------------------------
517
530
  # Options
518
531
  class _GlobalOptions:
@@ -525,6 +538,7 @@ class _GlobalOptions:
525
538
  discovery = _ServiceDiscovery()
526
539
  nacos = _Nacos()
527
540
  edgedb = _Edgedb()
541
+ k8s = _Kubernets()
528
542
 
529
543
  def load_file(self, filepath):
530
544
  parser = configparser.ConfigParser()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deepfos
3
- Version: 1.1.75
3
+ Version: 1.1.77
4
4
  Summary: Collecions of useful and handy tools for deepfos platform
5
5
  Home-page: http://py.deepfos.com
6
6
  Author: deepfos-python-team
@@ -167,6 +167,7 @@ versioneer.py
167
167
  ./deepfos/lib/filterparser.py
168
168
  ./deepfos/lib/httpcli.py
169
169
  ./deepfos/lib/jsonstreamer.py
170
+ ./deepfos/lib/k8s.py
170
171
  ./deepfos/lib/msg.py
171
172
  ./deepfos/lib/nacos.py
172
173
  ./deepfos/lib/patch.py
@@ -348,6 +349,7 @@ deepfos/lib/eureka.py
348
349
  deepfos/lib/filterparser.py
349
350
  deepfos/lib/httpcli.py
350
351
  deepfos/lib/jsonstreamer.py
352
+ deepfos/lib/k8s.py
351
353
  deepfos/lib/msg.py
352
354
  deepfos/lib/nacos.py
353
355
  deepfos/lib/patch.py
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes