deepfos 1.1.55__tar.gz → 1.1.56__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 (191) hide show
  1. {deepfos-1.1.55 → deepfos-1.1.56}/CHANGELOG.md +7 -0
  2. {deepfos-1.1.55 → deepfos-1.1.56}/PKG-INFO +1 -1
  3. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/_version.py +3 -3
  4. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/deepmodel.py +8 -2
  5. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/finmodel.py +123 -37
  6. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/sysutils.py +12 -6
  7. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos.egg-info/PKG-INFO +1 -1
  8. {deepfos-1.1.55 → deepfos-1.1.56}/.gitattributes +0 -0
  9. {deepfos-1.1.55 → deepfos-1.1.56}/.gitee/ISSUE_GUIDELINES.md +0 -0
  10. {deepfos-1.1.55 → deepfos-1.1.56}/.gitee/ISSUE_TEMPLATE.md +0 -0
  11. {deepfos-1.1.55 → deepfos-1.1.56}/.gitignore +0 -0
  12. {deepfos-1.1.55 → deepfos-1.1.56}/MANIFEST.in +0 -0
  13. {deepfos-1.1.55 → deepfos-1.1.56}/README.md +0 -0
  14. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/__init__.py +0 -0
  15. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/algo/__init__.py +0 -0
  16. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/algo/graph.py +0 -0
  17. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/V1_1/__init__.py +0 -0
  18. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/V1_1/business_model.py +0 -0
  19. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/V1_1/dimension.py +0 -0
  20. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/V1_1/models/__init__.py +0 -0
  21. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/V1_1/models/business_model.py +0 -0
  22. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/V1_1/models/dimension.py +0 -0
  23. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/V1_2/__init__.py +0 -0
  24. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/V1_2/dimension.py +0 -0
  25. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/V1_2/models/__init__.py +0 -0
  26. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/V1_2/models/dimension.py +0 -0
  27. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/__init__.py +0 -0
  28. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/account.py +0 -0
  29. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/accounting_engines.py +0 -0
  30. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/app.py +0 -0
  31. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/approval_process.py +0 -0
  32. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/base.py +0 -0
  33. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/business_model.py +0 -0
  34. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/consolidation.py +0 -0
  35. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/consolidation_process.py +0 -0
  36. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/datatable.py +0 -0
  37. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/deep_pipeline.py +0 -0
  38. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/deepconnector.py +0 -0
  39. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/deepfos_task.py +0 -0
  40. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/deepmodel.py +0 -0
  41. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/dimension.py +0 -0
  42. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/financial_model.py +0 -0
  43. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/journal_model.py +0 -0
  44. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/journal_template.py +0 -0
  45. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/memory_financial_model.py +0 -0
  46. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/__init__.py +0 -0
  47. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/account.py +0 -0
  48. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/accounting_engines.py +0 -0
  49. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/app.py +0 -0
  50. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/approval_process.py +0 -0
  51. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/base.py +0 -0
  52. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/business_model.py +0 -0
  53. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/consolidation.py +0 -0
  54. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/consolidation_process.py +0 -0
  55. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/datatable_mysql.py +0 -0
  56. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/deep_pipeline.py +0 -0
  57. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/deepconnector.py +0 -0
  58. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/deepfos_task.py +0 -0
  59. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/deepmodel.py +0 -0
  60. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/dimension.py +0 -0
  61. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/financial_model.py +0 -0
  62. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/journal_model.py +0 -0
  63. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/journal_template.py +0 -0
  64. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/memory_financial_model.py +0 -0
  65. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/platform.py +0 -0
  66. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/python.py +0 -0
  67. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/reconciliation_engine.py +0 -0
  68. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/reconciliation_report.py +0 -0
  69. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/role_strategy.py +0 -0
  70. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/smartlist.py +0 -0
  71. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/space.py +0 -0
  72. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/system.py +0 -0
  73. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/variable.py +0 -0
  74. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/models/workflow.py +0 -0
  75. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/platform.py +0 -0
  76. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/python.py +0 -0
  77. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/reconciliation_engine.py +0 -0
  78. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/reconciliation_report.py +0 -0
  79. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/role_strategy.py +0 -0
  80. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/smartlist.py +0 -0
  81. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/space.py +0 -0
  82. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/system.py +0 -0
  83. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/variable.py +0 -0
  84. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/api/workflow.py +0 -0
  85. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/boost/__init__.py +0 -0
  86. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/boost/jstream.c +0 -0
  87. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/boost/jstream.pyx +0 -0
  88. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/boost/pandas.c +0 -0
  89. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/boost/pandas.pyx +0 -0
  90. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/boost/py_jstream.py +0 -0
  91. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/boost/py_pandas.py +0 -0
  92. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/cache.py +0 -0
  93. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/config.py +0 -0
  94. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/__init__.py +0 -0
  95. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/cube/__init__.py +0 -0
  96. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/cube/_base.py +0 -0
  97. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/cube/constants.py +0 -0
  98. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/cube/cube.py +0 -0
  99. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/cube/formula.py +0 -0
  100. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/cube/syscube.py +0 -0
  101. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/cube/typing.py +0 -0
  102. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/cube/utils.py +0 -0
  103. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/dimension/__init__.py +0 -0
  104. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/dimension/_base.py +0 -0
  105. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/dimension/dimcreator.py +0 -0
  106. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/dimension/dimension.py +0 -0
  107. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/dimension/dimexpr.py +0 -0
  108. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/dimension/dimmember.py +0 -0
  109. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/dimension/eledimension.py +0 -0
  110. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/dimension/filters.py +0 -0
  111. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/dimension/sysdimension.py +0 -0
  112. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/logictable/__init__.py +0 -0
  113. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/logictable/_cache.py +0 -0
  114. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/logictable/_operator.py +0 -0
  115. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/logictable/nodemixin.py +0 -0
  116. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/logictable/sqlcondition.py +0 -0
  117. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/core/logictable/tablemodel.py +0 -0
  118. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/__init__.py +0 -0
  119. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/cipher.py +0 -0
  120. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/clickhouse.py +0 -0
  121. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/connector.py +0 -0
  122. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/daclickhouse.py +0 -0
  123. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/dameng.py +0 -0
  124. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/damysql.py +0 -0
  125. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/dbkits.py +0 -0
  126. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/deepengine.py +0 -0
  127. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/deepmodel.py +0 -0
  128. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/deepmodel_kingbase.py +0 -0
  129. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/edb.py +0 -0
  130. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/gauss.py +0 -0
  131. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/kingbase.py +0 -0
  132. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/mysql.py +0 -0
  133. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/oracle.py +0 -0
  134. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/postgresql.py +0 -0
  135. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/sqlserver.py +0 -0
  136. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/db/utils.py +0 -0
  137. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/__init__.py +0 -0
  138. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/accounting.py +0 -0
  139. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/apvlprocess.py +0 -0
  140. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/base.py +0 -0
  141. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/bizmodel.py +0 -0
  142. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/datatable.py +0 -0
  143. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/deep_pipeline.py +0 -0
  144. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/deepconnector.py +0 -0
  145. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/dimension.py +0 -0
  146. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/fact_table.py +0 -0
  147. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/journal.py +0 -0
  148. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/journal_template.py +0 -0
  149. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/pyscript.py +0 -0
  150. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/reconciliation.py +0 -0
  151. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/rolestrategy.py +0 -0
  152. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/smartlist.py +0 -0
  153. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/variable.py +0 -0
  154. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/element/workflow.py +0 -0
  155. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/exceptions/__init__.py +0 -0
  156. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/exceptions/hook.py +0 -0
  157. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lazy.py +0 -0
  158. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/__init__.py +0 -0
  159. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/_javaobj.py +0 -0
  160. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/asynchronous.py +0 -0
  161. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/concurrency.py +0 -0
  162. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/constant.py +0 -0
  163. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/decorator.py +0 -0
  164. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/deepchart.py +0 -0
  165. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/deepux.py +0 -0
  166. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/discovery.py +0 -0
  167. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/edb_lexer.py +0 -0
  168. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/eureka.py +0 -0
  169. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/filterparser.py +0 -0
  170. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/httpcli.py +0 -0
  171. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/jsonstreamer.py +0 -0
  172. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/msg.py +0 -0
  173. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/nacos.py +0 -0
  174. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/patch.py +0 -0
  175. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/redis.py +0 -0
  176. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/serutils.py +0 -0
  177. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/stopwatch.py +0 -0
  178. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/subtask.py +0 -0
  179. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/lib/utils.py +0 -0
  180. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/local.py +0 -0
  181. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/options.py +0 -0
  182. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos/translation.py +0 -0
  183. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos.egg-info/SOURCES.txt +0 -0
  184. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos.egg-info/dependency_links.txt +0 -0
  185. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos.egg-info/not-zip-safe +0 -0
  186. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos.egg-info/requires.txt +0 -0
  187. {deepfos-1.1.55 → deepfos-1.1.56}/deepfos.egg-info/top_level.txt +0 -0
  188. {deepfos-1.1.55 → deepfos-1.1.56}/requirements.txt +0 -0
  189. {deepfos-1.1.55 → deepfos-1.1.56}/setup.cfg +0 -0
  190. {deepfos-1.1.55 → deepfos-1.1.56}/setup.py +0 -0
  191. {deepfos-1.1.55 → deepfos-1.1.56}/versioneer.py +0 -0
