deepfos 1.1.77__tar.gz → 1.1.79__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.77 → deepfos-1.1.79}/CHANGELOG.md +16 -0
  2. {deepfos-1.1.77 → deepfos-1.1.79}/PKG-INFO +1 -1
  3. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/_version.py +3 -3
  4. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/base.py +68 -81
  5. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/financial_model.py +4 -0
  6. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/deepmodel.py +2 -2
  7. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/finmodel.py +19 -3
  8. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/edb_lexer.py +2 -0
  9. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/k8s.py +7 -1
  10. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/nacos.py +113 -22
  11. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/options.py +2 -0
  12. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos.egg-info/PKG-INFO +1 -1
  13. {deepfos-1.1.77 → deepfos-1.1.79}/setup.py +1 -1
  14. {deepfos-1.1.77 → deepfos-1.1.79}/.gitattributes +0 -0
  15. {deepfos-1.1.77 → deepfos-1.1.79}/.gitee/ISSUE_GUIDELINES.md +0 -0
  16. {deepfos-1.1.77 → deepfos-1.1.79}/.gitee/ISSUE_TEMPLATE.md +0 -0
  17. {deepfos-1.1.77 → deepfos-1.1.79}/.gitignore +0 -0
  18. {deepfos-1.1.77 → deepfos-1.1.79}/MANIFEST.in +0 -0
  19. {deepfos-1.1.77 → deepfos-1.1.79}/README.md +0 -0
  20. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/__init__.py +0 -0
  21. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/algo/__init__.py +0 -0
  22. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/algo/graph.py +0 -0
  23. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/V1_1/__init__.py +0 -0
  24. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/V1_1/business_model.py +0 -0
  25. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/V1_1/dimension.py +0 -0
  26. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/V1_1/models/__init__.py +0 -0
  27. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/V1_1/models/business_model.py +0 -0
  28. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/V1_1/models/dimension.py +0 -0
  29. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/V1_2/__init__.py +0 -0
  30. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/V1_2/dimension.py +0 -0
  31. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/V1_2/models/__init__.py +0 -0
  32. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/V1_2/models/dimension.py +0 -0
  33. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/__init__.py +0 -0
  34. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/account.py +0 -0
  35. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/accounting_engines.py +0 -0
  36. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/app.py +0 -0
  37. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/approval_process.py +0 -0
  38. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/business_model.py +0 -0
  39. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/consolidation.py +0 -0
  40. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/consolidation_process.py +0 -0
  41. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/datatable.py +0 -0
  42. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/deep_pipeline.py +0 -0
  43. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/deepconnector.py +0 -0
  44. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/deepfos_task.py +0 -0
  45. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/deepmodel.py +0 -0
  46. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/dimension.py +0 -0
  47. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/financial_model.py +0 -0
  48. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/journal_model.py +0 -0
  49. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/journal_template.py +0 -0
  50. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/memory_financial_model.py +0 -0
  51. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/__init__.py +0 -0
  52. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/account.py +0 -0
  53. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/accounting_engines.py +0 -0
  54. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/app.py +0 -0
  55. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/approval_process.py +0 -0
  56. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/base.py +0 -0
  57. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/business_model.py +0 -0
  58. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/consolidation.py +0 -0
  59. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/consolidation_process.py +0 -0
  60. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/datatable_mysql.py +0 -0
  61. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/deep_pipeline.py +0 -0
  62. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/deepconnector.py +0 -0
  63. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/deepfos_task.py +0 -0
  64. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/deepmodel.py +0 -0
  65. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/dimension.py +0 -0
  66. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/journal_model.py +0 -0
  67. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/journal_template.py +0 -0
  68. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/memory_financial_model.py +0 -0
  69. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/platform.py +0 -0
  70. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/python.py +0 -0
  71. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/reconciliation_engine.py +0 -0
  72. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/reconciliation_report.py +0 -0
  73. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/role_strategy.py +0 -0
  74. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/smartlist.py +0 -0
  75. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/space.py +0 -0
  76. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/system.py +0 -0
  77. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/variable.py +0 -0
  78. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/models/workflow.py +0 -0
  79. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/platform.py +0 -0
  80. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/python.py +0 -0
  81. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/reconciliation_engine.py +0 -0
  82. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/reconciliation_report.py +0 -0
  83. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/role_strategy.py +0 -0
  84. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/smartlist.py +0 -0
  85. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/space.py +0 -0
  86. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/system.py +0 -0
  87. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/variable.py +0 -0
  88. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/api/workflow.py +0 -0
  89. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/boost/__init__.py +0 -0
  90. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/boost/jstream.c +0 -0
  91. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/boost/jstream.pyx +0 -0
  92. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/boost/pandas.c +0 -0
  93. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/boost/pandas.pyx +0 -0
  94. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/boost/py_jstream.py +0 -0
  95. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/boost/py_pandas.py +0 -0
  96. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/cache.py +0 -0
  97. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/config.py +0 -0
  98. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/__init__.py +0 -0
  99. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/cube/__init__.py +0 -0
  100. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/cube/_base.py +0 -0
  101. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/cube/constants.py +0 -0
  102. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/cube/cube.py +0 -0
  103. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/cube/formula.py +0 -0
  104. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/cube/syscube.py +0 -0
  105. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/cube/typing.py +0 -0
  106. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/cube/utils.py +0 -0
  107. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/dimension/__init__.py +0 -0
  108. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/dimension/_base.py +0 -0
  109. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/dimension/dimcreator.py +0 -0
  110. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/dimension/dimension.py +0 -0
  111. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/dimension/dimexpr.py +0 -0
  112. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/dimension/dimmember.py +0 -0
  113. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/dimension/eledimension.py +0 -0
  114. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/dimension/filters.py +0 -0
  115. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/dimension/sysdimension.py +0 -0
  116. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/logictable/__init__.py +0 -0
  117. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/logictable/_cache.py +0 -0
  118. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/logictable/_operator.py +0 -0
  119. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/logictable/nodemixin.py +0 -0
  120. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/logictable/sqlcondition.py +0 -0
  121. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/core/logictable/tablemodel.py +0 -0
  122. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/__init__.py +0 -0
  123. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/cipher.py +0 -0
  124. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/clickhouse.py +0 -0
  125. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/connector.py +0 -0
  126. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/daclickhouse.py +0 -0
  127. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/dameng.py +0 -0
  128. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/damysql.py +0 -0
  129. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/dbkits.py +0 -0
  130. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/deepengine.py +0 -0
  131. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/deepmodel.py +0 -0
  132. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/deepmodel_kingbase.py +0 -0
  133. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/edb.py +0 -0
  134. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/gauss.py +0 -0
  135. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/kingbase.py +0 -0
  136. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/mysql.py +0 -0
  137. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/oracle.py +0 -0
  138. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/postgresql.py +0 -0
  139. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/sqlserver.py +0 -0
  140. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/db/utils.py +0 -0
  141. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/__init__.py +0 -0
  142. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/accounting.py +0 -0
  143. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/apvlprocess.py +0 -0
  144. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/base.py +0 -0
  145. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/bizmodel.py +0 -0
  146. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/datatable.py +0 -0
  147. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/deep_pipeline.py +0 -0
  148. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/deepconnector.py +0 -0
  149. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/dimension.py +0 -0
  150. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/fact_table.py +0 -0
  151. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/journal.py +0 -0
  152. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/journal_template.py +0 -0
  153. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/pyscript.py +0 -0
  154. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/reconciliation.py +0 -0
  155. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/rolestrategy.py +0 -0
  156. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/smartlist.py +0 -0
  157. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/variable.py +0 -0
  158. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/element/workflow.py +0 -0
  159. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/exceptions/__init__.py +0 -0
  160. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/exceptions/hook.py +0 -0
  161. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lazy.py +0 -0
  162. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/__init__.py +0 -0
  163. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/_javaobj.py +0 -0
  164. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/asynchronous.py +0 -0
  165. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/concurrency.py +0 -0
  166. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/constant.py +0 -0
  167. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/decorator.py +0 -0
  168. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/deepchart.py +0 -0
  169. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/deepux.py +0 -0
  170. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/discovery.py +0 -0
  171. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/eureka.py +0 -0
  172. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/filterparser.py +0 -0
  173. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/httpcli.py +0 -0
  174. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/jsonstreamer.py +0 -0
  175. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/msg.py +0 -0
  176. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/patch.py +0 -0
  177. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/redis.py +0 -0
  178. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/serutils.py +0 -0
  179. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/stopwatch.py +0 -0
  180. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/subtask.py +0 -0
  181. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/sysutils.py +0 -0
  182. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/lib/utils.py +0 -0
  183. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/local.py +0 -0
  184. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos/translation.py +0 -0
  185. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos.egg-info/SOURCES.txt +0 -0
  186. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos.egg-info/dependency_links.txt +0 -0
  187. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos.egg-info/not-zip-safe +0 -0
  188. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos.egg-info/requires.txt +0 -0
  189. {deepfos-1.1.77 → deepfos-1.1.79}/deepfos.egg-info/top_level.txt +0 -0
  190. {deepfos-1.1.77 → deepfos-1.1.79}/requirements.txt +0 -0
  191. {deepfos-1.1.77 → deepfos-1.1.79}/setup.cfg +0 -0
  192. {deepfos-1.1.77 → deepfos-1.1.79}/versioneer.py +0 -0
