deepfos 1.1.66__tar.gz → 1.1.68__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.66 → deepfos-1.1.68}/CHANGELOG.md +21 -0
  2. {deepfos-1.1.66 → deepfos-1.1.68}/PKG-INFO +1 -1
  3. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/_version.py +3 -3
  4. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/deepmodel.py +192 -187
  5. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/dimension.py +2 -2
  6. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/finmodel.py +25 -6
  7. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/journal.py +19 -8
  8. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/options.py +20 -3
  9. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos.egg-info/PKG-INFO +1 -1
  10. {deepfos-1.1.66 → deepfos-1.1.68}/.gitattributes +0 -0
  11. {deepfos-1.1.66 → deepfos-1.1.68}/.gitee/ISSUE_GUIDELINES.md +0 -0
  12. {deepfos-1.1.66 → deepfos-1.1.68}/.gitee/ISSUE_TEMPLATE.md +0 -0
  13. {deepfos-1.1.66 → deepfos-1.1.68}/.gitignore +0 -0
  14. {deepfos-1.1.66 → deepfos-1.1.68}/MANIFEST.in +0 -0
  15. {deepfos-1.1.66 → deepfos-1.1.68}/README.md +0 -0
  16. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/__init__.py +0 -0
  17. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/algo/__init__.py +0 -0
  18. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/algo/graph.py +0 -0
  19. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/V1_1/__init__.py +0 -0
  20. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/V1_1/business_model.py +0 -0
  21. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/V1_1/dimension.py +0 -0
  22. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/V1_1/models/__init__.py +0 -0
  23. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/V1_1/models/business_model.py +0 -0
  24. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/V1_1/models/dimension.py +0 -0
  25. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/V1_2/__init__.py +0 -0
  26. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/V1_2/dimension.py +0 -0
  27. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/V1_2/models/__init__.py +0 -0
  28. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/V1_2/models/dimension.py +0 -0
  29. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/__init__.py +0 -0
  30. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/account.py +0 -0
  31. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/accounting_engines.py +0 -0
  32. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/app.py +0 -0
  33. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/approval_process.py +0 -0
  34. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/base.py +0 -0
  35. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/business_model.py +0 -0
  36. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/consolidation.py +0 -0
  37. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/consolidation_process.py +0 -0
  38. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/datatable.py +0 -0
  39. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/deep_pipeline.py +0 -0
  40. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/deepconnector.py +0 -0
  41. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/deepfos_task.py +0 -0
  42. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/deepmodel.py +0 -0
  43. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/dimension.py +0 -0
  44. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/financial_model.py +0 -0
  45. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/journal_model.py +0 -0
  46. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/journal_template.py +0 -0
  47. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/memory_financial_model.py +0 -0
  48. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/__init__.py +0 -0
  49. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/account.py +0 -0
  50. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/accounting_engines.py +0 -0
  51. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/app.py +0 -0
  52. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/approval_process.py +0 -0
  53. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/base.py +0 -0
  54. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/business_model.py +0 -0
  55. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/consolidation.py +0 -0
  56. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/consolidation_process.py +0 -0
  57. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/datatable_mysql.py +0 -0
  58. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/deep_pipeline.py +0 -0
  59. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/deepconnector.py +0 -0
  60. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/deepfos_task.py +0 -0
  61. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/deepmodel.py +0 -0
  62. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/dimension.py +0 -0
  63. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/financial_model.py +0 -0
  64. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/journal_model.py +0 -0
  65. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/journal_template.py +0 -0
  66. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/memory_financial_model.py +0 -0
  67. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/platform.py +0 -0
  68. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/python.py +0 -0
  69. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/reconciliation_engine.py +0 -0
  70. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/reconciliation_report.py +0 -0
  71. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/role_strategy.py +0 -0
  72. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/smartlist.py +0 -0
  73. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/space.py +0 -0
  74. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/system.py +0 -0
  75. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/variable.py +0 -0
  76. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/models/workflow.py +0 -0
  77. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/platform.py +0 -0
  78. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/python.py +0 -0
  79. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/reconciliation_engine.py +0 -0
  80. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/reconciliation_report.py +0 -0
  81. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/role_strategy.py +0 -0
  82. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/smartlist.py +0 -0
  83. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/space.py +0 -0
  84. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/system.py +0 -0
  85. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/variable.py +0 -0
  86. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/api/workflow.py +0 -0
  87. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/boost/__init__.py +0 -0
  88. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/boost/jstream.c +0 -0
  89. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/boost/jstream.pyx +0 -0
  90. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/boost/pandas.c +0 -0
  91. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/boost/pandas.pyx +0 -0
  92. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/boost/py_jstream.py +0 -0
  93. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/boost/py_pandas.py +0 -0
  94. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/cache.py +0 -0
  95. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/config.py +0 -0
  96. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/__init__.py +0 -0
  97. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/cube/__init__.py +0 -0
  98. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/cube/_base.py +0 -0
  99. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/cube/constants.py +0 -0
  100. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/cube/cube.py +0 -0
  101. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/cube/formula.py +0 -0
  102. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/cube/syscube.py +0 -0
  103. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/cube/typing.py +0 -0
  104. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/cube/utils.py +0 -0
  105. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/dimension/__init__.py +0 -0
  106. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/dimension/_base.py +0 -0
  107. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/dimension/dimcreator.py +0 -0
  108. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/dimension/dimension.py +0 -0
  109. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/dimension/dimexpr.py +0 -0
  110. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/dimension/dimmember.py +0 -0
  111. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/dimension/eledimension.py +0 -0
  112. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/dimension/filters.py +0 -0
  113. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/dimension/sysdimension.py +0 -0
  114. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/logictable/__init__.py +0 -0
  115. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/logictable/_cache.py +0 -0
  116. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/logictable/_operator.py +0 -0
  117. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/logictable/nodemixin.py +0 -0
  118. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/logictable/sqlcondition.py +0 -0
  119. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/core/logictable/tablemodel.py +0 -0
  120. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/__init__.py +0 -0
  121. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/cipher.py +0 -0
  122. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/clickhouse.py +0 -0
  123. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/connector.py +0 -0
  124. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/daclickhouse.py +0 -0
  125. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/dameng.py +0 -0
  126. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/damysql.py +0 -0
  127. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/dbkits.py +0 -0
  128. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/deepengine.py +0 -0
  129. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/deepmodel.py +0 -0
  130. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/deepmodel_kingbase.py +0 -0
  131. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/edb.py +0 -0
  132. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/gauss.py +0 -0
  133. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/kingbase.py +0 -0
  134. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/mysql.py +0 -0
  135. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/oracle.py +0 -0
  136. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/postgresql.py +0 -0
  137. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/sqlserver.py +0 -0
  138. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/db/utils.py +0 -0
  139. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/__init__.py +0 -0
  140. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/accounting.py +0 -0
  141. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/apvlprocess.py +0 -0
  142. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/base.py +0 -0
  143. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/bizmodel.py +0 -0
  144. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/datatable.py +0 -0
  145. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/deep_pipeline.py +0 -0
  146. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/deepconnector.py +0 -0
  147. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/fact_table.py +0 -0
  148. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/journal_template.py +0 -0
  149. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/pyscript.py +0 -0
  150. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/reconciliation.py +0 -0
  151. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/rolestrategy.py +0 -0
  152. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/smartlist.py +0 -0
  153. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/variable.py +0 -0
  154. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/element/workflow.py +0 -0
  155. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/exceptions/__init__.py +0 -0
  156. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/exceptions/hook.py +0 -0
  157. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lazy.py +0 -0
  158. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/__init__.py +0 -0
  159. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/_javaobj.py +0 -0
  160. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/asynchronous.py +0 -0
  161. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/concurrency.py +0 -0
  162. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/constant.py +0 -0
  163. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/decorator.py +0 -0
  164. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/deepchart.py +0 -0
  165. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/deepux.py +0 -0
  166. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/discovery.py +0 -0
  167. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/edb_lexer.py +0 -0
  168. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/eureka.py +0 -0
  169. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/filterparser.py +0 -0
  170. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/httpcli.py +0 -0
  171. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/jsonstreamer.py +0 -0
  172. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/msg.py +0 -0
  173. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/nacos.py +0 -0
  174. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/patch.py +0 -0
  175. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/redis.py +0 -0
  176. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/serutils.py +0 -0
  177. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/stopwatch.py +0 -0
  178. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/subtask.py +0 -0
  179. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/sysutils.py +0 -0
  180. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/lib/utils.py +0 -0
  181. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/local.py +0 -0
  182. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos/translation.py +0 -0
  183. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos.egg-info/SOURCES.txt +0 -0
  184. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos.egg-info/dependency_links.txt +0 -0
  185. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos.egg-info/not-zip-safe +0 -0
  186. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos.egg-info/requires.txt +0 -0
  187. {deepfos-1.1.66 → deepfos-1.1.68}/deepfos.egg-info/top_level.txt +0 -0
  188. {deepfos-1.1.66 → deepfos-1.1.68}/requirements.txt +0 -0
  189. {deepfos-1.1.66 → deepfos-1.1.68}/setup.cfg +0 -0
  190. {deepfos-1.1.66 → deepfos-1.1.68}/setup.py +0 -0
  191. {deepfos-1.1.66 → deepfos-1.1.68}/versioneer.py +0 -0
@@ -1,3 +1,24 @@
1
+ ## [1.1.68] - 2025-07-29
2
+
3
+ ### 更新
4
+
5
+ * DeepModel元素insert_df和update_df接受chunksize=None
6
+ * DeepModel元素insert_df和update_df组织的bulk语句优化
7
+ * 修复DataFrame.replace会引发类型推断导致的bug
8
+
9
+
10
+ ## [1.1.67] - 2025-07-22
11
+
12
+ ### 新增
13
+
14
+ * 财务模型元素查询支持指定透视成员列表
15
+ * 凭证模型数据更新接受指定头行操作类型
16
+
17
+ ### 更新
18
+
19
+ * 兼容维度load_dataframe依据共享成员列分数据时共享成员列非bool列的处理
20
+
21
+
1
22
  ## [1.1.66] - 2025-07-10
2
23
 
3
24
  ### 更新
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deepfos
3
- Version: 1.1.66
3
+ Version: 1.1.68
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-07-10T07:24:49+0000",
11
+ "date": "2025-08-07T03:10:50+0000",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "7742bce18499f0a93f0279f4e2d18c6a9113f288",
15
- "version": "1.1.66"
14
+ "full-revisionid": "e1b02f36c62e37f03965c5219dc9426d19af95a8",
15
+ "version": "1.1.68"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -1,4 +1,5 @@
1
1
  import re
2
+ import textwrap
2
3
  import threading
3
4
 
4
5
  import numpy as np
@@ -7,7 +8,7 @@ import json
7
8
  import uuid
8
9
  from contextlib import asynccontextmanager, contextmanager
9
10
  from contextvars import ContextVar
10
- from itertools import count
11
+ from itertools import count, chain
11
12
  from typing import (
12
13
  List, TYPE_CHECKING, Any, Dict, Union, NamedTuple,
13
14
  Iterable, Optional, Literal
@@ -37,7 +38,7 @@ from deepfos.lib import serutils
37
38
  from deepfos.lib.asynchronous import future_property, evloop
38
39
  from deepfos.lib.decorator import flagmethod, cached_property, lru_cache
39
40
  from deepfos.lib.utils import (
40
- AliasGenerator, to_version_tuple, ChunkAlert, split_dataframe_alert
41
+ AliasGenerator, to_version_tuple,
41
42
  )
42
43
 
43
44
  __all__ = ['AsyncDeepModel', 'DeepModel', 'to_fields', 'QueryWithArgs']
@@ -121,6 +122,7 @@ dm_type_to_edb_scalar = {
121
122
  'uuid': 'std::str',
122
123
  'json': 'std::json',
123
124
  }
125
+ TAB = ' ' * 4
124
126
 
125
127
 
126
128
  class ObjectElement(ObjectParam):
@@ -485,19 +487,30 @@ def _iter_single_assign(
485
487
  field: PtrInfo,
486
488
  cast_type: str,
487
489
  target_main_field: Dict[str, MainField]
488
- ):
489
- assign_string = f"{field.name} := "
490
+ ) -> str:
491
+ """
492
+ 生成单字段赋值语句
493
+
494
+ Args:
495
+ field: 字段信息
496
+ cast_type: 字段类型
497
+ target_main_field: 目标字段信息
498
+
499
+ Returns:
500
+ 赋值语句
501
+ """
502
+ assign = f"\n{field.name} := "
490
503
  # 设置标量值
491
504
  if field.name not in target_main_field:
492
505
  if field.is_multi:
493
- return assign_string + f"json_array_unpack(item['{field.name}'])"
506
+ return assign + f"json_array_unpack(item['{field.name}'])"
494
507
 
495
- assign_string += f"<{cast_type}>"
508
+ assign += f"<{cast_type}>"
496
509
 
497
510
  if cast_type in NEED_CAST_STR:
498
- assign_string += '<std::str>'
511
+ assign += '<std::str>'
499
512
 
500
- return assign_string + f"item['{field.name}']"
513
+ return assign + f"item['{field.name}']"
501
514
 
502
515
  # 设置link target值
503
516
  link = field.name
@@ -516,20 +529,20 @@ def _iter_single_assign(
516
529
  target = cast_type
517
530
 
518
531
  if main_field.is_multi:
519
- assign_string += f"""(
520
- select detached {target}
521
- filter contains(
522
- <array<{main_field.type}>>(json_get(item, '{link}', 'target')),
523
- .{main_field.business_key}
524
- )
525
- )"""
532
+ assign += 'distinct (\n' + textwrap.indent(textwrap.dedent(f"""\
533
+ for each_{link} in json_array_unpack(json_get(item, '{link}', 'target'))
534
+ union (
535
+ select detached {target}
536
+ filter .{main_field.business_key} = <{main_field.type}>each_{link}
537
+ )"""), TAB) + '\n)'
526
538
  else:
527
- assign_string += f"""assert_single((
539
+ assign += textwrap.dedent(f"""\
540
+ assert_single((
528
541
  select detached {target}
529
542
  filter .{main_field.business_key} = <{main_field.type}>(json_get(item, '{link}'))
530
- ))"""
543
+ ))""")
531
544
 
532
- return assign_string
545
+ return assign
533
546
 
534
547
 
535
548
  def bulk_insert_by_fields(
@@ -537,21 +550,16 @@ def bulk_insert_by_fields(
537
550
  field_type: List[PtrInfo],
538
551
  target_main_field: Dict[str, MainField],
539
552
  ):
540
- insert_assign_body = ','.join(
541
- [
542
- _iter_single_assign(field, field.type, target_main_field)
543
- for field in field_type
544
- ]
545
- )
546
-
547
- return f"""
548
- with raw_data := <json>to_json(<std::str>${BATCH_INSERT_KW}),
549
- for item in json_array_unpack(raw_data) union (
550
- insert {object_name} {{
551
- {insert_assign_body}
552
- }}
553
- )
554
- """
553
+ insert_assign_body = ','.join([
554
+ _iter_single_assign(field, field.type, target_main_field)
555
+ for field in field_type
556
+ ])
557
+ return textwrap.dedent(f"""
558
+ with raw_data := <json>to_json(<std::str>${BATCH_INSERT_KW}),
559
+ for item in json_array_unpack(raw_data) union (
560
+ insert {object_name} {{{textwrap.indent(insert_assign_body, TAB * 4)}
561
+ }}
562
+ )""")
555
563
 
556
564
 
557
565
  def bulk_upsert_by_fields(
@@ -562,34 +570,27 @@ def bulk_upsert_by_fields(
562
570
  update_fields: Iterable[str]
563
571
  ):
564
572
  conflict_on_fields = map(lambda n: f'.{n}', exclusive_fields)
565
-
566
- insert_assign_body = ','.join(
567
- [
568
- _iter_single_assign(field, field.type, target_main_field)
569
- for field in field_type
570
- ]
571
- )
573
+ insert_assign_body = ','.join([
574
+ _iter_single_assign(field, field.type, target_main_field)
575
+ for field in field_type
576
+ ])
572
577
  update_assign_body = ','.join(
573
578
  [
574
579
  _iter_single_assign(field, field.type, target_main_field)
575
580
  for field in field_type if field.name in update_fields
576
581
  ]
577
582
  )
578
-
579
- return f"""
583
+ return textwrap.dedent(f"""
580
584
  with raw_data := <json>to_json(<std::str>${BATCH_INSERT_KW}),
581
585
  for item in json_array_unpack(raw_data) union (
582
- insert {object_name} {{
583
- {insert_assign_body}
586
+ insert {object_name} {{{textwrap.indent(insert_assign_body, TAB * 4)}
584
587
  }}
585
588
  unless conflict on ({','.join(conflict_on_fields)})
586
589
  else (
587
- update {object_name} set {{
588
- {update_assign_body}
590
+ update {object_name} set {{{textwrap.indent(update_assign_body, TAB * 5)}
589
591
  }}
590
592
  )
591
- )
592
- """
593
+ )""")
593
594
 
594
595
 
595
596
  def bulk_update_by_fields(
@@ -599,32 +600,27 @@ def bulk_update_by_fields(
599
600
  match_fields: Iterable[str],
600
601
  update_fields: Iterable[str],
601
602
  ):
602
- update_assign_body = ','.join(
603
- [
604
- _iter_single_assign(field, field.type, target_main_field)
605
- for field in field_type if field.name in update_fields
606
- ]
607
- )
603
+ update_assign_body = ','.join([
604
+ _iter_single_assign(field, field.type, target_main_field)
605
+ for field in field_type if field.name in update_fields
606
+ ])
608
607
 
609
608
  field_type_map = {field.name: field.type for field in field_type}
610
-
611
609
  match_str = " and ".join(
612
610
  [
613
611
  f".{name} = <{field_type_map.get(name, 'std::str')}>item['{name}']"
614
612
  for name in match_fields
615
613
  ]
616
614
  )
617
-
618
- return f"""
619
- with raw_data := <json>to_json(<std::str>${BATCH_INSERT_KW}),
620
- for item in json_array_unpack(raw_data) union (
621
- update {object_name}
622
- filter {match_str}
623
- set {{
624
- {update_assign_body}
625
- }}
626
- )
627
- """
615
+ return textwrap.dedent(f"""
616
+ with raw_data := <json>to_json(<std::str>${BATCH_INSERT_KW}),
617
+ for item in json_array_unpack(raw_data) union (
618
+ update {object_name}
619
+ filter {match_str}
620
+ set {{{textwrap.indent(update_assign_body, TAB * 3)}
621
+ }}
622
+ )
623
+ """)
628
624
 
629
625
 
630
626
  def format_obj(obj: edgedb.Object) -> ObjectTypeFrame:
@@ -793,8 +789,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
793
789
  self,
794
790
  direct_access: bool = True,
795
791
  pg_dsn: str = None,
796
- before_chunk: ChunkAlert = None,
797
- after_chunk: ChunkAlert = None,
792
+ **kwargs
798
793
  ):
799
794
  self._txn_ = ContextVar('QLTXN')
800
795
  self.appmodule = f"app{OPTION.api.header['app']}"
@@ -805,8 +800,6 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
805
800
  self.alias = AliasGenerator()
806
801
  self.pg_dsn = pg_dsn
807
802
  self._globals = None
808
- self.before_chunk = before_chunk
809
- self.after_chunk = after_chunk
810
803
  self._clients = threading.local()
811
804
 
812
805
  @future_property
@@ -1099,6 +1092,10 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1099
1092
  会自动用作所有string形式ql的参数
1100
1093
 
1101
1094
  """
1095
+ qls_with_args = self._collect_execute_qls(qls, kwargs)
1096
+ return await self._maybe_exec_qls(qls_with_args)
1097
+
1098
+ def _collect_execute_qls(self, qls, kwargs):
1102
1099
  self._ensure_client()
1103
1100
  if isinstance(qls, str):
1104
1101
  qls_with_args = [QueryWithArgs(
@@ -1126,8 +1123,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1126
1123
  ))
1127
1124
  else:
1128
1125
  raise TypeError(f'qls参数中出现类型非法成员:{type(ql)}')
1129
-
1130
- return await self._maybe_exec_qls(qls_with_args)
1126
+ return qls_with_args
1131
1127
 
1132
1128
  execute.__doc__ = execute.__doc__ + DOC_ARGS_KWARGS
1133
1129
 
@@ -1302,6 +1298,10 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1302
1298
  name = field.name
1303
1299
  # 链接至其他对象,记录目标对象信息
1304
1300
  if is_multi:
1301
+ if name not in relation:
1302
+ raise ValueError(
1303
+ f'对象[{object_name}]的多选链接:[{name}]未定义在relation中'
1304
+ )
1305
1305
  link_props = set(relation[name].columns).intersection(field.props)
1306
1306
  else:
1307
1307
  link_props = set(
@@ -1312,30 +1312,17 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1312
1312
  tgt_main_field[name] = MainField(tgt_bkey, is_multi, link_props)
1313
1313
  return field_info, tgt_main_field
1314
1314
 
1315
- def _collect_qls(
1316
- self,
1317
- data: pd.DataFrame,
1318
- ql: str,
1319
- chunksize: int,
1320
- qls: List[QueryWithArgs]
1321
- ):
1315
+ def _ql_payload(self, data: pd.DataFrame, ql: str,):
1322
1316
  self._ensure_client()
1323
-
1324
- for part, alert in split_dataframe_alert(
1325
- data, chunksize, self.before_chunk, self.after_chunk
1326
- ):
1327
- with alert:
1328
- kw_name = self.alias.get(BATCH_INSERT_KW)
1329
- qls.append(QueryWithArgs(
1330
- commands=ql.replace(
1331
- f'${BATCH_INSERT_KW}', f'${kw_name}'
1332
- ),
1333
- kwargs={kw_name: part.to_json(
1334
- orient='records', double_precision=15,
1335
- force_ascii=False, default_handler=str
1336
- )},
1337
- globals=self._globals
1338
- ))
1317
+ kw_name = self.alias.get(BATCH_INSERT_KW)
1318
+ return QueryWithArgs(
1319
+ commands=ql.replace(f'${BATCH_INSERT_KW}', f'${kw_name}'),
1320
+ kwargs={kw_name: data.to_json(
1321
+ orient='records', double_precision=15,
1322
+ force_ascii=False, default_handler=str
1323
+ )},
1324
+ globals=self._globals,
1325
+ )
1339
1326
 
1340
1327
  @staticmethod
1341
1328
  def _split_self_link(data, relation, structure, bkey):
@@ -1391,6 +1378,89 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1391
1378
  data = data.join(link.to_frame(name), on=bkey)
1392
1379
  return data
1393
1380
 
1381
+ async def _collect_bulk_qls(
1382
+ self,
1383
+ object_name: str,
1384
+ data: pd.DataFrame,
1385
+ relation: Dict[str, pd.DataFrame] = None,
1386
+ chunk_size: int = 500,
1387
+ enable_upsert: bool = False,
1388
+ update_fields: Iterable[str] = None,
1389
+ exclusive_fields: Iterable[str] = None,
1390
+ match_fields: Iterable[str] = None,
1391
+ insert: bool = True
1392
+ ) -> List[List[QueryWithArgs]]:
1393
+ if object_name in self.objects:
1394
+ obj = self.objects[object_name]
1395
+ else:
1396
+ raise ObjectNotExist(
1397
+ f'DeepModel对象[{object_name}]在当前应用不存在,无法插入数据'
1398
+ )
1399
+ if obj.external:
1400
+ raise ExternalObjectReadOnly('外部对象只可读')
1401
+
1402
+ structure = ObjectStructure(name=obj.name, structure=obj.fields.values())
1403
+ self._valid_data(data, object_name, relation, structure, check_required=insert)
1404
+
1405
+ relation = relation or {}
1406
+ bkey = await self._get_bkey(obj)
1407
+ if bkey not in data.columns:
1408
+ raise RequiredFieldUnfilled(f'缺少业务主键[{bkey}]')
1409
+
1410
+ # data拼接relation df
1411
+ data = self._merge_relation(data, relation, structure, bkey)
1412
+ # 从data中分离出self-link更新信息
1413
+ data, self_link_dfs = self._split_self_link(data, relation, structure, bkey)
1414
+ field_info, tgt_main_field = await self._collect_bulk_field_info(
1415
+ object_name, structure, data, relation
1416
+ )
1417
+ field_names = set(map(lambda f: f.name, field_info))
1418
+ if insert:
1419
+ if enable_upsert:
1420
+ self._valid_upsert(obj, field_names, bkey, exclusive_fields, update_fields)
1421
+
1422
+ exclusive_fields = set(exclusive_fields or {bkey}) & set(field_names)
1423
+ update_fields = set(update_fields or (field_names - {bkey})) & set(field_names)
1424
+ if enable_upsert and update_fields:
1425
+ bulk_ql = bulk_upsert_by_fields(
1426
+ object_name, field_info, tgt_main_field,
1427
+ exclusive_fields, update_fields
1428
+ )
1429
+ else:
1430
+ bulk_ql = bulk_insert_by_fields(object_name, field_info, tgt_main_field)
1431
+ else:
1432
+ if missing := (set(match_fields or [bkey]) - set(field_names)):
1433
+ raise ValueError(f"match fields: {missing} 不在提供的数据中")
1434
+
1435
+ match_fields = set(match_fields or [bkey]) & set(field_names)
1436
+ if to_upd := (field_names - match_fields):
1437
+ bulk_ql = bulk_update_by_fields(
1438
+ object_name, field_info, tgt_main_field,
1439
+ match_fields, to_upd
1440
+ )
1441
+ else:
1442
+ bulk_ql = None
1443
+ qls = []
1444
+ self._ensure_client()
1445
+ if chunk_size is None:
1446
+ chunk_size = len(data)
1447
+ for i in range(0, len(data), chunk_size):
1448
+ part = structure.fit(data.iloc[i: i + chunk_size])
1449
+ ql_chunk = []
1450
+ # Ignore bulk_ql when only update multi links
1451
+ if bulk_ql is not None:
1452
+ ql_chunk = [self._ql_payload(part, bulk_ql)]
1453
+ for update_field, (update_df, main_field) in self_link_dfs.items():
1454
+ field = structure.fields[update_field]
1455
+ update_ql = bulk_update_by_fields(
1456
+ object_name, [field], {update_field: main_field},
1457
+ [bkey], [update_field]
1458
+ )
1459
+ update_part = update_df.iloc[i: i + chunk_size]
1460
+ ql_chunk.append(self._ql_payload(update_part, update_ql))
1461
+ qls.append(ql_chunk)
1462
+ return qls
1463
+
1394
1464
  @txn_support
1395
1465
  async def insert_df(
1396
1466
  self,
@@ -1401,6 +1471,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1401
1471
  enable_upsert: bool = False,
1402
1472
  update_fields: Iterable[str] = None,
1403
1473
  exclusive_fields: Iterable[str] = None,
1474
+ commit_per_chunk: bool = False,
1404
1475
  ) -> None:
1405
1476
  """以事务执行基于DataFrame字段信息的批量插入数据
1406
1477
 
@@ -1421,6 +1492,9 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1421
1492
  exclusive_fields: upsert句式下update的exclusive fields列表,
1422
1493
  涉及的fields需出现在data或relation中,
1423
1494
  默认为业务主键
1495
+ commit_per_chunk: 每次插入后是否提交事务,
1496
+ 默认为False,即所有数据插入后再提交事务
1497
+ 该参数仅在非start transaction上下文中生效
1424
1498
 
1425
1499
  Notes:
1426
1500
 
@@ -1493,54 +1567,16 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1493
1567
  logger.info("data为空,无DML执行")
1494
1568
  return
1495
1569
 
1496
- if object_name in self.objects:
1497
- obj = self.objects[object_name]
1498
- else:
1499
- raise ObjectNotExist(
1500
- f'DeepModel对象[{object_name}]在当前应用不存在,无法插入数据'
1501
- )
1502
- if obj.external:
1503
- raise ExternalObjectReadOnly('外部对象只可读')
1504
-
1505
- structure = ObjectStructure(name=obj.name, structure=obj.fields.values())
1506
-
1507
- self._valid_data(data, object_name, relation, structure)
1508
-
1509
- relation = relation or {}
1510
- bkey = await self._get_bkey(obj)
1511
- # data拼接relation df
1512
- data = self._merge_relation(data, relation, structure, bkey)
1513
- # 从data中分离出self-link更新信息
1514
- data, self_link_dfs = self._split_self_link(data, relation, structure, bkey)
1515
- field_info, tgt_main_field = await self._collect_bulk_field_info(
1516
- object_name, structure, data, relation
1570
+ qls = await self._collect_bulk_qls(
1571
+ object_name, data, relation, chunksize,
1572
+ enable_upsert, update_fields, exclusive_fields,
1573
+ insert=True
1517
1574
  )
1518
- field_names = set(map(lambda f: f.name, field_info))
1519
- if enable_upsert:
1520
- self._valid_upsert(obj, field_names, bkey, exclusive_fields, update_fields)
1521
-
1522
- exclusive_fields = set(exclusive_fields or {bkey}) & set(field_names)
1523
- update_fields = set(update_fields or (field_names - {bkey})) & set(field_names)
1524
- if enable_upsert and update_fields:
1525
- insert_ql = bulk_upsert_by_fields(
1526
- object_name, field_info, tgt_main_field,
1527
- exclusive_fields, update_fields
1528
- )
1575
+ if commit_per_chunk:
1576
+ for ql_chunk in qls:
1577
+ await self.execute(ql_chunk)
1529
1578
  else:
1530
- insert_ql = bulk_insert_by_fields(object_name, field_info, tgt_main_field)
1531
-
1532
- qls = []
1533
- self._collect_qls(structure.fit(data), insert_ql, chunksize, qls)
1534
- if self_link_dfs:
1535
- for update_field, (update_df, main_field) in self_link_dfs.items():
1536
- field = structure.fields[update_field]
1537
- update_ql = bulk_update_by_fields(
1538
- object_name, [field], {update_field: main_field},
1539
- [bkey], [update_field]
1540
- )
1541
- self._collect_qls(update_df, update_ql, chunksize, qls)
1542
-
1543
- await self.execute(qls)
1579
+ await self.execute(list(chain(*qls)))
1544
1580
 
1545
1581
  async def get_object(
1546
1582
  self,
@@ -1693,6 +1729,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1693
1729
  relation: Dict[str, pd.DataFrame] = None,
1694
1730
  chunksize: int = 500,
1695
1731
  match_fields: Iterable[str] = None,
1732
+ commit_per_chunk: bool = False,
1696
1733
  ) -> None:
1697
1734
  """以事务执行基于DataFrame字段信息的批量更新数据
1698
1735
 
@@ -1709,57 +1746,23 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1709
1746
  若有link property,则以property名为列名,提供在除source和target的列中
1710
1747
  chunksize: 单次最大行数
1711
1748
  match_fields: update的匹配列表,涉及的fields需出现在data或relation中,默认为业务主键
1749
+ commit_per_chunk: 每次插入后是否提交事务,
1750
+ 默认为False,即所有数据插入后再提交事务
1751
+ 该参数仅在非start transaction上下文中生效
1712
1752
  """
1713
1753
  if data.empty:
1714
1754
  logger.info("data为空,无DML执行")
1715
1755
  return
1716
1756
 
1717
- if object_name in self.objects:
1718
- obj = self.objects[object_name]
1719
- else:
1720
- raise ObjectNotExist(
1721
- f'DeepModel对象[{object_name}]在当前应用不存在,无法更新数据'
1722
- )
1723
- if obj.external:
1724
- raise ExternalObjectReadOnly('外部对象只可读')
1725
-
1726
- structure = ObjectStructure(name=obj.name, structure=obj.fields.values())
1727
- self._valid_data(data, object_name, relation, structure, check_required=False)
1728
- relation = relation or {}
1729
- bkey = await self._get_bkey(obj)
1730
- if bkey not in data.columns:
1731
- raise RequiredFieldUnfilled(f'缺少业务主键[{bkey}]')
1732
- # data拼接relation df
1733
- data = self._merge_relation(data, relation, structure, bkey)
1734
- # 从data中分离出self-link更新信息
1735
- data, self_link_dfs = self._split_self_link(data, relation, structure, bkey)
1736
- field_info, tgt_main_field = await self._collect_bulk_field_info(
1737
- object_name, structure, data, relation
1738
- )
1739
- field_names = set(map(lambda f: f.name, field_info))
1740
-
1741
- if missing := (set(match_fields or [bkey]) - set(field_names)):
1742
- raise ValueError(f"match fields: {missing} 不在提供的数据中")
1743
-
1744
- match_fields = set(match_fields or [bkey]) & set(field_names)
1745
- update_ql = bulk_update_by_fields(
1746
- object_name, field_info, tgt_main_field,
1747
- match_fields, field_names - match_fields
1757
+ qls = await self._collect_bulk_qls(
1758
+ object_name, data, relation, chunksize,
1759
+ match_fields=match_fields, insert=False
1748
1760
  )
1749
- qls = []
1750
- self._collect_qls(structure.fit(data), update_ql, chunksize, qls)
1751
- if self_link_dfs:
1752
- for update_field, (update_df, main_field) in self_link_dfs.items():
1753
- field = structure.fields[update_field]
1754
- update_ql = bulk_update_by_fields(
1755
- object_name, [field],
1756
- {update_field: main_field},
1757
- [bkey],
1758
- [update_field]
1759
- )
1760
- self._collect_qls(update_df, update_ql, chunksize, qls)
1761
-
1762
- await self.execute(qls)
1761
+ if commit_per_chunk:
1762
+ for ql_chunk in qls:
1763
+ await self.execute(ql_chunk)
1764
+ else:
1765
+ await self.execute(list(chain(*qls)))
1763
1766
 
1764
1767
  @asynccontextmanager
1765
1768
  async def start_transaction(self, flatten: bool = False):
@@ -1799,7 +1802,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
1799
1802
 
1800
1803
  Important:
1801
1804
 
1802
- 仅 :func:`insert_df` :func:`execute` 方法支持在事务中执行
1805
+ 仅 :func:`insert_df` :func:`update_df` :func:`execute` 方法支持在事务中执行
1803
1806
 
1804
1807
  """
1805
1808
  try:
@@ -1913,6 +1916,7 @@ class DeepModel(AsyncDeepModel, metaclass=SyncMeta):
1913
1916
  enable_upsert: bool = False,
1914
1917
  update_fields: Iterable[str] = None,
1915
1918
  exclusive_fields: Iterable[str] = None,
1919
+ commit_per_chunk: bool = False,
1916
1920
  ) -> None:
1917
1921
  ...
1918
1922
 
@@ -1934,6 +1938,7 @@ class DeepModel(AsyncDeepModel, metaclass=SyncMeta):
1934
1938
  relation: Dict[str, pd.DataFrame] = None,
1935
1939
  chunksize: int = 500,
1936
1940
  match_fields: Iterable[str] = None,
1941
+ commit_per_chunk: bool = False,
1937
1942
  ) -> None:
1938
1943
  ...
1939
1944
 
@@ -956,7 +956,7 @@ class AsyncDimension(ElementBase[DimensionAPI]):
956
956
 
957
957
  # -----------------------------------------------------------------------------
958
958
  # has shared member
959
- df_shared: pd.DataFrame = df[df[shared_mbr_col]]
959
+ df_shared: pd.DataFrame = df[df[shared_mbr_col].astype(bool)]
960
960
  if self._strict:
961
961
  existed_mbrs = self._member_memo
962
962
 
@@ -989,7 +989,7 @@ class AsyncDimension(ElementBase[DimensionAPI]):
989
989
  # 在df中丢弃系统中已存在的共享节点
990
990
  df_shared_remain = df_shared[~df_shared.index.isin(dup_sharedmbrs)]
991
991
 
992
- df_not_shared = df[~df[shared_mbr_col]]
992
+ df_not_shared = df[~df[shared_mbr_col].astype(bool)]
993
993
  existed_idx = df_not_shared[DFLT_NAME_COLUMN].isin(existed_mbrs)
994
994
  return df_not_shared.loc[existed_idx], \
995
995
  pd.concat([df_not_shared.loc[~existed_idx], df_shared_remain])