deepfos 1.1.76__tar.gz → 1.1.78__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.76 → deepfos-1.1.78}/CHANGELOG.md +15 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/PKG-INFO +1 -1
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/_version.py +3 -3
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/account.py +1 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/app.py +1 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/base.py +68 -70
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/platform.py +1 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/space.py +1 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/system.py +1 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/deepmodel.py +2 -2
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/discovery.py +3 -0
- deepfos-1.1.78/deepfos/lib/k8s.py +101 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/options.py +19 -5
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos.egg-info/PKG-INFO +1 -1
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos.egg-info/SOURCES.txt +2 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/setup.py +1 -1
- {deepfos-1.1.76 → deepfos-1.1.78}/.gitattributes +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/.gitee/ISSUE_GUIDELINES.md +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/.gitee/ISSUE_TEMPLATE.md +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/.gitignore +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/MANIFEST.in +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/README.md +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/algo/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/algo/graph.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/V1_1/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/V1_1/business_model.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/V1_1/dimension.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/V1_1/models/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/V1_1/models/business_model.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/V1_1/models/dimension.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/V1_2/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/V1_2/dimension.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/V1_2/models/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/V1_2/models/dimension.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/accounting_engines.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/approval_process.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/business_model.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/consolidation.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/consolidation_process.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/datatable.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/deep_pipeline.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/deepconnector.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/deepfos_task.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/deepmodel.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/dimension.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/financial_model.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/journal_model.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/journal_template.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/memory_financial_model.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/account.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/accounting_engines.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/app.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/approval_process.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/base.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/business_model.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/consolidation.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/consolidation_process.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/datatable_mysql.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/deep_pipeline.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/deepconnector.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/deepfos_task.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/deepmodel.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/dimension.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/financial_model.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/journal_model.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/journal_template.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/memory_financial_model.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/platform.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/python.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/reconciliation_engine.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/reconciliation_report.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/role_strategy.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/smartlist.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/space.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/system.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/variable.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/models/workflow.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/python.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/reconciliation_engine.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/reconciliation_report.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/role_strategy.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/smartlist.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/variable.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/api/workflow.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/boost/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/boost/jstream.c +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/boost/jstream.pyx +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/boost/pandas.c +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/boost/pandas.pyx +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/boost/py_jstream.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/boost/py_pandas.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/cache.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/config.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/cube/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/cube/_base.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/cube/constants.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/cube/cube.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/cube/formula.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/cube/syscube.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/cube/typing.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/cube/utils.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/dimension/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/dimension/_base.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/dimension/dimcreator.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/dimension/dimension.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/dimension/dimexpr.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/dimension/dimmember.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/dimension/eledimension.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/dimension/filters.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/dimension/sysdimension.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/logictable/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/logictable/_cache.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/logictable/_operator.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/logictable/nodemixin.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/logictable/sqlcondition.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/core/logictable/tablemodel.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/cipher.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/clickhouse.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/connector.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/daclickhouse.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/dameng.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/damysql.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/dbkits.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/deepengine.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/deepmodel.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/deepmodel_kingbase.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/edb.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/gauss.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/kingbase.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/mysql.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/oracle.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/postgresql.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/sqlserver.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/db/utils.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/accounting.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/apvlprocess.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/base.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/bizmodel.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/datatable.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/deep_pipeline.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/deepconnector.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/dimension.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/fact_table.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/finmodel.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/journal.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/journal_template.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/pyscript.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/reconciliation.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/rolestrategy.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/smartlist.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/variable.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/element/workflow.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/exceptions/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/exceptions/hook.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lazy.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/__init__.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/_javaobj.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/asynchronous.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/concurrency.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/constant.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/decorator.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/deepchart.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/deepux.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/edb_lexer.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/eureka.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/filterparser.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/httpcli.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/jsonstreamer.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/msg.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/nacos.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/patch.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/redis.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/serutils.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/stopwatch.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/subtask.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/sysutils.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/lib/utils.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/local.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos/translation.py +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos.egg-info/dependency_links.txt +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos.egg-info/not-zip-safe +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos.egg-info/requires.txt +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/deepfos.egg-info/top_level.txt +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/requirements.txt +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/setup.cfg +0 -0
- {deepfos-1.1.76 → deepfos-1.1.78}/versioneer.py +0 -0
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2025-
|
|
11
|
+
"date": "2025-12-22T07:20:38+0000",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "1.1.
|
|
14
|
+
"full-revisionid": "1a939ca4b6be850040e0d9076eaf235608eebb23",
|
|
15
|
+
"version": "1.1.78"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -120,6 +120,7 @@ class UserImport(ChildAPI):
|
|
|
120
120
|
class AccountAPI(RootAPI):
|
|
121
121
|
"""账户中心"""
|
|
122
122
|
prefix = lambda: OPTION.server.account
|
|
123
|
+
server_name = "seepln-account"
|
|
123
124
|
|
|
124
125
|
def __init__(self, *args, **kwargs):
|
|
125
126
|
super(self.__class__.__base__, self).__init__(*args, **kwargs)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import enum
|
|
2
2
|
import json
|
|
3
3
|
import re
|
|
4
|
-
import weakref
|
|
5
4
|
from importlib import import_module
|
|
6
5
|
from shlex import quote
|
|
7
6
|
from typing import (
|
|
@@ -366,7 +365,8 @@ class Route:
|
|
|
366
365
|
|
|
367
366
|
# ---------------------------------------------------------------------
|
|
368
367
|
# get request info
|
|
369
|
-
|
|
368
|
+
base_url = await ins.get_base_url()
|
|
369
|
+
req = RequestInfo(url=concat_url(base_url, endpoint), method=method)
|
|
370
370
|
req.update_default(func(ins, *args, **kwargs))
|
|
371
371
|
url, body, ext_header = req.url, req.body, req.header
|
|
372
372
|
raw_result = model is None
|
|
@@ -533,6 +533,7 @@ post = DummyDeco(method='post')
|
|
|
533
533
|
|
|
534
534
|
class APIBase:
|
|
535
535
|
endpoint = '/'
|
|
536
|
+
server_name: str = None
|
|
536
537
|
|
|
537
538
|
def __init__(
|
|
538
539
|
self,
|
|
@@ -553,14 +554,27 @@ class APIBase:
|
|
|
553
554
|
else:
|
|
554
555
|
self.header = header
|
|
555
556
|
|
|
556
|
-
|
|
557
|
-
self.base_url = concat_url(OPTION.server.base, mat.group(1), self.endpoint)
|
|
558
|
-
else:
|
|
559
|
-
self.base_url = concat_url(prefix, self.endpoint)
|
|
557
|
+
self.prefix = prefix
|
|
560
558
|
self.header.update({
|
|
561
559
|
"Content-Type": "application/json;charset=UTF8",
|
|
562
560
|
"Connection": "close",
|
|
563
561
|
})
|
|
562
|
+
self.base_url = None
|
|
563
|
+
|
|
564
|
+
async def get_base_url(self):
|
|
565
|
+
if self.base_url is None:
|
|
566
|
+
if (
|
|
567
|
+
OPTION.discovery.enabled
|
|
568
|
+
and OPTION.discovery.take_over
|
|
569
|
+
and self.server_name is not None
|
|
570
|
+
):
|
|
571
|
+
discovery = ServiceDiscovery.instantiate()
|
|
572
|
+
self.base_url = await discovery.get_url(self.server_name)
|
|
573
|
+
elif mat := RE_SYS_SERVER_PARSER.match(self.prefix):
|
|
574
|
+
self.base_url = concat_url(OPTION.server.base, mat.group(1))
|
|
575
|
+
else:
|
|
576
|
+
self.base_url = self.prefix
|
|
577
|
+
return self.base_url
|
|
564
578
|
|
|
565
579
|
|
|
566
580
|
class APIMeta(type):
|
|
@@ -596,9 +610,11 @@ class SyncAPIBase(APIBase, metaclass=APIMeta):
|
|
|
596
610
|
|
|
597
611
|
# noinspection PyUnresolvedReferences
|
|
598
612
|
class _DynamicAPIMixin:
|
|
613
|
+
module_id: str
|
|
599
614
|
server_cache = TTLCache(maxsize=128, ttl=3600)
|
|
600
615
|
module_type: str = UNSET
|
|
601
|
-
|
|
616
|
+
server_name: str = None
|
|
617
|
+
base_url: str = None
|
|
602
618
|
version = None
|
|
603
619
|
|
|
604
620
|
def get_module_id(self, version: Union[float, str], module_id: str):
|
|
@@ -619,16 +635,30 @@ class _DynamicAPIMixin:
|
|
|
619
635
|
self.server_cache[self.module_id] = server_name
|
|
620
636
|
return server_name
|
|
621
637
|
|
|
622
|
-
def get_server_name(self):
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
638
|
+
async def get_server_name(self):
|
|
639
|
+
if self.server_name is None:
|
|
640
|
+
if self.module_id in self.server_cache:
|
|
641
|
+
self.server_name = self.server_cache[self.module_id]
|
|
642
|
+
else:
|
|
643
|
+
from .space import SpaceAPI
|
|
644
|
+
api = SpaceAPI(self.header, sync=False)
|
|
645
|
+
server_meta = await api.module.detail(self.module_id) # noqa
|
|
646
|
+
self.server_name = self._add_to_memo(server_meta)
|
|
647
|
+
return self.server_name
|
|
648
|
+
|
|
649
|
+
async def get_base_url(self):
|
|
650
|
+
if self.base_url is None:
|
|
651
|
+
server_name = await self.get_server_name()
|
|
652
|
+
if OPTION.discovery.enabled: # pragma: no cover
|
|
653
|
+
discovery = ServiceDiscovery.instantiate()
|
|
654
|
+
base_url = await discovery.get_url(server_name)
|
|
655
|
+
self.base_url = concat_url(base_url)
|
|
656
|
+
else:
|
|
657
|
+
self.base_url = concat_url(OPTION.server.base, server_name)
|
|
658
|
+
return self.base_url
|
|
629
659
|
|
|
630
660
|
|
|
631
|
-
class DynamicAPIBase(
|
|
661
|
+
class DynamicAPIBase(_DynamicAPIMixin, SyncAPIBase):
|
|
632
662
|
def __init__(
|
|
633
663
|
self,
|
|
634
664
|
version: Union[float, str] = None,
|
|
@@ -637,33 +667,16 @@ class DynamicAPIBase(SyncAPIBase, _DynamicAPIMixin):
|
|
|
637
667
|
lazy: bool = False
|
|
638
668
|
):
|
|
639
669
|
super().__init__(header)
|
|
640
|
-
self.module_id =
|
|
641
|
-
# lazy = True means called from element/base, will be set url in ElementBase
|
|
642
|
-
if module_id is not None and not lazy:
|
|
643
|
-
if module_id in self.server_cache:
|
|
644
|
-
logger.debug(f'Find server name for module: {module_id} from cache.')
|
|
645
|
-
server_name = self.server_cache[module_id]
|
|
646
|
-
else:
|
|
647
|
-
server_name = self.get_server_name()
|
|
648
|
-
self.set_url(server_name)
|
|
649
|
-
|
|
650
|
-
def get_server_name(self):
|
|
651
|
-
from .space import SpaceAPI
|
|
652
|
-
api = SpaceAPI(self.header, sync=True)
|
|
653
|
-
server_meta = api.module.detail(self.module_id)
|
|
654
|
-
return self._add_to_memo(server_meta)
|
|
655
|
-
|
|
656
|
-
def set_url(self, server_name):
|
|
657
|
-
if OPTION.discovery.enabled: # pragma: no cover
|
|
658
|
-
discovery = ServiceDiscovery.instantiate()
|
|
659
|
-
base_url = discovery.sync_get_url(server_name)
|
|
660
|
-
self.base_url = concat_url(base_url, self.endpoint)
|
|
661
|
-
self.server_known = True
|
|
662
|
-
else:
|
|
663
|
-
super().set_url(server_name)
|
|
670
|
+
self.module_id = self.get_module_id(version, module_id)
|
|
664
671
|
|
|
672
|
+
def set_server_name(self, server_name):
|
|
673
|
+
self.server_name = server_name
|
|
665
674
|
|
|
666
|
-
|
|
675
|
+
# backward compatibility
|
|
676
|
+
set_url = set_server_name
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
class ADynamicAPIBase(_DynamicAPIMixin, AsyncAPIBase):
|
|
667
680
|
def __init__(
|
|
668
681
|
self,
|
|
669
682
|
version: Union[float, str] = None,
|
|
@@ -678,32 +691,14 @@ class ADynamicAPIBase(AsyncAPIBase, _DynamicAPIMixin):
|
|
|
678
691
|
def __await__(self):
|
|
679
692
|
return self.init().__await__()
|
|
680
693
|
|
|
681
|
-
async def get_server_name(self):
|
|
682
|
-
from .space import SpaceAPI
|
|
683
|
-
api = SpaceAPI(self.header, sync=False)
|
|
684
|
-
server_meta = await api.module.detail(self.module_id) # noqa
|
|
685
|
-
return self._add_to_memo(server_meta)
|
|
686
|
-
|
|
687
694
|
async def init(self):
|
|
688
|
-
if self.module_id is None:
|
|
689
|
-
return self
|
|
690
|
-
# lazy = True means called from element/base, will be set url in ElementBase
|
|
691
|
-
if not self.lazy:
|
|
692
|
-
if self.module_id in self.server_cache:
|
|
693
|
-
server_name = self.server_cache[self.module_id]
|
|
694
|
-
else:
|
|
695
|
-
server_name = await self.get_server_name()
|
|
696
|
-
await self.set_url(server_name)
|
|
697
695
|
return self
|
|
698
696
|
|
|
699
|
-
async def
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
self.server_known = True
|
|
705
|
-
else:
|
|
706
|
-
super().set_url(server_name)
|
|
697
|
+
async def set_server_name(self, server_name):
|
|
698
|
+
self.server_name = server_name
|
|
699
|
+
|
|
700
|
+
# backward compatibility
|
|
701
|
+
set_url = set_server_name
|
|
707
702
|
|
|
708
703
|
|
|
709
704
|
class RootAPI:
|
|
@@ -722,6 +717,7 @@ class RootAPI:
|
|
|
722
717
|
api_version = None
|
|
723
718
|
cls_name = None
|
|
724
719
|
module_name = None
|
|
720
|
+
server_name = None
|
|
725
721
|
builtin = True
|
|
726
722
|
|
|
727
723
|
if TYPE_CHECKING: # pragma: no cover
|
|
@@ -881,17 +877,19 @@ class ChildAPI(RootAPI):
|
|
|
881
877
|
def __new__(cls, root: RootAPI):
|
|
882
878
|
clz = cls.resolve_cls(
|
|
883
879
|
root.sync, (SyncAPIBase, _ChildAPI), (AsyncAPIBase, _ChildAPI),
|
|
884
|
-
extra={'
|
|
880
|
+
extra={'get_base_url': cls.get_base_url}
|
|
885
881
|
)
|
|
886
|
-
ins = clz(header=root.header, prefix=root.
|
|
882
|
+
ins = clz(header=root.header, prefix=root.prefix)
|
|
887
883
|
if root.url_need_format:
|
|
888
|
-
ins.
|
|
889
|
-
ins.
|
|
884
|
+
ins.endpoint = ins.endpoint.format(**root.header)
|
|
885
|
+
ins.root = root
|
|
890
886
|
return ins
|
|
891
887
|
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
888
|
+
async def get_base_url(self):
|
|
889
|
+
if self.base_url is None:
|
|
890
|
+
base_url = await self.root.get_base_url()
|
|
891
|
+
self.base_url = concat_url(base_url, self.endpoint)
|
|
892
|
+
return self.base_url
|
|
895
893
|
|
|
896
894
|
|
|
897
895
|
class DynamicRootAPI(RootAPI):
|
|
@@ -1249,7 +1249,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1249
1249
|
lambda f: f.name,
|
|
1250
1250
|
filter(lambda f: f.required, structure.fields.values())
|
|
1251
1251
|
))
|
|
1252
|
-
if missing_fields := (required_fields - set(data.columns)):
|
|
1252
|
+
if missing_fields := (required_fields - set(data.columns).union(relation)):
|
|
1253
1253
|
raise RequiredFieldUnfilled(f'缺少必填字段: {missing_fields}')
|
|
1254
1254
|
|
|
1255
1255
|
if not relation:
|
|
@@ -1449,9 +1449,9 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1449
1449
|
raise ExternalObjectReadOnly('外部对象只可读')
|
|
1450
1450
|
|
|
1451
1451
|
structure = ObjectStructure(name=obj.name, structure=obj.fields.values())
|
|
1452
|
+
relation = relation or {}
|
|
1452
1453
|
self._valid_data(data, object_name, relation, structure, check_required=insert)
|
|
1453
1454
|
|
|
1454
|
-
relation = relation or {}
|
|
1455
1455
|
bkey = await self._get_bkey(obj)
|
|
1456
1456
|
if bkey not in data.columns:
|
|
1457
1457
|
raise RequiredFieldUnfilled(f'缺少业务主键[{bkey}]')
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from collections import defaultdict
|
|
3
|
+
from functools import cached_property
|
|
4
|
+
from typing import TypedDict, Literal, Type, Dict, FrozenSet
|
|
5
|
+
|
|
6
|
+
from loguru import logger
|
|
7
|
+
from kubernetes_asyncio import client, config
|
|
8
|
+
from kubernetes_asyncio.client import (
|
|
9
|
+
V1ServiceList,
|
|
10
|
+
V1Endpoints,
|
|
11
|
+
V1EndpointSubset,
|
|
12
|
+
V1EndpointAddress,
|
|
13
|
+
CoreV1EndpointPort,
|
|
14
|
+
)
|
|
15
|
+
from deepfos.lib.discovery import ServiceDiscovery
|
|
16
|
+
from deepfos import OPTION
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class K8s(ServiceDiscovery):
|
|
20
|
+
def __init__(self):
|
|
21
|
+
super().__init__()
|
|
22
|
+
self._instance_lock: Dict[str, asyncio.Lock] = defaultdict(asyncio.Lock)
|
|
23
|
+
self._server_lock = asyncio.Lock()
|
|
24
|
+
self._cares = set()
|
|
25
|
+
self._ns = OPTION.k8s.namespace
|
|
26
|
+
|
|
27
|
+
async def on_close(self):
|
|
28
|
+
self._cares.clear()
|
|
29
|
+
self.server_cache.clear()
|
|
30
|
+
self._instance_lock.clear()
|
|
31
|
+
|
|
32
|
+
async def on_startup(self):
|
|
33
|
+
config.load_incluster_config()
|
|
34
|
+
|
|
35
|
+
@cached_property
|
|
36
|
+
def _api(self):
|
|
37
|
+
return client.CoreV1Api()
|
|
38
|
+
|
|
39
|
+
async def on_interval(self):
|
|
40
|
+
await self._update_cache()
|
|
41
|
+
|
|
42
|
+
async def _update_cache(self):
|
|
43
|
+
logger.opt(lazy=True).debug(f"Update cache for instance: {self._cares}")
|
|
44
|
+
await asyncio.gather(*(
|
|
45
|
+
self.update_instance_for_service(sn)
|
|
46
|
+
for sn in self._cares
|
|
47
|
+
))
|
|
48
|
+
|
|
49
|
+
async def update_service_cache(self, server_name: str):
|
|
50
|
+
async with self._server_lock:
|
|
51
|
+
if server_name not in self.server_cache:
|
|
52
|
+
await self.update_services()
|
|
53
|
+
|
|
54
|
+
async def update_instance_cache(self, server_name):
|
|
55
|
+
self._cares.add(server_name)
|
|
56
|
+
await self.update_instance_for_service(server_name)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
async def _list_all_service_names(self) -> FrozenSet[str]:
|
|
60
|
+
svcs: V1ServiceList = await self._api.list_namespaced_service(self._ns)
|
|
61
|
+
return frozenset(svc.metadata.name for svc in svcs.items)
|
|
62
|
+
|
|
63
|
+
async def update_services(self):
|
|
64
|
+
new_services = await self._list_all_service_names()
|
|
65
|
+
cur_services = frozenset(self.server_cache.keys())
|
|
66
|
+
|
|
67
|
+
if added := new_services - cur_services:
|
|
68
|
+
for srv in added:
|
|
69
|
+
self.server_cache.__getitem__(srv)
|
|
70
|
+
logger.debug(f"Added services: {added}")
|
|
71
|
+
|
|
72
|
+
if removed := cur_services - new_services:
|
|
73
|
+
for srv in removed:
|
|
74
|
+
self.server_cache.pop(srv)
|
|
75
|
+
self._instance_lock.pop(srv, None) # noqa
|
|
76
|
+
logger.debug(f"Removed servieces: {removed}")
|
|
77
|
+
|
|
78
|
+
async def update_instance_for_service(self, server_name: str):
|
|
79
|
+
endpoints: V1Endpoints = await self._api.read_namespaced_endpoints(
|
|
80
|
+
server_name,
|
|
81
|
+
self._ns,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
no_active_nodes = True
|
|
85
|
+
async with self._instance_lock[server_name]:
|
|
86
|
+
cache = self.server_cache[server_name]
|
|
87
|
+
|
|
88
|
+
for subset in endpoints.subsets or []:
|
|
89
|
+
subset: V1EndpointSubset
|
|
90
|
+
for addr in subset.addresses or []:
|
|
91
|
+
addr: V1EndpointAddress
|
|
92
|
+
no_active_nodes = False
|
|
93
|
+
for port in subset.ports:
|
|
94
|
+
port: CoreV1EndpointPort
|
|
95
|
+
url = f"{port.name}://{addr.ip}:{port.port}"
|
|
96
|
+
cache.add(url)
|
|
97
|
+
|
|
98
|
+
if no_active_nodes:
|
|
99
|
+
logger.debug(f"{server_name} has no active endpoint, clear invalid...")
|
|
100
|
+
for item in list(cache):
|
|
101
|
+
cache.delete(item)
|
|
@@ -115,7 +115,8 @@ def _ensure_discovery_server_is_set(value):
|
|
|
115
115
|
impl = OPTION.discovery.implementation
|
|
116
116
|
server_opt = {
|
|
117
117
|
'eureka': OPTION.server.eureka,
|
|
118
|
-
'nacos': OPTION.nacos.server
|
|
118
|
+
'nacos': OPTION.nacos.server,
|
|
119
|
+
'k8s': OPTION.k8s.namespace,
|
|
119
120
|
}[impl]
|
|
120
121
|
|
|
121
122
|
if server_opt is None:
|
|
@@ -379,9 +380,9 @@ class _Category:
|
|
|
379
380
|
class _Server(_Category):
|
|
380
381
|
__id__ = 'server_url'
|
|
381
382
|
|
|
382
|
-
base = _Option('http://', val_type=str)
|
|
383
|
+
base = _Option('http://web-gateway', val_type=str)
|
|
383
384
|
app = _Option('http://app-server', val_type=str)
|
|
384
|
-
account = _Option('http://account
|
|
385
|
+
account = _Option('http://seepln-account', val_type=str)
|
|
385
386
|
system = _Option('http://system-server', val_type=str)
|
|
386
387
|
space = _Option('http://space-server', val_type=str)
|
|
387
388
|
platform_file = _Option('http://platform-file-server', val_type=str)
|
|
@@ -484,16 +485,18 @@ class _Boost(_Category):
|
|
|
484
485
|
class _ServiceDiscovery(_Category):
|
|
485
486
|
__id__ = 'service_discovery'
|
|
486
487
|
|
|
487
|
-
#:
|
|
488
|
+
#: 是否使用服务发现功能(仅影响DynamicAPI)
|
|
488
489
|
enabled = _Option(False, val_type=bool, on_set=_ensure_discovery_server_is_set)
|
|
489
490
|
#: 服务注册发现使用的实现
|
|
490
|
-
implementation = _Option('eureka', val_type=str, val_choices=('eureka', 'nacos'))
|
|
491
|
+
implementation = _Option('eureka', val_type=str, val_choices=('eureka', 'nacos', 'k8s'))
|
|
491
492
|
#: 服务注册发现使用的缓存策略
|
|
492
493
|
cache_strategy = _Option(
|
|
493
494
|
'ranked',
|
|
494
495
|
val_type=str,
|
|
495
496
|
val_choices=('ranked', 'roundrobin', 'random')
|
|
496
497
|
)
|
|
498
|
+
#: 是否完全使用服务发现获取请求地址(包括Root API)
|
|
499
|
+
take_over = _Option(False, val_type=bool)
|
|
497
500
|
|
|
498
501
|
def __get__(self, instance, owner) -> '_ServiceDiscovery':
|
|
499
502
|
"""defined to help ide"""
|
|
@@ -513,6 +516,16 @@ class _Nacos(_Category):
|
|
|
513
516
|
return super().__get__(instance, owner)
|
|
514
517
|
|
|
515
518
|
|
|
519
|
+
class _Kubernets(_Category):
|
|
520
|
+
"""Nacos 相关配置"""
|
|
521
|
+
|
|
522
|
+
namespace = _Option(None, val_type=str)
|
|
523
|
+
|
|
524
|
+
def __get__(self, instance, owner) -> '_Kubernets':
|
|
525
|
+
"""defined to help ide"""
|
|
526
|
+
return super().__get__(instance, owner)
|
|
527
|
+
|
|
528
|
+
|
|
516
529
|
# -----------------------------------------------------------------------------
|
|
517
530
|
# Options
|
|
518
531
|
class _GlobalOptions:
|
|
@@ -525,6 +538,7 @@ class _GlobalOptions:
|
|
|
525
538
|
discovery = _ServiceDiscovery()
|
|
526
539
|
nacos = _Nacos()
|
|
527
540
|
edgedb = _Edgedb()
|
|
541
|
+
k8s = _Kubernets()
|
|
528
542
|
|
|
529
543
|
def load_file(self, filepath):
|
|
530
544
|
parser = configparser.ConfigParser()
|
|
@@ -167,6 +167,7 @@ versioneer.py
|
|
|
167
167
|
./deepfos/lib/filterparser.py
|
|
168
168
|
./deepfos/lib/httpcli.py
|
|
169
169
|
./deepfos/lib/jsonstreamer.py
|
|
170
|
+
./deepfos/lib/k8s.py
|
|
170
171
|
./deepfos/lib/msg.py
|
|
171
172
|
./deepfos/lib/nacos.py
|
|
172
173
|
./deepfos/lib/patch.py
|
|
@@ -348,6 +349,7 @@ deepfos/lib/eureka.py
|
|
|
348
349
|
deepfos/lib/filterparser.py
|
|
349
350
|
deepfos/lib/httpcli.py
|
|
350
351
|
deepfos/lib/jsonstreamer.py
|
|
352
|
+
deepfos/lib/k8s.py
|
|
351
353
|
deepfos/lib/msg.py
|
|
352
354
|
deepfos/lib/nacos.py
|
|
353
355
|
deepfos/lib/patch.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|