@@ -1,3 +1,19 @@
1
+ ## [1.1.79] - 2026-01-12
2
+
3
+ ### 更新
4
+
5
+ * k8s客户端不校验证书有效性
6
+ * FinancialCube添加两个参数dataAuditSwitch和cmtSwitch
7
+ * DeepQL允许使用`__bk__` 作为查询字段
8
+ * nacos支持账号密码验证
9
+
10
+ ## [1.1.78] - 2025-12-11
11
+
12
+ ### 更新
13
+
14
+ * api base实现方式改进
15
+ * 修复deepmodel无法insert必填多选链接的bug
16
+
1
17
  ## [1.1.77] - 2025-12-05
2
18
 
3
19
  ### 新增
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deepfos
3
- Version: 1.1.77
3
+ Version: 1.1.79
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-12-05T02:41:19+0000",
11
+ "date": "2026-01-13T06:00:21+0000",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "bd3d3dac6c3b6e4d9a695174c9064820da0912b6",
15
- "version": "1.1.77"
14
+ "full-revisionid": "d049dc802ae4862dbe78beae839ba023357d5e14",
15
+ "version": "1.1.79"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -1,7 +1,6 @@
1
1
  import enum
2
2
  import json
3
3
  import re
4
- import weakref
5
4
  from importlib import import_module