@@ -1,3 +1,10 @@
1
+ ## [1.1.56] - 2025-04-27
2
+
3
+ ### 新增
4
+
5
+ * 财务模型支持complement_save_unpivot
6
+
7
+
1
8
  ## [1.1.55] - 2025-04-25
2
9
 
3
10
  ### 新增
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deepfos
3
- Version: 1.1.55
3
+ Version: 1.1.56
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-04-27T01:54:31+0000",
11
+ "date": "2025-04-28T08:53:07+0000",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "8a98c948a65577c31df7cff7c2a512e8d71de104",
15
- "version": "1.1.55"
14
+ "full-revisionid": "65654605edcd2831ed325b40b62f71c933313017",
15
+ "version": "1.1.56"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -774,8 +774,12 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
774
774
  """DeepModel元素
775
775
 
776
776
  Args:
777
- direct_access: 是否使用直连模式
777
+ direct_access: 是否使用直连模式,默认为True
778
+ 会结合OPTION.edgedb.dsn是否有值决定是否使用直连模式,如无值,则仍为非直连模式
779
+ 直连模式下,会使用edgedb-python库直连edgedb server,
780
+ 否则会使用DeepModel组件API进行操作
778
781
  pg_dsn: PG连接信息
782
+
779
783
  """
780
784
  __mangle_docs__ = False
781
785
 
@@ -783,7 +787,9 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
783
787
  self._txn_ = ContextVar('QLTXN')
784
788
  self.appmodule = f"app{OPTION.api.header['app']}"
785
789
  self.spacemodule = f"space{OPTION.api.header['space']}"
786
- self.direct_access = direct_access
790
+ self.direct_access = direct_access and bool(OPTION.edgedb.dsn)
791
+ if not self.direct_access:
792
+ logger.debug('当前DeepModel为非直连模式')
787
793
  self.alias = AliasGenerator()
788
794
  self.pg_dsn = pg_dsn
789
795
  self._globals = {}
@@ -487,10 +487,10 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
487
487
  pov: Optional[Union[str, Dict[str, str]]] = None,
488
488
  data_column: str = DFLT_DATA_COLUMN,
489
489
  comment_column: str = DFLT_COMMENT_COLUMN,
490
- ) -> pd.DataFrame:
490
+ ) -> Tuple[pd.DataFrame, Dict[str, str]]:
491
491
  if data.empty:
492
492
  logger.info("Will not save to cube because dataframe is empty.")
493
- return pd.DataFrame()
493
+ return pd.DataFrame(), {}
494
494
 
495
495
  if data_column not in data.columns:
496
496
  raise ValueError(f"Missing data column: {data_column}.")
@@ -537,7 +537,7 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
537
537
  data = pd.concat([data, cmt_data])
538
538
  required_cols.add(COLUMN_USAGE_FIELD)
539
539
 
540
- return data[list(required_cols)]
540
+ return data[list(required_cols)], pov
541
541
 
542
542
  async def save(
543
543
  self,
@@ -580,11 +580,34 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
580
580
  :meth:`save_unpivot`
581
581
 
582
582
  """
583
- data = self._build_dataframe_for_save(data, pov, data_column, comment_column)
583
+ data, pov = self._build_dataframe_for_save(data, pov, data_column, comment_column)
584
+ if data.empty:
585
+ return
586
+
584
587
  return await self._save_impl(
585
588
  data, pov, need_check, data_audit, chunksize, callback, auth_mode
586
589
  )
587
590
 
591
+ def _complement(
592
+ self,
593
+ data: pd.DataFrame,
594
+ expression: str,
595
+ default_hierarchy: str = 'Base',
596
+ pov: Dict[str, str] = None,
597
+ ):
598
+ if isinstance(expression, dict):
599
+ expression = dict_to_expr(expression)
600
+ expr, pov = self._split_expr(expression, pov or {}, default_hierarchy)
601
+ full_expr = {**expr_to_dict(expr), **pov}
602
+ folders = {col: dim.folderId for col, dim in self.dimensions.items()}
603
+ data_comp = complete_cartesian_product(
604
+ full_expr,
605
+ data,
606
+ folder_ids=folders,
607
+ col_dim_map=self.col_dim_map,
608
+ )
609
+ return data_comp
610
+
588
611
  async def complement_save(
589
612
  self,
590
613
  data: pd.DataFrame,
@@ -619,22 +642,42 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
619
642
  **kwargs: 其他可传给:meth:`save`的参数
620
643
 
621
644
  """
622
- data = self._build_dataframe_for_save(data, pov, data_column, comment_column)
645
+ data, pov = self._build_dataframe_for_save(data, pov, data_column, comment_column)
623
646
  if data.empty:
624
647
  return
625
648
 
626
- if isinstance(expression, dict):
627
- expression = dict_to_expr(expression)
628
- expr, pov = self._split_expr(expression, pov or {}, default_hierarchy)
629
- full_expr = {**expr_to_dict(expr), **pov}
649
+ data_comp = self._complement(data, expression, default_hierarchy, pov)
650
+ return await self._save_impl(data_comp, pov, **kwargs)
630
651
 
631
- folders = {col: dim.folderId for col, dim in self.dimensions.items()}
632
- data_comp = complete_cartesian_product(
633
- full_expr,
634
- data,
635
- folder_ids=folders,
652
+ def _build_dataframe_for_save_unpivot(
653
+ self,
654
+ data: pd.DataFrame,
655
+ unpivot_dim: str,
656
+ pov: Optional[Union[str, Dict[str, str]]] = None,
657
+ save_nan: bool = False,
658
+ ) -> Tuple[pd.DataFrame, Dict[str, str]]:
659
+ if data.empty:
660
+ logger.info("Will not save to cube because dataframe is empty.")
661
+ return pd.DataFrame(), {}
662
+
663
+ data = data.rename(columns=self._maybe_get_column_from_dim)
664
+ dim = self._get_column_from_dim(unpivot_dim)
665
+ pov = self._resolve_pov_as_dict(pov)
666
+ data_cols = set(data.columns)
667
+ unpivot_cols = data_cols.difference(pov.keys(), self.dim_col_map.values())
668
+ if self._meta.autoCalculation:
669
+ unpivot_cols.discard(VIEW)
670
+ id_cols = data_cols - unpivot_cols
671
+ data = data.melt(
672
+ id_vars=id_cols, value_vars=unpivot_cols,
673
+ var_name=dim, value_name=DFLT_DATA_COLUMN
636
674
  )
637
- return await self._save_impl(data_comp, **kwargs)
675
+ if not save_nan:
676
+ data = data.dropna()
677
+ if data.empty:
678
+ logger.info("Will not save to cube because dataframe is empty.")
679
+ return pd.DataFrame(), {}
680
+ return data, pov
638
681
 
639
682
  async def save_unpivot(
640
683
  self,
@@ -682,34 +725,62 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
682
725
  | :meth:`save`
683
726
 
684
727
  """
728
+ data, pov = self._build_dataframe_for_save_unpivot(
729
+ data, unpivot_dim, pov, save_nan
730
+ )
685
731
  if data.empty:
686
- logger.info("Will not save to cube because dataframe is empty.")
687
732
  return
688
733
 
689
- data = data.rename(columns=self._maybe_get_column_from_dim)
690
- dim = self._get_column_from_dim(unpivot_dim)
691
- pov = self._resolve_pov_as_dict(pov)
692
- data_cols = set(data.columns)
693
- unpivot_cols = data_cols.difference(pov.keys(), self.dim_col_map.values())
734
+ return await self._save_impl(
735
+ data, pov, need_check, data_audit, chunksize, callback
736
+ )
694
737
 
695
- if self._meta.autoCalculation:
696
- unpivot_cols.discard(VIEW)
738
+ async def complement_save_unpivot(
739
+ self,
740
+ data: pd.DataFrame,
741
+ unpivot_dim: str,
742
+ expression: Union[str, Dict[str, Union[List[str], str]]],
743
+ default_hierarchy: str = "Base",
744
+ pov: Optional[Union[str, Dict[str, str]]] = None,
745
+ save_nan: bool = False,
746
+ **kwargs
747
+ ):
748
+ """覆盖指定维度范围并保有某个维度所有成员在列上的 ``DataFrame``
697
749
 
698
- id_cols = data_cols - unpivot_cols
699
- data = data.melt(
700
- id_vars=id_cols, value_vars=unpivot_cols,
701
- var_name=dim, value_name=DFLT_DATA_COLUMN
702
- )
750
+ 相比于:meth:`save_unpivot`,在保存前,会将`data`按照`expression`补全笛卡尔积。
751
+ 并且不在`data`范围的数据以`None`填充
703
752
 
704
- if not save_nan:
705
- data = data.dropna()
706
- if data.empty:
707
- logger.info("Will not save to cube because dataframe is empty.")
708
- return
753
+ Note:
754
+ 逻辑上等价于两次调用
709
755
 
710
- return await self._save_impl(
711
- data, pov, need_check, data_audit, chunksize, callback
756
+ .. code-block:: python
757
+
758
+ cube.delete(expression)
759
+ cube.save_unpivot(data, unpivot_dim, **kwargs)
760
+
761
+ Args:
762
+ data: 需要保存的数据
763
+ unpivot_dim: 成员在列上的维度
764
+ expression: 需要覆盖的范围(维度表达式)
765
+ default_hierarchy: 单expression中没指定对应维度时,默认取的层级函数,
766
+ 即填充为 `default_hierarchy(#root,0)`
767
+ pov: Point Of View,维度表达式或者KV键值对格式。
768
+ need_check: 是否需要java接口校验脏数据
769
+ data_audit: 是否需要记录到数据审计
770
+ chunksize: 单次调用保存接口时最大的dataframe行数。
771
+ 当data的行数超过此值时,将会分多次进行保存。
772
+ save_nan: 当把数据列成员转换到行上时,data为空的数据是否保存
773
+ callback: 是否回调
774
+
775
+ """
776
+ data, pov = self._build_dataframe_for_save_unpivot(
777
+ data, unpivot_dim, pov, save_nan
712
778
  )
779
+ if data.empty:
780
+ return
781
+
782
+ data_comp = self._complement(data, expression, default_hierarchy, pov)
783
+ return await self._save_impl(data_comp, pov, **kwargs)
713
784
 
714
785
  async def _save_impl(
715
786
  self,
@@ -722,7 +793,9 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
722
793
  auth_mode: Literal[0, 1, 2, 3] = 0,
723
794
  ):
724
795
  # replace NaN to standard None
725
- data = data.mask(data.isna(), None)
796
+ # NB: replace twice in case of infer None to nan happened in 2.x pandas
797
+ data = data.replace({None: np.nan})
798
+ data = data.replace({np.nan: None})
726
799
  # ensure view is capitalized
727
800
  if self._meta.autoCalculation:
728
801
  data = data.rename(columns=VIEW_DICT)
@@ -1381,6 +1454,7 @@ class FinancialCube(AsyncFinancialCube, metaclass=SyncMeta):
1381
1454
  'save',
1382
1455
  'complement_save',
1383
1456
  'save_unpivot',
1457
+ 'complement_save_unpivot',
1384
1458
  'delete',
1385
1459
  'delete_with_mdx',
1386
1460
  'pc_init',
@@ -1388,7 +1462,7 @@ class FinancialCube(AsyncFinancialCube, metaclass=SyncMeta):
1388
1462
  'pc_upsert',
1389
1463
  'insert_null',
1390
1464
  'copy_calculate',
1391
- 'mdx_execution'
1465
+ 'mdx_execution',
1392
1466
  )
1393
1467
 
1394
1468
  if TYPE_CHECKING: # pragma: no cover
@@ -1451,6 +1525,18 @@ class FinancialCube(AsyncFinancialCube, metaclass=SyncMeta):
1451
1525
  ):
1452
1526
  ...
1453
1527
 
1528
+ def complement_save_unpivot(
1529
+ self,
1530
+ data: pd.DataFrame,
1531
+ unpivot_dim: str,
1532
+ expression: Union[str, Dict[str, Union[List[str], str]]],
1533
+ default_hierarchy: str = "Base",
1534
+ pov: Optional[Union[str, Dict[str, str]]] = None,
1535
+ save_nan: bool = False,
1536
+ **kwargs
1537
+ ):
1538
+ ...
1539
+
1454
1540
  def delete(
1455
1541
  self,
1456
1542
  expression: Union[str, Dict[str, Union[List[str], str]]],
@@ -105,6 +105,7 @@ def complete_cartesian_product(
105
105
  df: pd.DataFrame = None,
106
106
  paths: Union[str, Dict[str, str]] = None,
107
107
  folder_ids: Union[str, Dict[str, str]] = None,
108
+ col_dim_map: Dict[str, str] = None,
108
109
  ) -> pd.DataFrame:
109
110
  """
110
111
  构造完整的维度成员笛卡尔积
@@ -115,6 +116,7 @@ def complete_cartesian_product(
115
116
  paths: fix中维度的path,如果所有维度的目录相同,传同一个path,否则传字典,key为维度名,value为path。
116
117
  如果不传,则自动寻找维度对应的path。
117
118
  folder_ids: 类似paths, 但值是folder_id
119
+ col_dim_map: data中的列名与实际维度名的映射关系,默认data中的列名与维度名相同
118
120
 
119
121
  Returns:
120
122
  维度成员笛卡尔积的DataFrame
@@ -165,29 +167,33 @@ def complete_cartesian_product(
165
167
  else:
166
168
  loc_key = "path"
167
169
  loc_getter = lambda _: None
170
+ if col_dim_map is None:
171
+ col_dim_map = {}
168
172
 
169
173
  # 遍历fix,如果fix的值为str,则认为是维度表达式,将表达式转换为成员list
170
174
  mbrs = {}
171
175
  futures = []
172
176
 
173
- for dim, exp in fix.items():
177
+ for col, exp in fix.items():
174
178
  if isinstance(exp, str):
175
179
  if "(" not in exp:
176
- mbrs[dim] = exp.split(';')
180
+ mbrs[col] = exp.split(';')
177
181
  else:
182
+ dim = col_dim_map.get(col, col)
178
183
  loc = loc_getter(dim)
179
184
  future = evloop.apply(AsyncDimension(element_name=dim, **{loc_key: loc}).query(
180
185
  expression=exp, fields=['name'], as_model=False
181
186
  ))
182
187
 
183
- futures.append((dim, future))
188
+ futures.append((col, future))
184
189
  else:
185
190
  if not isinstance(exp, list):
186
191
  raise TypeError('fix参数的value只能为维度表达式(str)或维度成员(list)')
187
- mbrs[dim] = exp
192
+ mbrs[col] = exp
188
193
 
189
- for dim, future in futures:
190
- mbrs[dim] = [item['name'] for item in future.result()]
194
+ for col, future in futures:
195
+ dim_mbrs = future.result()
196
+ mbrs[col] = [item['name'] for item in dim_mbrs]
191
197
 
192
198
  if df is None:
193
199
  df = pd.DataFrame(columns=list(fix.keys()))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deepfos
3
- Version: 1.1.55
3
+ Version: 1.1.56
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes