deepfos 1.1.75__tar.gz → 1.1.76__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.
- {deepfos-1.1.75 → deepfos-1.1.76}/CHANGELOG.md +9 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/PKG-INFO +1 -1
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/_version.py +3 -3
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/V1_2/models/dimension.py +1 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/dimension.py +1 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/deepmodel.py +91 -38
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/dimension.py +16 -3
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos.egg-info/PKG-INFO +1 -1
- {deepfos-1.1.75 → deepfos-1.1.76}/.gitattributes +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/.gitee/ISSUE_GUIDELINES.md +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/.gitee/ISSUE_TEMPLATE.md +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/.gitignore +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/MANIFEST.in +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/README.md +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/algo/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/algo/graph.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/V1_1/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/V1_1/business_model.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/V1_1/dimension.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/V1_1/models/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/V1_1/models/business_model.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/V1_1/models/dimension.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/V1_2/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/V1_2/dimension.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/V1_2/models/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/account.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/accounting_engines.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/app.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/approval_process.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/base.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/business_model.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/consolidation.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/consolidation_process.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/datatable.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/deep_pipeline.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/deepconnector.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/deepfos_task.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/deepmodel.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/dimension.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/financial_model.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/journal_model.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/journal_template.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/memory_financial_model.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/account.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/accounting_engines.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/app.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/approval_process.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/base.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/business_model.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/consolidation.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/consolidation_process.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/datatable_mysql.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/deep_pipeline.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/deepconnector.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/deepfos_task.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/deepmodel.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/financial_model.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/journal_model.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/journal_template.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/memory_financial_model.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/platform.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/python.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/reconciliation_engine.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/reconciliation_report.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/role_strategy.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/smartlist.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/space.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/system.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/variable.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/models/workflow.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/platform.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/python.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/reconciliation_engine.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/reconciliation_report.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/role_strategy.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/smartlist.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/space.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/system.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/variable.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/api/workflow.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/boost/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/boost/jstream.c +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/boost/jstream.pyx +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/boost/pandas.c +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/boost/pandas.pyx +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/boost/py_jstream.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/boost/py_pandas.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/cache.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/config.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/cube/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/cube/_base.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/cube/constants.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/cube/cube.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/cube/formula.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/cube/syscube.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/cube/typing.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/cube/utils.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/dimension/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/dimension/_base.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/dimension/dimcreator.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/dimension/dimension.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/dimension/dimexpr.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/dimension/dimmember.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/dimension/eledimension.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/dimension/filters.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/dimension/sysdimension.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/logictable/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/logictable/_cache.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/logictable/_operator.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/logictable/nodemixin.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/logictable/sqlcondition.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/core/logictable/tablemodel.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/cipher.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/clickhouse.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/connector.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/daclickhouse.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/dameng.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/damysql.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/dbkits.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/deepengine.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/deepmodel.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/deepmodel_kingbase.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/edb.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/gauss.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/kingbase.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/mysql.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/oracle.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/postgresql.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/sqlserver.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/db/utils.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/accounting.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/apvlprocess.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/base.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/bizmodel.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/datatable.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/deep_pipeline.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/deepconnector.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/fact_table.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/finmodel.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/journal.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/journal_template.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/pyscript.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/reconciliation.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/rolestrategy.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/smartlist.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/variable.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/element/workflow.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/exceptions/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/exceptions/hook.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lazy.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/__init__.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/_javaobj.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/asynchronous.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/concurrency.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/constant.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/decorator.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/deepchart.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/deepux.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/discovery.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/edb_lexer.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/eureka.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/filterparser.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/httpcli.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/jsonstreamer.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/msg.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/nacos.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/patch.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/redis.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/serutils.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/stopwatch.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/subtask.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/sysutils.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/lib/utils.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/local.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/options.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos/translation.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos.egg-info/SOURCES.txt +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos.egg-info/dependency_links.txt +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos.egg-info/not-zip-safe +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos.egg-info/requires.txt +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/deepfos.egg-info/top_level.txt +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/requirements.txt +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/setup.cfg +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/setup.py +0 -0
- {deepfos-1.1.75 → deepfos-1.1.76}/versioneer.py +0 -0
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2025-
|
|
11
|
+
"date": "2025-11-06T08:50:17+0000",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "1.1.
|
|
14
|
+
"full-revisionid": "1f02db295b03468baac5e6df6dfd160ee0eba4a2",
|
|
15
|
+
"version": "1.1.76"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -304,20 +304,43 @@ class ObjectTypeFrame(BaseModel):
|
|
|
304
304
|
return exclusive
|
|
305
305
|
|
|
306
306
|
|
|
307
|
-
def _format_link(
|
|
308
|
-
if
|
|
309
|
-
return
|
|
307
|
+
def _format_link(link_df_fit: pd.DataFrame, link_name: str):
|
|
308
|
+
if link_df_fit.empty:
|
|
309
|
+
return pd.Series(dtype=object), False
|
|
310
310
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
if not record.index.is_unique:
|
|
311
|
+
if link_df_fit.duplicated(subset=['source', 'target']).any():
|
|
314
312
|
raise MultiLinkTargetNotUnique(
|
|
315
313
|
f'Multi Link: [{link_name}] relation dataframe中'
|
|
316
314
|
f'source与target对应存在不唯一性'
|
|
317
315
|
)
|
|
318
316
|
|
|
319
|
-
|
|
320
|
-
|
|
317
|
+
prop_cols = [col for col in link_df_fit.columns if col not in ['source', 'target']]
|
|
318
|
+
has_props = bool(prop_cols)
|
|
319
|
+
|
|
320
|
+
if has_props:
|
|
321
|
+
sources = link_df_fit['source'].values
|
|
322
|
+
targets = link_df_fit['target'].values
|
|
323
|
+
unique_sources, source_indices = np.unique(sources, return_inverse=True)
|
|
324
|
+
|
|
325
|
+
prop_arrays = {col: link_df_fit[col].values for col in prop_cols}
|
|
326
|
+
result = {}
|
|
327
|
+
|
|
328
|
+
for i in range(len(unique_sources)):
|
|
329
|
+
idx = source_indices == i
|
|
330
|
+
source = unique_sources[i]
|
|
331
|
+
source_targets = targets[idx]
|
|
332
|
+
|
|
333
|
+
indices = np.where(idx)[0]
|
|
334
|
+
prop_dict = {
|
|
335
|
+
source_targets[j]: {col: prop_arrays[col][indices[j]] for col in prop_cols}
|
|
336
|
+
for j in range(len(source_targets))
|
|
337
|
+
}
|
|
338
|
+
result[source] = {'target': source_targets.tolist(), 'prop': prop_dict}
|
|
339
|
+
link = pd.Series(result, dtype=object)
|
|
340
|
+
else:
|
|
341
|
+
link = link_df_fit.groupby('source')['target'].agg(list)
|
|
342
|
+
|
|
343
|
+
return link, has_props
|
|
321
344
|
|
|
322
345
|
|
|
323
346
|
class BaseField(PtrInfo):
|
|
@@ -486,7 +509,8 @@ def _iter_link_prop_assign(link, business_key, prop_name, prop_type, is_multi):
|
|
|
486
509
|
def _iter_single_assign(
|
|
487
510
|
field: PtrInfo,
|
|
488
511
|
cast_type: str,
|
|
489
|
-
target_main_field: Dict[str, MainField]
|
|
512
|
+
target_main_field: Dict[str, MainField],
|
|
513
|
+
error_on_empty_link: bool = False
|
|
490
514
|
) -> str:
|
|
491
515
|
"""
|
|
492
516
|
生成单字段赋值语句
|
|
@@ -495,6 +519,7 @@ def _iter_single_assign(
|
|
|
495
519
|
field: 字段信息
|
|
496
520
|
cast_type: 字段类型
|
|
497
521
|
target_main_field: 目标字段信息
|
|
522
|
+
error_on_empty_link: 链接字段值不存在时是否抛出异常
|
|
498
523
|
|
|
499
524
|
Returns:
|
|
500
525
|
赋值语句
|
|
@@ -517,30 +542,38 @@ def _iter_single_assign(
|
|
|
517
542
|
main_field = target_main_field[link]
|
|
518
543
|
|
|
519
544
|
if main_field.props:
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
field.prop_type[name], main_field.is_multi)
|
|
525
|
-
for name in main_field.props
|
|
526
|
-
) + "}"
|
|
545
|
+
prop_assigns = ','.join(
|
|
546
|
+
_iter_link_prop_assign(link, main_field.business_key, name,
|
|
547
|
+
field.prop_type[name], main_field.is_multi)
|
|
548
|
+
for name in main_field.props
|
|
527
549
|
)
|
|
550
|
+
prop_block = f" {{{prop_assigns}}}"
|
|
528
551
|
else:
|
|
529
|
-
|
|
552
|
+
prop_block = ""
|
|
530
553
|
|
|
531
554
|
if main_field.is_multi:
|
|
555
|
+
link_value = f"each_{link}"
|
|
556
|
+
else:
|
|
557
|
+
link_value = f"(json_get(item, '{link}'))"
|
|
558
|
+
|
|
559
|
+
if error_on_empty_link:
|
|
560
|
+
link_expr = f"(<{cast_type}><std::str>{link_value}){prop_block}"
|
|
561
|
+
else:
|
|
562
|
+
link_expr = f"(select detached {cast_type}{prop_block}\nfilter .{main_field.business_key} = <std::str>{link_value})"
|
|
563
|
+
|
|
564
|
+
if main_field.is_multi:
|
|
565
|
+
if main_field.props:
|
|
566
|
+
target_source = f"json_get(item, '{link}', 'target')"
|
|
567
|
+
else:
|
|
568
|
+
target_source = f"item['{link}']"
|
|
569
|
+
|
|
532
570
|
assign += 'distinct (\n' + textwrap.indent(textwrap.dedent(f"""\
|
|
533
|
-
for each_{link} in json_array_unpack(
|
|
571
|
+
for each_{link} in json_array_unpack({target_source})
|
|
534
572
|
union (
|
|
535
|
-
|
|
536
|
-
filter .{main_field.business_key} = <{main_field.type}>each_{link}
|
|
573
|
+
{link_expr}
|
|
537
574
|
)"""), TAB) + '\n)'
|
|
538
575
|
else:
|
|
539
|
-
assign +=
|
|
540
|
-
assert_single((
|
|
541
|
-
select detached {target}
|
|
542
|
-
filter .{main_field.business_key} = <{main_field.type}>(json_get(item, '{link}'))
|
|
543
|
-
))""")
|
|
576
|
+
assign += link_expr
|
|
544
577
|
|
|
545
578
|
return assign
|
|
546
579
|
|
|
@@ -549,9 +582,10 @@ def bulk_insert_by_fields(
|
|
|
549
582
|
object_name: str,
|
|
550
583
|
field_type: List[PtrInfo],
|
|
551
584
|
target_main_field: Dict[str, MainField],
|
|
585
|
+
error_on_empty_link: bool = False,
|
|
552
586
|
):
|
|
553
587
|
insert_assign_body = ','.join([
|
|
554
|
-
_iter_single_assign(field, field.type, target_main_field)
|
|
588
|
+
_iter_single_assign(field, field.type, target_main_field, error_on_empty_link)
|
|
555
589
|
for field in field_type
|
|
556
590
|
])
|
|
557
591
|
return textwrap.dedent(f"""
|
|
@@ -567,16 +601,17 @@ def bulk_upsert_by_fields(
|
|
|
567
601
|
field_type: List[PtrInfo],
|
|
568
602
|
target_main_field: Dict[str, MainField],
|
|
569
603
|
exclusive_fields: Iterable[str],
|
|
570
|
-
update_fields: Iterable[str]
|
|
604
|
+
update_fields: Iterable[str],
|
|
605
|
+
error_on_empty_link: bool = False,
|
|
571
606
|
):
|
|
572
607
|
conflict_on_fields = map(lambda n: f'.{n}', exclusive_fields)
|
|
573
608
|
insert_assign_body = ','.join([
|
|
574
|
-
_iter_single_assign(field, field.type, target_main_field)
|
|
609
|
+
_iter_single_assign(field, field.type, target_main_field, error_on_empty_link)
|
|
575
610
|
for field in field_type
|
|
576
611
|
])
|
|
577
612
|
update_assign_body = ','.join(
|
|
578
613
|
[
|
|
579
|
-
_iter_single_assign(field, field.type, target_main_field)
|
|
614
|
+
_iter_single_assign(field, field.type, target_main_field, error_on_empty_link)
|
|
580
615
|
for field in field_type if field.name in update_fields
|
|
581
616
|
]
|
|
582
617
|
)
|
|
@@ -599,9 +634,10 @@ def bulk_update_by_fields(
|
|
|
599
634
|
target_main_field: Dict[str, MainField],
|
|
600
635
|
match_fields: Iterable[str],
|
|
601
636
|
update_fields: Iterable[str],
|
|
637
|
+
error_on_empty_link: bool = False,
|
|
602
638
|
):
|
|
603
639
|
update_assign_body = ','.join([
|
|
604
|
-
_iter_single_assign(field, field.type, target_main_field)
|
|
640
|
+
_iter_single_assign(field, field.type, target_main_field, error_on_empty_link)
|
|
605
641
|
for field in field_type if field.name in update_fields
|
|
606
642
|
])
|
|
607
643
|
|
|
@@ -1374,9 +1410,20 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1374
1410
|
]
|
|
1375
1411
|
)
|
|
1376
1412
|
link_df = temp_structure.fit(link_df)
|
|
1377
|
-
link = link_df
|
|
1378
|
-
|
|
1379
|
-
|
|
1413
|
+
link, has_props = _format_link(link_df, name)
|
|
1414
|
+
|
|
1415
|
+
if not has_props:
|
|
1416
|
+
data = data.drop(columns=[name], errors='ignore')
|
|
1417
|
+
data = data.join(link.to_frame(name), on=bkey, how='left')
|
|
1418
|
+
mask = data[name].isna()
|
|
1419
|
+
if mask.any():
|
|
1420
|
+
empty_series = pd.Series([[]] * mask.sum(), index=data[mask].index, dtype=object)
|
|
1421
|
+
data.loc[mask, name] = empty_series
|
|
1422
|
+
else:
|
|
1423
|
+
bkey_values = data[bkey].values
|
|
1424
|
+
mapped_values = np.array([link.get(key, []) for key in bkey_values], dtype=object)
|
|
1425
|
+
data[name] = mapped_values
|
|
1426
|
+
|
|
1380
1427
|
return data
|
|
1381
1428
|
|
|
1382
1429
|
async def _collect_bulk_qls(
|
|
@@ -1389,7 +1436,8 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1389
1436
|
update_fields: Iterable[str] = None,
|
|
1390
1437
|
exclusive_fields: Iterable[str] = None,
|
|
1391
1438
|
match_fields: Iterable[str] = None,
|
|
1392
|
-
insert: bool = True
|
|
1439
|
+
insert: bool = True,
|
|
1440
|
+
error_on_empty_link: bool = False
|
|
1393
1441
|
) -> List[List[QueryWithArgs]]:
|
|
1394
1442
|
if object_name in self.objects:
|
|
1395
1443
|
obj = self.objects[object_name]
|
|
@@ -1425,10 +1473,10 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1425
1473
|
if enable_upsert and update_fields:
|
|
1426
1474
|
bulk_ql = bulk_upsert_by_fields(
|
|
1427
1475
|
object_name, field_info, tgt_main_field,
|
|
1428
|
-
exclusive_fields, update_fields
|
|
1476
|
+
exclusive_fields, update_fields, error_on_empty_link
|
|
1429
1477
|
)
|
|
1430
1478
|
else:
|
|
1431
|
-
bulk_ql = bulk_insert_by_fields(object_name, field_info, tgt_main_field)
|
|
1479
|
+
bulk_ql = bulk_insert_by_fields(object_name, field_info, tgt_main_field, error_on_empty_link)
|
|
1432
1480
|
else:
|
|
1433
1481
|
if missing := (set(match_fields or [bkey]) - set(field_names)):
|
|
1434
1482
|
raise ValueError(f"match fields: {missing} 不在提供的数据中")
|
|
@@ -1437,7 +1485,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1437
1485
|
if to_upd := (field_names - match_fields):
|
|
1438
1486
|
bulk_ql = bulk_update_by_fields(
|
|
1439
1487
|
object_name, field_info, tgt_main_field,
|
|
1440
|
-
match_fields, to_upd
|
|
1488
|
+
match_fields, to_upd, error_on_empty_link
|
|
1441
1489
|
)
|
|
1442
1490
|
else:
|
|
1443
1491
|
bulk_ql = None
|
|
@@ -1473,6 +1521,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1473
1521
|
update_fields: Iterable[str] = None,
|
|
1474
1522
|
exclusive_fields: Iterable[str] = None,
|
|
1475
1523
|
commit_per_chunk: bool = False,
|
|
1524
|
+
error_on_empty_link: bool = False,
|
|
1476
1525
|
) -> None:
|
|
1477
1526
|
"""以事务执行基于DataFrame字段信息的批量插入数据
|
|
1478
1527
|
|
|
@@ -1496,6 +1545,9 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1496
1545
|
commit_per_chunk: 每次插入后是否提交事务,
|
|
1497
1546
|
默认为False,即所有数据插入后再提交事务
|
|
1498
1547
|
该参数仅在非start transaction上下文中生效
|
|
1548
|
+
error_on_empty_link: 链接字段值不存在时是否抛出异常,
|
|
1549
|
+
默认为False,即不检查链接目标是否存在
|
|
1550
|
+
当设置为True时,会检查链接目标是否存在,不存在则抛出异常
|
|
1499
1551
|
|
|
1500
1552
|
Notes:
|
|
1501
1553
|
|
|
@@ -1571,7 +1623,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1571
1623
|
qls = await self._collect_bulk_qls(
|
|
1572
1624
|
object_name, data, relation, chunksize,
|
|
1573
1625
|
enable_upsert, update_fields, exclusive_fields,
|
|
1574
|
-
insert=True
|
|
1626
|
+
insert=True, error_on_empty_link=error_on_empty_link
|
|
1575
1627
|
)
|
|
1576
1628
|
if commit_per_chunk:
|
|
1577
1629
|
for ql_chunk in qls:
|
|
@@ -1918,6 +1970,7 @@ class DeepModel(AsyncDeepModel, metaclass=SyncMeta):
|
|
|
1918
1970
|
update_fields: Iterable[str] = None,
|
|
1919
1971
|
exclusive_fields: Iterable[str] = None,
|
|
1920
1972
|
commit_per_chunk: bool = False,
|
|
1973
|
+
error_on_empty_link: bool = False,
|
|
1921
1974
|
) -> None:
|
|
1922
1975
|
...
|
|
1923
1976
|
|
|
@@ -1162,12 +1162,25 @@ def _validate_df_for_dimension(df: pd.DataFrame):
|
|
|
1162
1162
|
f"You have null value in dataframe. "
|
|
1163
1163
|
f"column: [{DFLT_NAME_COLUMN}], index: {null_index}.")
|
|
1164
1164
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1165
|
+
col_parent_name = None
|
|
1166
|
+
col_shared_member = None
|
|
1167
|
+
|
|
1168
|
+
if DFLT_PNAME_COLUMN in df.columns:
|
|
1169
|
+
col_parent_name = DFLT_PNAME_COLUMN
|
|
1170
|
+
elif DFLT_PNAME_COLUMN_V12 in df.columns:
|
|
1171
|
+
col_parent_name = DFLT_PNAME_COLUMN_V12
|
|
1167
1172
|
|
|
1168
1173
|
if SHAREDMEMBER in df.columns:
|
|
1174
|
+
col_shared_member = SHAREDMEMBER
|
|
1175
|
+
elif SHAREDMEMBERV12 in df.columns:
|
|
1176
|
+
col_shared_member = SHAREDMEMBERV12
|
|
1177
|
+
|
|
1178
|
+
if col_parent_name is None:
|
|
1179
|
+
raise ValueError(f"Missing column [{DFLT_PNAME_COLUMN}] or [{DFLT_PNAME_COLUMN_V12}] in dataframe.")
|
|
1180
|
+
|
|
1181
|
+
if col_shared_member is not None:
|
|
1169
1182
|
unique_df = df.groupby(
|
|
1170
|
-
[DFLT_NAME_COLUMN,
|
|
1183
|
+
[DFLT_NAME_COLUMN, col_parent_name, col_shared_member],
|
|
1171
1184
|
as_index=False
|
|
1172
1185
|
).size()
|
|
1173
1186
|
duplicated = unique_df[unique_df['size'] > 1]
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|