6
5
  from shlex import quote
7
6
  from typing import (
@@ -366,7 +365,8 @@ class Route:
366
365
 
367
366
  # ---------------------------------------------------------------------
368
367
  # get request info
369
- req = RequestInfo(url=concat_url(ins.base_url, endpoint), method=method)
368
+ base_url = await ins.get_base_url()
369
+ req = RequestInfo(url=concat_url(base_url, endpoint), method=method)
370
370
  req.update_default(func(ins, *args, **kwargs))
371
371
  url, body, ext_header = req.url, req.body, req.header
372
372
  raw_result = model is None
@@ -533,6 +533,7 @@ post = DummyDeco(method='post')
533
533
 
534
534
  class APIBase:
535
535
  endpoint = '/'
536
+ server_name: str = None
536
537
 
537
538
  def __init__(
538
539
  self,
@@ -553,14 +554,27 @@ class APIBase:
553
554
  else:
554
555
  self.header = header
555
556
 
556
- if mat := RE_SYS_SERVER_PARSER.match(prefix):
557
- self.base_url = concat_url(OPTION.server.base, mat.group(1), self.endpoint)
558
- else:
559
- self.base_url = concat_url(prefix, self.endpoint)
557
+ self.prefix = prefix
560
558
  self.header.update({
561
559
  "Content-Type": "application/json;charset=UTF8",
562
560
  "Connection": "close",
563
561
  })
562
+ self.base_url = None
563
+
564
+ async def get_base_url(self):
565
+ if self.base_url is None:
566
+ if (
567
+ OPTION.discovery.enabled
568
+ and OPTION.discovery.take_over
569
+ and self.server_name is not None
570
+ ):
571
+ discovery = ServiceDiscovery.instantiate()
572
+ self.base_url = await discovery.get_url(self.server_name)
573
+ elif mat := RE_SYS_SERVER_PARSER.match(self.prefix):
574
+ self.base_url = concat_url(OPTION.server.base, mat.group(1))
575
+ else:
576
+ self.base_url = self.prefix
577
+ return self.base_url
564
578
 
565
579
 
566
580
  class APIMeta(type):
@@ -596,9 +610,11 @@ class SyncAPIBase(APIBase, metaclass=APIMeta):
596
610
 
597
611
  # noinspection PyUnresolvedReferences
598
612
  class _DynamicAPIMixin:
613
+ module_id: str
599
614
  server_cache = TTLCache(maxsize=128, ttl=3600)
600
615
  module_type: str = UNSET
601
- server_known = False
616
+ server_name: str = None
617
+ base_url: str = None
602
618
  version = None
603
619
 
604
620
  def get_module_id(self, version: Union[float, str], module_id: str):
@@ -619,16 +635,30 @@ class _DynamicAPIMixin:
619
635
  self.server_cache[self.module_id] = server_name
620
636
  return server_name
621
637
 
622
- def get_server_name(self):
623
- return NotImplemented
624
-
625
- # noinspection PyAttributeOutsideInit
626
- def set_url(self, server_name):
627
- self.base_url = concat_url(OPTION.server.base, server_name, self.base_url)
628
- self.server_known = True
638
+ async def get_server_name(self):
639
+ if self.server_name is None:
640
+ if self.module_id in self.server_cache:
641
+ self.server_name = self.server_cache[self.module_id]
642
+ else:
643
+ from .space import SpaceAPI
644
+ api = SpaceAPI(self.header, sync=False)
645
+ server_meta = await api.module.detail(self.module_id) # noqa
646
+ self.server_name = self._add_to_memo(server_meta)
647
+ return self.server_name
648
+
649
+ async def get_base_url(self):
650
+ if self.base_url is None:
651
+ server_name = await self.get_server_name()
652
+ if OPTION.discovery.enabled: # pragma: no cover
653
+ discovery = ServiceDiscovery.instantiate()
654
+ base_url = await discovery.get_url(server_name)
655
+ self.base_url = concat_url(base_url)
656
+ else:
657
+ self.base_url = concat_url(OPTION.server.base, server_name)
658
+ return self.base_url
629
659
 
630
660
 
631
- class DynamicAPIBase(SyncAPIBase, _DynamicAPIMixin):
661
+ class DynamicAPIBase(_DynamicAPIMixin, SyncAPIBase):
632
662
  def __init__(
633
663
  self,
634
664
  version: Union[float, str] = None,
@@ -637,33 +667,16 @@ class DynamicAPIBase(SyncAPIBase, _DynamicAPIMixin):
637
667
  lazy: bool = False
638
668
  ):
639
669
  super().__init__(header)
640
- self.module_id = module_id = self.get_module_id(version, module_id)
641
- # lazy = True means called from element/base, will be set url in ElementBase
642
- if module_id is not None and not lazy:
643
- if module_id in self.server_cache:
644
- logger.debug(f'Find server name for module: {module_id} from cache.')
645
- server_name = self.server_cache[module_id]
646
- else:
647
- server_name = self.get_server_name()
648
- self.set_url(server_name)
649
-
650
- def get_server_name(self):
651
- from .space import SpaceAPI
652
- api = SpaceAPI(self.header, sync=True)
653
- server_meta = api.module.detail(self.module_id)
654
- return self._add_to_memo(server_meta)
655
-
656
- def set_url(self, server_name):
657
- if OPTION.discovery.enabled: # pragma: no cover
658
- discovery = ServiceDiscovery.instantiate()
659
- base_url = discovery.sync_get_url(server_name)
660
- self.base_url = concat_url(base_url, self.endpoint)
661
- self.server_known = True
662
- else:
663
- super().set_url(server_name)
670
+ self.module_id = self.get_module_id(version, module_id)
671
+
672
+ def set_server_name(self, server_name):
673
+ self.server_name = server_name
664
674
 
675
+ # backward compatibility
676
+ set_url = set_server_name
665
677
 
666
- class ADynamicAPIBase(AsyncAPIBase, _DynamicAPIMixin):
678
+
679
+ class ADynamicAPIBase(_DynamicAPIMixin, AsyncAPIBase):
667
680
  def __init__(
668
681
  self,
669
682
  version: Union[float, str] = None,
@@ -678,32 +691,14 @@ class ADynamicAPIBase(AsyncAPIBase, _DynamicAPIMixin):
678
691
  def __await__(self):
679
692
  return self.init().__await__()
680
693
 
681
- async def get_server_name(self):
682
- from .space import SpaceAPI
683
- api = SpaceAPI(self.header, sync=False)
684
- server_meta = await api.module.detail(self.module_id) # noqa
685
- return self._add_to_memo(server_meta)
686
-
687
694
  async def init(self):
688
- if self.module_id is None:
689
- return self
690
- # lazy = True means called from element/base, will be set url in ElementBase
691
- if not self.lazy:
692
- if self.module_id in self.server_cache:
693
- server_name = self.server_cache[self.module_id]
694
- else:
695
- server_name = await self.get_server_name()
696
- await self.set_url(server_name)
697
695
  return self
698
696
 
699
- async def set_url(self, server_name):
700
- if OPTION.discovery.enabled: # pragma: no cover
701
- discovery = ServiceDiscovery.instantiate()
702
- base_url = await discovery.get_url(server_name)
703
- self.base_url = concat_url(base_url, self.endpoint)
704
- self.server_known = True
705
- else:
706
- super().set_url(server_name)
697
+ async def set_server_name(self, server_name):
698
+ self.server_name = server_name
699
+
700
+ # backward compatibility
701
+ set_url = set_server_name
707
702
 
708
703
 
709
704
  class RootAPI:
@@ -860,17 +855,7 @@ class RootAPI:
860
855
 
861
856
  """
862
857
  clz = cls.resolve_cls(sync, SyncAPIBase, AsyncAPIBase)
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)
858
+ ins = clz(header=header, prefix=cls.prefix())
874
859
  ins.sync = sync
875
860
  ins.multi_version = cls.multi_version
876
861
  ins.default_version = cls.default_version
@@ -892,17 +877,19 @@ class ChildAPI(RootAPI):
892
877
  def __new__(cls, root: RootAPI):
893
878
  clz = cls.resolve_cls(
894
879
  root.sync, (SyncAPIBase, _ChildAPI), (AsyncAPIBase, _ChildAPI),
895
- extra={'root': cls.root}
880
+ extra={'get_base_url': cls.get_base_url}
896
881
  )
897
- ins = clz(header=root.header, prefix=root.base_url)
882
+ ins = clz(header=root.header, prefix=root.prefix)
898
883
  if root.url_need_format:
899
- ins.base_url = ins.base_url.format(**root.header)
900
- ins.__root = weakref.ref(root)
884
+ ins.endpoint = ins.endpoint.format(**root.header)
885
+ ins.root = root
901
886
  return ins
902
887
 
903
- @property
904
- def root(self):
905
- return self.__root()
888
+ async def get_base_url(self):
889
+ if self.base_url is None:
890
+ base_url = await self.root.get_base_url()
891
+ self.base_url = concat_url(base_url, self.endpoint)
892
+ return self.base_url
906
893
 
907
894
 
908
895
  class DynamicRootAPI(RootAPI):
@@ -122,6 +122,10 @@ class CopyCalculateDTO(BaseModel):
122
122
  fixMembers: Optional[str] = None
123
123
  #: formula表达式
124
124
  formula: Optional[str] = None
125
+ #: 是否记录数据审计
126
+ dataAuditSwitch: Optional[bool] = None
127
+ #: 是否拷贝批注
128
+ cmtSwitch: Optional[bool] = None
125
129
 
126
130
 
127
131
  class CubeDataLogForm(BaseModel):
@@ -1249,7 +1249,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1249
1249
  lambda f: f.name,
1250
1250
  filter(lambda f: f.required, structure.fields.values())
1251
1251
  ))
1252
- if missing_fields := (required_fields - set(data.columns)):
1252
+ if missing_fields := (required_fields - set(data.columns).union(relation)):
1253
1253
  raise RequiredFieldUnfilled(f'缺少必填字段: {missing_fields}')
1254
1254
 
1255
1255
  if not relation:
@@ -1449,9 +1449,9 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1449
1449
  raise ExternalObjectReadOnly('外部对象只可读')
1450
1450
 
1451
1451
  structure = ObjectStructure(name=obj.name, structure=obj.fields.values())
1452
+ relation = relation or {}
1452
1453
  self._valid_data(data, object_name, relation, structure, check_required=insert)
1453
1454
 
1454
- relation = relation or {}
1455
1455
  bkey = await self._get_bkey(obj)
1456
1456
  if bkey not in data.columns:
1457
1457
  raise RequiredFieldUnfilled(f'缺少业务主键[{bkey}]')
@@ -1393,13 +1393,21 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
1393
1393
  processMap=process_map,
1394
1394
  status=status))
1395
1395
 
1396
- async def copy_calculate(self, formula: str, fix_members: str):
1396
+ async def copy_calculate(
1397
+ self,
1398
+ formula: str,
1399
+ fix_members: str,
1400
+ data_audit_switch: Optional[bool] = None,
1401
+ cmt_switch: Optional[bool] = None,
1402
+ ):
1397
1403
  """
1398
1404
  cube copy计算接口
1399
1405
 
1400
1406
  Args:
1401
1407
  formula: 维度成员来源和目的的表达式
1402
1408
  fix_members: 维度成员的筛选表达式
1409
+ data_audit_switch: 是否记录数据审计
1410
+ cmt_switch: 是否拷贝批注
1403
1411
 
1404
1412
  Returns:
1405
1413
  更新结果
@@ -1422,7 +1430,9 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
1422
1430
  cubePath=self._path,
1423
1431
  formula=formula,
1424
1432
  fixMembers=fix_members,
1425
- entryObject="python"
1433
+ entryObject="python",
1434
+ dataAuditSwitch=data_audit_switch,
1435
+ cmtSwitch=cmt_switch,
1426
1436
  )
1427
1437
  )
1428
1438
 
@@ -1861,7 +1871,13 @@ class FinancialCube(AsyncFinancialCube, metaclass=SyncMeta):
1861
1871
  ):
1862
1872
  ...
1863
1873
 
1864
- def copy_calculate(self, formula: str, fix_members: str):
1874
+ def copy_calculate(
1875
+ self,
1876
+ formula: str,
1877
+ fix_members: str,
1878
+ data_audit_switch: Optional[bool] = None,
1879
+ cmt_switch: Optional[bool] = None,
1880
+ ):
1865
1881
  ...
1866
1882
 
1867
1883
  def mdx_execution(
@@ -652,6 +652,8 @@ class EdgeQLLexer(Lexer):
652
652
  Rule(token='BADIDENT',
653
653
  next_state=STATE_KEEP,
654
654
  regexp=r'''
655
+ (?!__bk__\b)
656
+ (?!`__bk__`)
655
657
  __[^\W\d]\w*__
656
658
  |
657
659
  `__([^`]|``)*__`(?!`)
@@ -16,7 +16,7 @@ from deepfos.lib.discovery import ServiceDiscovery
16
16
  from deepfos import OPTION
17
17
 
18
18
 
19
- class K8s(ServiceDiscovery):
19
+ class K8sCli(ServiceDiscovery):
20
20
  def __init__(self):
21
21
  super().__init__()
22
22
  self._instance_lock: Dict[str, asyncio.Lock] = defaultdict(asyncio.Lock)
@@ -34,6 +34,9 @@ class K8s(ServiceDiscovery):
34
34
 
35
35
  @cached_property
36
36
  def _api(self):
37
+ c = client.Configuration.get_default_copy()
38
+ c.verify_ssl = False
39
+ client.Configuration.set_default(c)
37
40
  return client.CoreV1Api()
38
41
 
39
42
  async def on_interval(self):
@@ -99,3 +102,6 @@ class K8s(ServiceDiscovery):
99
102
  logger.debug(f"{server_name} has no active endpoint, clear invalid...")
100
103
  for item in list(cache):
101
104
  cache.delete(item)
105
+
106
+
107
+ K8s = K8sCli()
@@ -2,15 +2,16 @@ import asyncio
2
2
  import functools
3
3
  import json
4
4
  from collections import defaultdict
5
- from typing import TypedDict, Any, Tuple, Type, Dict
5
+ from typing import TypedDict, Any, Tuple, Type, Dict, Optional
6
6
 
7
7
  from loguru import logger
8
+ from aiohttp import ClientError
8
9
 
9
10
  from deepfos import OPTION
10
11
  from deepfos.exceptions import APIResponseError
11
- from deepfos.lib.discovery import ServiceDiscovery
12
+ from deepfos.lib.discovery import ServiceDiscovery, RankedCache
12
13
  from deepfos.lib.httpcli import AioHttpCli
13
- from deepfos.lib.utils import concat_url
14
+ from deepfos.lib.utils import concat_url, retry
14
15
 
15
16
  __all__ = ['Nacos']
16
17
 
@@ -78,20 +79,46 @@ class Route: # pragma: no cover
78
79
  is_get = method == 'GET'
79
80
 
80
81
  @functools.wraps(func)
81
- async def call(*args, **kwargs):
82
- ins = args[0]
83
- url = concat_url(ins.base_url, endpoint)
84
- body = func(ins, *args[1::], **kwargs)
85
- logger.opt(lazy=True).debug(
86
- f"Sending request: {method} {url} "
87
- f"body: {repr(body)}"
88
- )
82
+ async def call(ins: "NacosAPI", *args, **kwargs):
83
+ body = func(ins, *args, **kwargs)
89
84
  req_args = {
90
85
  'headers': ins.header,
91
86
  'params' if is_get else 'data': body
92
87
  }
93
- response = await request(url, **req_args)
94
- text = await response.text()
88
+ url_cache = ins.base_urls
89
+ for i, base_url in zip(reversed(range(len(url_cache))), url_cache.sort()):
90
+ is_last_url = i == 0
91
+ try:
92
+ url = concat_url(base_url, endpoint)
93
+ logger.opt(lazy=True).debug(
94
+ f"Sending request: {method} {url} "
95
+ f"body: {repr(body)}"
96
+ )
97
+ response = await request(url, **req_args)
98
+ if (
99
+ response.status == 403
100
+ and func.__qualname__ != 'NacosAPI.login'
101
+ ):
102
+ # retry if token expired
103
+ if await ins.maybe_login(schedule_renewal=False):
104
+ body.update(func(ins, *args, **kwargs))
105
+ response = await request(url, **req_args)
106
+
107
+ if not (200 <= response.status < 300):
108
+ raise APIResponseError(
109
+ f"Call API: {endpoint} failed with http status: {response.status}"
110
+ )
111
+ url_cache.reward(base_url)
112
+ break
113
+ except ClientError as e:
114
+ url_cache.punish(base_url)
115
+ if is_last_url:
116
+ logger.warning(f"Request of all urls failed.")
117
+ raise
118
+ else:
119
+ logger.warning(f"Request failed with {e}, try next url...")
120
+
121
+ text = await response.text() # noqa
95
122
  if response_checker is not None:
96
123
  ok, result = response_checker.validate(text, endpoint)
97
124
  if not ok:
@@ -109,28 +136,89 @@ class Route: # pragma: no cover
109
136
  return execute
110
137
 
111
138
 
139
+ def auth(func):
140
+ @functools.wraps(func)
141
+ def wrapper(self, *args, **kwargs):
142
+ resp = func(self, *args, **kwargs)
143
+ if token := getattr(self, '_token', None):
144
+ resp['accessToken'] = token
145
+ return resp
146
+
147
+ return wrapper
148
+
149
+
112
150
  get = Route(method='get')
151
+ post = Route(method='post')
113
152
 
114
153
 
115
154
  class NacosAPI:
116
155
  def __init__(self): # noqa
117
156
  nacos_server: str = OPTION.nacos.server.lower()
118
- if nacos_server.rstrip('/').endswith('nacos'):
119
- base_url = nacos_server
120
- else:
121
- base_url = concat_url(nacos_server, 'nacos')
122
-
123
- self.base_url = concat_url(base_url, 'v1')
157
+ self._base_urls = self._resolve_base_urls(nacos_server)
124
158
  self.header = {"Content-Type": "application/x-www-form-urlencoded"}
159
+ self._token = None
160
+ self._user = OPTION.nacos.user
161
+ self._password = OPTION.nacos.password
162
+
163
+ @staticmethod
164
+ def _resolve_base_urls(url: str) -> RankedCache:
165
+ urls = RankedCache()
166
+ for nacos_server in url.split(','):
167
+ if nacos_server.rstrip('/').endswith('nacos'):
168
+ base_url = nacos_server
169
+ else:
170
+ base_url = concat_url(nacos_server, 'nacos')
171
+ urls.add(concat_url(base_url, 'v1'))
172
+ return urls
173
+
174
+ @property
175
+ def base_urls(self) -> RankedCache:
176
+ return self._base_urls
177
+
178
+ async def maybe_login(
179
+ self,
180
+ schedule_renewal: bool = True,
181
+ delay: Optional[float] = None,
182
+ ) -> bool:
183
+ if self._user is not None and self._password is not None:
184
+ if delay:
185
+ await asyncio.sleep(delay)
186
+
187
+ resp = await retry(self.login, wait=1)(self._user, self._password)
188
+ self._token = resp['accessToken']
189
+
190
+ ttl = resp['tokenTtl']
191
+ if schedule_renewal:
192
+ _ = asyncio.create_task(self.maybe_login(
193
+ schedule_renewal=True,
194
+ delay=min((ttl * 2 / 3), ttl - 5)
195
+ ))
196
+ return True
197
+ return False
198
+
199
+ @post('auth/login', JsonResponse)
200
+ def login(self, user: str, password: str):
201
+ return {
202
+ "username": user,
203
+ "password": password
204
+ }
125
205
 
126
206
  @get('ns/service/list', JsonResponse)
127
- def list_service(self): # pragma: no cover
207
+ @auth
208
+ def list_service(
209
+ self,
210
+ group: str = 'DEFAULT_GROUP',
211
+ namespace: str = 'public',
212
+ ):
128
213
  return {
129
214
  'pageNo': 1,
130
215
  'pageSize': 1000000,
216
+ 'namespaceId': namespace,
217
+ 'groupName': group,
131
218
  }
132
219
 
133
220
  @get('ns/instance/list', JsonResponse)
221
+ @auth
134
222
  def list_instance(
135
223
  self,
136
224
  service_name: str,
@@ -163,7 +251,7 @@ class NacosCli(ServiceDiscovery):
163
251
  self._instance_lock.clear()
164
252
 
165
253
  async def on_startup(self):
166
- pass
254
+ await self._api.maybe_login()
167
255
 
168
256
  async def on_interval(self):
169
257
  await self._update_cache()
@@ -186,7 +274,10 @@ class NacosCli(ServiceDiscovery):
186
274
  await self.update_instance_for_service(server_name)
187
275
 
188
276
  async def update_services(self):
189
- new_services = frozenset((await self._api.list_service())['doms'])
277
+ new_services = frozenset((await self._api.list_service(
278
+ group=self._group,
279
+ namespace=self._ns,
280
+ ))['doms'])
190
281
  cur_services = frozenset(self.server_cache.keys())
191
282
 
192
283
  if added := new_services - cur_services:
@@ -510,6 +510,8 @@ class _Nacos(_Category):
510
510
  cluster = _Option('DEFAULT', val_type=str)
511
511
  namespace = _Option('public', val_type=str)
512
512
  group = _Option('DEFAULT_GROUP', val_type=str)
513
+ user = _Option(None, val_type=str)
514
+ password = _Option(None, val_type=str)
513
515
 
514
516
  def __get__(self, instance, owner) -> '_Nacos':
515
517
  """defined to help ide"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deepfos
3
- Version: 1.1.77
3
+ Version: 1.1.79
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
@@ -54,5 +54,5 @@ def resolve_extensions():
54
54
  setup(
55
55
  version=versioneer.get_version(),
56
56
  cmdclass=versioneer.get_cmdclass(),
57
- ext_modules=resolve_extensions()
57
+ ext_modules=[]
58
58
  )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes