deepfos 1.1.24__tar.gz → 1.1.25__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.24 → deepfos-1.1.25}/PKG-INFO +1 -1
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/_version.py +3 -3
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/financial_model.py +2 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/finmodel.py +105 -21
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/exceptions/__init__.py +4 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/asynchronous.py +49 -23
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/serutils.py +4 -20
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos.egg-info/PKG-INFO +1 -1
- {deepfos-1.1.24 → deepfos-1.1.25}/MANIFEST.in +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/README.md +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/algo/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/algo/graph.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/V1_1/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/V1_1/business_model.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/V1_1/dimension.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/V1_1/models/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/V1_1/models/business_model.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/V1_1/models/dimension.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/V1_2/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/V1_2/dimension.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/V1_2/models/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/V1_2/models/dimension.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/account.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/accounting_engines.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/app.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/approval_process.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/base.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/business_model.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/consolidation.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/consolidation_process.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/datatable.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/deepconnector.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/deepfos_task.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/deepmodel.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/dimension.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/financial_model.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/journal_model.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/journal_template.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/memory_financial_model.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/account.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/accounting_engines.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/app.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/approval_process.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/base.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/business_model.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/consolidation.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/consolidation_process.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/datatable_mysql.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/deepconnector.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/deepfos_task.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/deepmodel.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/dimension.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/journal_model.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/journal_template.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/memory_financial_model.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/platform.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/python.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/reconciliation_engine.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/reconciliation_report.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/role_strategy.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/smartlist.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/space.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/system.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/variable.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/models/workflow.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/platform.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/python.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/reconciliation_engine.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/reconciliation_report.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/role_strategy.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/smartlist.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/space.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/system.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/variable.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/api/workflow.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/boost/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/boost/jstream.c +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/boost/jstream.pyx +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/boost/pandas.c +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/boost/pandas.pyx +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/boost/py_jstream.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/boost/py_pandas.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/cache.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/config.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/cube/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/cube/_base.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/cube/constants.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/cube/cube.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/cube/formula.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/cube/syscube.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/cube/typing.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/cube/utils.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/dimension/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/dimension/_base.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/dimension/dimcreator.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/dimension/dimension.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/dimension/dimexpr.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/dimension/dimmember.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/dimension/eledimension.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/dimension/filters.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/dimension/sysdimension.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/logictable/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/logictable/_cache.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/logictable/_operator.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/logictable/nodemixin.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/logictable/sqlcondition.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/core/logictable/tablemodel.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/cipher.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/clickhouse.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/connector.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/daclickhouse.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/dameng.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/damysql.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/dbkits.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/deepengine.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/deepmodel.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/deepmodel_kingbase.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/edb.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/gauss.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/kingbase.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/mysql.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/oracle.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/postgresql.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/sqlserver.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/db/utils.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/accounting.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/apvlprocess.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/base.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/bizmodel.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/datatable.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/deepconnector.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/deepmodel.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/dimension.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/fact_table.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/journal.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/journal_template.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/pyscript.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/reconciliation.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/rolestrategy.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/smartlist.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/variable.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/element/workflow.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/exceptions/hook.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lazy.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/_javaobj.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/concurrency.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/constant.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/decorator.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/deepchart.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/deepux.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/discovery.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/eureka.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/filterparser.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/httpcli.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/jsonstreamer.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/nacos.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/patch.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/redis.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/stopwatch.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/subtask.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/sysutils.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/lib/utils.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/local.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/options.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos/translation.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos.egg-info/SOURCES.txt +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos.egg-info/dependency_links.txt +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos.egg-info/not-zip-safe +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos.egg-info/requires.txt +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/deepfos.egg-info/top_level.txt +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/setup.cfg +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/setup.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/tests/__init__.py +0 -0
- {deepfos-1.1.24 → deepfos-1.1.25}/versioneer.py +0 -0
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2023-12-
|
|
11
|
+
"date": "2023-12-19T06:52:40+0000",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "1.1.
|
|
14
|
+
"full-revisionid": "0c1304879b006d56f7565a69c2cb418cd6f94968",
|
|
15
|
+
"version": "1.1.25"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -44,8 +44,7 @@ from deepfos.api.models.financial_model import (
|
|
|
44
44
|
from deepfos.api.models.base import BaseModel
|
|
45
45
|
from deepfos.options import OPTION
|
|
46
46
|
from deepfos.lib.decorator import cached_property
|
|
47
|
-
from deepfos.exceptions import MDXExecuteTimeout
|
|
48
|
-
|
|
47
|
+
from deepfos.exceptions import MDXExecuteTimeout, MDXExecuteFail
|
|
49
48
|
|
|
50
49
|
__all__ = [
|
|
51
50
|
'AsyncFinancialCube',
|
|
@@ -487,6 +486,7 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
487
486
|
need_check: bool = True,
|
|
488
487
|
data_audit: bool = True,
|
|
489
488
|
chunksize: Optional[int] = None,
|
|
489
|
+
callback: bool = True
|
|
490
490
|
):
|
|
491
491
|
"""
|
|
492
492
|
将DataFrame的数据保存至cube。
|
|
@@ -499,6 +499,7 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
499
499
|
data_audit: 是否需要记录到数据审计
|
|
500
500
|
chunksize: 单次调用保存接口时最大的dataframe行数。
|
|
501
501
|
当data的行数超过此值时,将会分多次进行保存。
|
|
502
|
+
callback: 是否回调
|
|
502
503
|
|
|
503
504
|
Note:
|
|
504
505
|
此方法会对落库数据做以下处理:
|
|
@@ -539,7 +540,10 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
539
540
|
if missing_dims := required_cols - set(data.columns):
|
|
540
541
|
raise ValueError(
|
|
541
542
|
f"Cannot save data because following columns are missing: {missing_dims}")
|
|
542
|
-
return await self._save_impl(
|
|
543
|
+
return await self._save_impl(
|
|
544
|
+
data[list(required_cols)],
|
|
545
|
+
pov, need_check, data_audit, chunksize, callback
|
|
546
|
+
)
|
|
543
547
|
|
|
544
548
|
async def save_unpivot(
|
|
545
549
|
self,
|
|
@@ -550,6 +554,7 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
550
554
|
data_audit: bool = True,
|
|
551
555
|
chunksize: Optional[int] = None,
|
|
552
556
|
save_nan: bool = False,
|
|
557
|
+
callback: bool = True
|
|
553
558
|
):
|
|
554
559
|
"""保存有某个维度所有成员在列上的 ``DataFrame``
|
|
555
560
|
|
|
@@ -567,6 +572,7 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
567
572
|
chunksize: 单次调用保存接口时最大的dataframe行数。
|
|
568
573
|
当data的行数超过此值时,将会分多次进行保存。
|
|
569
574
|
save_nan: 当把数据列成员转换到行上时,data为空的数据是否保存
|
|
575
|
+
callback: 是否回调
|
|
570
576
|
|
|
571
577
|
Warnings:
|
|
572
578
|
由于数据完整性等原因,此方法接收的dataframe数据列经常会有一些额外的空值。
|
|
@@ -610,7 +616,9 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
610
616
|
logger.info("Will not save to cube because dataframe is empty.")
|
|
611
617
|
return
|
|
612
618
|
|
|
613
|
-
return await self._save_impl(
|
|
619
|
+
return await self._save_impl(
|
|
620
|
+
data, pov, need_check, data_audit, chunksize, callback
|
|
621
|
+
)
|
|
614
622
|
|
|
615
623
|
async def _save_impl(
|
|
616
624
|
self,
|
|
@@ -619,6 +627,7 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
619
627
|
need_check: bool = True,
|
|
620
628
|
data_audit: bool = True,
|
|
621
629
|
chunksize: Optional[int] = None,
|
|
630
|
+
callback: bool = True
|
|
622
631
|
):
|
|
623
632
|
# replace NaN to standard None
|
|
624
633
|
data = data.mask(data.isna(), None)
|
|
@@ -643,18 +652,20 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
643
652
|
needCheck=need_check,
|
|
644
653
|
dataAuditSwitch=data_audit,
|
|
645
654
|
entryMode=1,
|
|
646
|
-
validateDimensionMember=need_check
|
|
655
|
+
validateDimensionMember=need_check,
|
|
656
|
+
callback=callback
|
|
657
|
+
)
|
|
658
|
+
r = await self.async_api.reactspreadsheet.save(
|
|
659
|
+
payload.dict(exclude_unset=True)
|
|
647
660
|
)
|
|
648
|
-
r = await self.async_api.reactspreadsheet.save(payload.dict(exclude_unset=True))
|
|
649
661
|
resp.append(r)
|
|
650
662
|
return resp
|
|
651
663
|
|
|
652
|
-
async def
|
|
664
|
+
async def delete_with_mdx(
|
|
653
665
|
self,
|
|
654
|
-
expression: Union[str, Dict[str, Union[List[str], str]]]
|
|
655
|
-
chunksize: Optional[int] = None
|
|
666
|
+
expression: Union[str, Dict[str, Union[List[str], str]]]
|
|
656
667
|
):
|
|
657
|
-
"""
|
|
668
|
+
"""通过MDX脚本删除数据
|
|
658
669
|
|
|
659
670
|
根据维度表达式删除Cube数据
|
|
660
671
|
|
|
@@ -665,7 +676,6 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
665
676
|
|
|
666
677
|
Args:
|
|
667
678
|
expression: 维度表达式
|
|
668
|
-
chunksize: 目前使用MDX实现,已弃用(弃用版本: 1.1.24),仅兼容旧版本保留
|
|
669
679
|
|
|
670
680
|
.. admonition:: 示例
|
|
671
681
|
|
|
@@ -676,25 +686,20 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
676
686
|
|
|
677
687
|
cube = FinancialCube('example')
|
|
678
688
|
expr = 'Year{2021;2022}->Entiy{Base(TotalEntity,0)}'
|
|
679
|
-
r = cube.
|
|
689
|
+
r = cube.delete_with_mdx(expr)
|
|
680
690
|
expr_dict = {
|
|
681
691
|
"Year": ['2021', '2022'],
|
|
682
692
|
"Entity": "Base(TotalEntity,0)"
|
|
683
693
|
}
|
|
684
|
-
r = cube.
|
|
694
|
+
r = cube.delete_with_mdx(expr_dict)
|
|
685
695
|
|
|
686
696
|
Returns:
|
|
687
|
-
|
|
697
|
+
MDX执行结果
|
|
688
698
|
|
|
689
699
|
See Also:
|
|
690
|
-
:meth:`insert_null`
|
|
700
|
+
:meth:`insert_null` :meth:`delete`
|
|
691
701
|
|
|
692
702
|
"""
|
|
693
|
-
if chunksize:
|
|
694
|
-
logger.warning(
|
|
695
|
-
'Parameter \'chunksize\' is deprecated since 1.1.24'
|
|
696
|
-
)
|
|
697
|
-
|
|
698
703
|
if isinstance(expression, dict):
|
|
699
704
|
expression = dict_to_expr(expression)
|
|
700
705
|
|
|
@@ -779,6 +784,69 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
779
784
|
|
|
780
785
|
return await self.mdx_execution(script)
|
|
781
786
|
|
|
787
|
+
async def delete(
|
|
788
|
+
self,
|
|
789
|
+
expression: Union[str, Dict[str, Union[List[str], str]]],
|
|
790
|
+
chunksize: Optional[int] = None,
|
|
791
|
+
use_mdx: bool = False,
|
|
792
|
+
callback: bool = True
|
|
793
|
+
):
|
|
794
|
+
"""删除数据
|
|
795
|
+
|
|
796
|
+
根据维度表达式删除Cube数据。
|
|
797
|
+
|
|
798
|
+
Warnings:
|
|
799
|
+
此方法首先查询数据,并且替换为null再调用保存接口。
|
|
800
|
+
因此如果要删除的数据量大,可能导致内存不足等问题。
|
|
801
|
+
如果不需要数据审计功能,请使用 :meth:`insert_null`
|
|
802
|
+
|
|
803
|
+
Args:
|
|
804
|
+
expression: 维度表达式
|
|
805
|
+
chunksize: 单次调用保存接口时最大的dataframe行数。
|
|
806
|
+
当data的行数超过此值时,将会分多次进行保存。
|
|
807
|
+
use_mdx: 是否使用MDX脚本实现,默认为否,等效于调用 :meth:`delete_with_mdx`
|
|
808
|
+
callback: 是否回调
|
|
809
|
+
|
|
810
|
+
.. admonition:: 示例
|
|
811
|
+
|
|
812
|
+
两种调用方式等价:
|
|
813
|
+
|
|
814
|
+
.. code-block:: python
|
|
815
|
+
:emphasize-lines: 3,8
|
|
816
|
+
|
|
817
|
+
cube = FinancialCube('example')
|
|
818
|
+
expr = 'Year{2021;2022}->Entiy{Base(TotalEntity,0)}'
|
|
819
|
+
r = cube.delete(expr)
|
|
820
|
+
expr_dict = {
|
|
821
|
+
"Year": ['2021', '2022'],
|
|
822
|
+
"Entity": "Base(TotalEntity,0)"
|
|
823
|
+
}
|
|
824
|
+
r = cube.delete(expr_dict)
|
|
825
|
+
|
|
826
|
+
Returns:
|
|
827
|
+
删除结果
|
|
828
|
+
|
|
829
|
+
See Also:
|
|
830
|
+
:meth:`insert_null` :meth:`delete_with_mdx`
|
|
831
|
+
|
|
832
|
+
"""
|
|
833
|
+
if use_mdx:
|
|
834
|
+
return await self.delete_with_mdx(expression)
|
|
835
|
+
|
|
836
|
+
if self._meta.autoCalculation:
|
|
837
|
+
if isinstance(expression, str):
|
|
838
|
+
expression = expr_to_dict(expression)
|
|
839
|
+
expression = {**expression}
|
|
840
|
+
|
|
841
|
+
if isinstance(expression, dict):
|
|
842
|
+
expression = dict_to_expr(expression)
|
|
843
|
+
|
|
844
|
+
data, pov = await self.query(expression)
|
|
845
|
+
data[DFLT_DATA_COLUMN] = None
|
|
846
|
+
return await self.save(
|
|
847
|
+
data, pov, data_audit=True, chunksize=chunksize, callback=callback
|
|
848
|
+
)
|
|
849
|
+
|
|
782
850
|
async def queries(
|
|
783
851
|
self,
|
|
784
852
|
expressions: Iterable[str],
|
|
@@ -1204,6 +1272,11 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
1204
1272
|
if res.status == 1:
|
|
1205
1273
|
raise MDXExecuteTimeout(f'MDX执行超时,具体响应:\n{res}')
|
|
1206
1274
|
|
|
1275
|
+
if res.result is False:
|
|
1276
|
+
raise MDXExecuteFail(
|
|
1277
|
+
f'MDX执行失败,失败原因:\n{res.failReason}'
|
|
1278
|
+
)
|
|
1279
|
+
|
|
1207
1280
|
return res
|
|
1208
1281
|
|
|
1209
1282
|
|
|
@@ -1214,6 +1287,7 @@ class FinancialCube(AsyncFinancialCube, metaclass=SyncMeta):
|
|
|
1214
1287
|
'save',
|
|
1215
1288
|
'save_unpivot',
|
|
1216
1289
|
'delete',
|
|
1290
|
+
'delete_with_mdx',
|
|
1217
1291
|
'pc_init',
|
|
1218
1292
|
'pc_update',
|
|
1219
1293
|
'pc_upsert',
|
|
@@ -1252,6 +1326,7 @@ class FinancialCube(AsyncFinancialCube, metaclass=SyncMeta):
|
|
|
1252
1326
|
need_check: bool = True,
|
|
1253
1327
|
data_audit: bool = True,
|
|
1254
1328
|
chunksize: Optional[int] = None,
|
|
1329
|
+
callback: bool = True
|
|
1255
1330
|
):
|
|
1256
1331
|
...
|
|
1257
1332
|
|
|
@@ -1264,13 +1339,22 @@ class FinancialCube(AsyncFinancialCube, metaclass=SyncMeta):
|
|
|
1264
1339
|
data_audit: bool = True,
|
|
1265
1340
|
chunksize: Optional[int] = None,
|
|
1266
1341
|
save_nan: bool = False,
|
|
1342
|
+
callback: bool = True
|
|
1267
1343
|
):
|
|
1268
1344
|
...
|
|
1269
1345
|
|
|
1270
1346
|
def delete(
|
|
1271
1347
|
self,
|
|
1272
1348
|
expression: Union[str, Dict[str, Union[List[str], str]]],
|
|
1273
|
-
chunksize: Optional[int] = None
|
|
1349
|
+
chunksize: Optional[int] = None,
|
|
1350
|
+
use_mdx: bool = False,
|
|
1351
|
+
callback: bool = True
|
|
1352
|
+
):
|
|
1353
|
+
...
|
|
1354
|
+
|
|
1355
|
+
def delete_with_mdx(
|
|
1356
|
+
self,
|
|
1357
|
+
expression: Union[str, Dict[str, Union[List[str], str]]]
|
|
1274
1358
|
):
|
|
1275
1359
|
...
|
|
1276
1360
|
|
|
@@ -129,6 +129,10 @@ class MDXExecuteTimeout(DeepfosBaseException):
|
|
|
129
129
|
"""执行MDX任务超时"""
|
|
130
130
|
|
|
131
131
|
|
|
132
|
+
class MDXExecuteFail(DeepfosBaseException):
|
|
133
|
+
"""执行MDX任务失败"""
|
|
134
|
+
|
|
135
|
+
|
|
132
136
|
# -----------------------------------------------------------------------------
|
|
133
137
|
# DeepModel Error
|
|
134
138
|
class DeepModelError(DeepfosBaseException):
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import asyncio
|
|
2
4
|
import itertools
|
|
3
5
|
from asyncio import SelectorEventLoop
|
|
4
6
|
import asyncio.events as events
|
|
7
|
+
from asyncio import Future as AioFuture
|
|
5
8
|
import sys
|
|
6
9
|
from contextlib import contextmanager
|
|
7
10
|
from heapq import heappop
|
|
@@ -14,7 +17,7 @@ import atexit
|
|
|
14
17
|
from typing import (
|
|
15
18
|
Optional, Tuple, Union, TYPE_CHECKING, List,
|
|
16
19
|
Callable, NamedTuple, Coroutine, Any, Dict,
|
|
17
|
-
Generic, Iterable, TypeVar, Awaitable, overload
|
|
20
|
+
Generic, Iterable, TypeVar, Awaitable, overload,
|
|
18
21
|
)
|
|
19
22
|
# noinspection PyProtectedMember
|
|
20
23
|
from concurrent.futures._base import (
|
|
@@ -269,11 +272,11 @@ class LinkedList(Generic[LinkListItem]):
|
|
|
269
272
|
self.remove(node)
|
|
270
273
|
|
|
271
274
|
|
|
272
|
-
class _AbstractTask(Generic[
|
|
275
|
+
class _AbstractTask(Generic[ReturnT]):
|
|
273
276
|
def __init__(
|
|
274
277
|
self,
|
|
275
|
-
future:
|
|
276
|
-
coro: Coroutine,
|
|
278
|
+
future: Union[Future[ReturnT], AioFuture[ReturnT]],
|
|
279
|
+
coro: Coroutine[ReturnT, Any, ReturnT],
|
|
277
280
|
ensure_completed: bool = False,
|
|
278
281
|
die_in_peace: bool = False
|
|
279
282
|
):
|
|
@@ -282,10 +285,10 @@ class _AbstractTask(Generic[FutureT]):
|
|
|
282
285
|
self.ensure_completed = ensure_completed
|
|
283
286
|
self.die_in_peace = die_in_peace
|
|
284
287
|
|
|
285
|
-
def result(self, timeout: Optional[float] = None): # pragma: no cover
|
|
288
|
+
def result(self, timeout: Optional[float] = None) -> ReturnT: # pragma: no cover
|
|
286
289
|
raise NotImplementedError
|
|
287
290
|
|
|
288
|
-
def done(self):
|
|
291
|
+
def done(self) -> bool:
|
|
289
292
|
return self.future.done()
|
|
290
293
|
|
|
291
294
|
def add_done_callback(self, callback):
|
|
@@ -305,26 +308,40 @@ class _AbstractTask(Generic[FutureT]):
|
|
|
305
308
|
)
|
|
306
309
|
|
|
307
310
|
|
|
308
|
-
class AsyncIOTask(_AbstractTask
|
|
309
|
-
def __init__(
|
|
310
|
-
|
|
311
|
+
class AsyncIOTask(_AbstractTask):
|
|
312
|
+
def __init__(
|
|
313
|
+
self,
|
|
314
|
+
future: AioFuture[ReturnT],
|
|
315
|
+
coro: Coroutine[ReturnT, Any, ReturnT],
|
|
316
|
+
ensure_completed: bool = False,
|
|
317
|
+
):
|
|
318
|
+
super().__init__(future, coro, ensure_completed)
|
|
311
319
|
self.r = UNSET
|
|
320
|
+
self.exc = None
|
|
312
321
|
self.future.add_done_callback(self.set_task_done)
|
|
313
322
|
|
|
314
|
-
def set_task_done(self, future:
|
|
315
|
-
|
|
323
|
+
def set_task_done(self, future: AioFuture):
|
|
324
|
+
if exc := future.exception():
|
|
325
|
+
self.exc = exc
|
|
326
|
+
else:
|
|
327
|
+
self.r = future.result()
|
|
316
328
|
|
|
317
329
|
async def _wait_for_result(self, timeout=None):
|
|
318
330
|
return await asyncio.wait_for(self.future, timeout)
|
|
319
331
|
|
|
320
|
-
def result(self, timeout: Optional[float] = None):
|
|
332
|
+
def result(self, timeout: Optional[float] = None) -> ReturnT:
|
|
333
|
+
if self.exc is not None:
|
|
334
|
+
raise self.exc
|
|
321
335
|
if self.r is UNSET:
|
|
322
336
|
evloop.run(self._wait_for_result(timeout))
|
|
323
337
|
return self.r
|
|
324
338
|
|
|
325
339
|
|
|
326
|
-
class ThreadTask(_AbstractTask
|
|
327
|
-
|
|
340
|
+
class ThreadTask(_AbstractTask):
|
|
341
|
+
if TYPE_CHECKING:
|
|
342
|
+
future: Future
|
|
343
|
+
|
|
344
|
+
def result(self, timeout: Optional[float] = None) -> ReturnT:
|
|
328
345
|
if (
|
|
329
346
|
evloop.in_same_thread()
|
|
330
347
|
and not (
|
|
@@ -419,13 +436,17 @@ class EventLoop:
|
|
|
419
436
|
def set_loop(self, loop: asyncio.BaseEventLoop):
|
|
420
437
|
self.__loop = loop
|
|
421
438
|
|
|
422
|
-
def run(self, coro):
|
|
439
|
+
def run(self, coro: Coroutine[ReturnT, Any, ReturnT]) -> ReturnT:
|
|
423
440
|
if self.in_same_thread():
|
|
424
441
|
return self.loop.run_until_complete(coro)
|
|
425
442
|
else:
|
|
426
443
|
return self.create_task(coro).result()
|
|
427
444
|
|
|
428
|
-
def create_task(
|
|
445
|
+
def create_task(
|
|
446
|
+
self,
|
|
447
|
+
coro: Coroutine[ReturnT, Any, ReturnT],
|
|
448
|
+
ensure_completed=False
|
|
449
|
+
) -> _AbstractTask[ReturnT]:
|
|
429
450
|
task: _AbstractTask
|
|
430
451
|
if self.in_same_thread():
|
|
431
452
|
task = AsyncIOTask(
|
|
@@ -446,7 +467,12 @@ class EventLoop:
|
|
|
446
467
|
|
|
447
468
|
def _report_task_done(self, node: Node):
|
|
448
469
|
def cb(fut):
|
|
449
|
-
|
|
470
|
+
def get_hint():
|
|
471
|
+
if exc := fut.exception():
|
|
472
|
+
return f'failed with exception: {exc!r}'
|
|
473
|
+
else:
|
|
474
|
+
return f'finsihed with result: {fut.result()}'
|
|
475
|
+
logger.opt(lazy=True).debug(f"Task {node.value} {{}}", get_hint)
|
|
450
476
|
self._tasks.remove(node)
|
|
451
477
|
return cb
|
|
452
478
|
|
|
@@ -539,7 +565,7 @@ class EventLoop:
|
|
|
539
565
|
periodic_task.task.cancel()
|
|
540
566
|
if periodic_task.on_stop is not None:
|
|
541
567
|
self.run(periodic_task.on_stop())
|
|
542
|
-
except Exception: # pragma: no cover
|
|
568
|
+
except Exception: # pragma: no cover # noqa
|
|
543
569
|
logger.exception("Exception occurs when cancel task.")
|
|
544
570
|
|
|
545
571
|
|
|
@@ -599,16 +625,16 @@ class _TaskProp:
|
|
|
599
625
|
class future_property(Generic[ReturnT]):
|
|
600
626
|
def __init__(
|
|
601
627
|
self,
|
|
602
|
-
func: Optional[Callable[[Any],
|
|
603
|
-
on_demand=False
|
|
628
|
+
func: Optional[Callable[[Any], Coroutine[ReturnT, Any, ReturnT]]] = None,
|
|
629
|
+
on_demand: bool = False
|
|
604
630
|
):
|
|
605
631
|
self.func = func
|
|
606
632
|
self.on_demand = on_demand
|
|
607
633
|
if func is not None:
|
|
608
634
|
self.__doc__ = func.__doc__
|
|
609
|
-
self._tasks: Dict[
|
|
635
|
+
self._tasks: Dict[int, _TaskProp] = {}
|
|
610
636
|
|
|
611
|
-
def __call__(self, func: Callable[[Any],
|
|
637
|
+
def __call__(self, func: Callable[[Any], Coroutine[ReturnT, Any, ReturnT]]):
|
|
612
638
|
self.func = func
|
|
613
639
|
self.__doc__ = func.__doc__
|
|
614
640
|
return self
|
|
@@ -778,7 +804,7 @@ class DeepFOSIO:
|
|
|
778
804
|
finally:
|
|
779
805
|
try:
|
|
780
806
|
await self.apply_handler(self.on_shutdown)
|
|
781
|
-
except Exception: # pragma: no cover
|
|
807
|
+
except Exception: # pragma: no cover # noqa
|
|
782
808
|
pass
|
|
783
809
|
|
|
784
810
|
|
|
@@ -107,39 +107,23 @@ def _set(o):
|
|
|
107
107
|
return [serialize(el) for el in o]
|
|
108
108
|
|
|
109
109
|
|
|
110
|
-
@serialize.register(uuid.UUID)
|
|
111
|
-
def _stringify(o):
|
|
112
|
-
return str(o)
|
|
113
|
-
|
|
114
|
-
|
|
115
110
|
@serialize.register(int)
|
|
116
111
|
@serialize.register(float)
|
|
117
112
|
@serialize.register(str)
|
|
118
113
|
@serialize.register(bytes)
|
|
119
114
|
@serialize.register(bool)
|
|
120
115
|
@serialize.register(type(None))
|
|
116
|
+
@serialize.register(uuid.UUID)
|
|
121
117
|
@serialize.register(decimal.Decimal)
|
|
122
118
|
@serialize.register(datetime.timedelta)
|
|
119
|
+
@serialize.register(datetime.date)
|
|
120
|
+
@serialize.register(datetime.datetime)
|
|
121
|
+
@serialize.register(datetime.time)
|
|
123
122
|
@serialize.register(edgedb.RelativeDuration)
|
|
124
123
|
def _scalar(o):
|
|
125
124
|
return o
|
|
126
125
|
|
|
127
126
|
|
|
128
|
-
@serialize.register
|
|
129
|
-
def _datetime(o: datetime.datetime):
|
|
130
|
-
return o.isoformat()
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
@serialize.register
|
|
134
|
-
def _date(o: datetime.date):
|
|
135
|
-
return o.isoformat()
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
@serialize.register
|
|
139
|
-
def _time(o: datetime.time):
|
|
140
|
-
return o.isoformat()
|
|
141
|
-
|
|
142
|
-
|
|
143
127
|
@serialize.register
|
|
144
128
|
def _enum(o: edgedb.EnumValue):
|
|
145
129
|
return str(o)
|
|
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
|