recurvedata-lib 0.1.487__py2.py3-none-any.whl
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.
Potentially problematic release.
This version of recurvedata-lib might be problematic. Click here for more details.
- recurvedata/__init__.py +0 -0
- recurvedata/__version__.py +1 -0
- recurvedata/client/__init__.py +3 -0
- recurvedata/client/client.py +150 -0
- recurvedata/client/server_client.py +91 -0
- recurvedata/config.py +99 -0
- recurvedata/connectors/__init__.py +20 -0
- recurvedata/connectors/_register.py +46 -0
- recurvedata/connectors/base.py +111 -0
- recurvedata/connectors/config_schema.py +1575 -0
- recurvedata/connectors/connectors/__init__.py +0 -0
- recurvedata/connectors/connectors/aliyun_access_key.py +30 -0
- recurvedata/connectors/connectors/auth.py +44 -0
- recurvedata/connectors/connectors/azure_blob.py +89 -0
- recurvedata/connectors/connectors/azure_synapse.py +79 -0
- recurvedata/connectors/connectors/bigquery.py +359 -0
- recurvedata/connectors/connectors/clickhouse.py +219 -0
- recurvedata/connectors/connectors/dingtalk.py +61 -0
- recurvedata/connectors/connectors/doris.py +215 -0
- recurvedata/connectors/connectors/es.py +62 -0
- recurvedata/connectors/connectors/feishu.py +65 -0
- recurvedata/connectors/connectors/ftp.py +50 -0
- recurvedata/connectors/connectors/generic.py +49 -0
- recurvedata/connectors/connectors/google_cloud_storage.py +115 -0
- recurvedata/connectors/connectors/google_service_account.py +225 -0
- recurvedata/connectors/connectors/hive.py +207 -0
- recurvedata/connectors/connectors/impala.py +210 -0
- recurvedata/connectors/connectors/jenkins.py +51 -0
- recurvedata/connectors/connectors/mail.py +89 -0
- recurvedata/connectors/connectors/microsoft_fabric.py +284 -0
- recurvedata/connectors/connectors/mongo.py +79 -0
- recurvedata/connectors/connectors/mssql.py +131 -0
- recurvedata/connectors/connectors/mysql.py +191 -0
- recurvedata/connectors/connectors/n8n.py +141 -0
- recurvedata/connectors/connectors/oss.py +74 -0
- recurvedata/connectors/connectors/owncloud.py +36 -0
- recurvedata/connectors/connectors/phoenix.py +36 -0
- recurvedata/connectors/connectors/postgres.py +230 -0
- recurvedata/connectors/connectors/python.py +50 -0
- recurvedata/connectors/connectors/redshift.py +187 -0
- recurvedata/connectors/connectors/s3.py +93 -0
- recurvedata/connectors/connectors/sftp.py +87 -0
- recurvedata/connectors/connectors/slack.py +35 -0
- recurvedata/connectors/connectors/spark.py +99 -0
- recurvedata/connectors/connectors/starrocks.py +175 -0
- recurvedata/connectors/connectors/tencent_cos.py +40 -0
- recurvedata/connectors/connectors/tidb.py +49 -0
- recurvedata/connectors/const.py +315 -0
- recurvedata/connectors/datasource.py +189 -0
- recurvedata/connectors/dbapi.py +469 -0
- recurvedata/connectors/fs.py +66 -0
- recurvedata/connectors/ftp.py +40 -0
- recurvedata/connectors/object_store.py +60 -0
- recurvedata/connectors/pigeon.py +172 -0
- recurvedata/connectors/proxy.py +104 -0
- recurvedata/connectors/service.py +223 -0
- recurvedata/connectors/utils.py +47 -0
- recurvedata/consts.py +49 -0
- recurvedata/core/__init__.py +0 -0
- recurvedata/core/config.py +46 -0
- recurvedata/core/configurable.py +27 -0
- recurvedata/core/consts.py +2 -0
- recurvedata/core/templating.py +206 -0
- recurvedata/core/tracing.py +223 -0
- recurvedata/core/transformer.py +186 -0
- recurvedata/core/translation.py +91 -0
- recurvedata/dbt/client.py +97 -0
- recurvedata/dbt/consts.py +99 -0
- recurvedata/dbt/cosmos_utils.py +275 -0
- recurvedata/dbt/error_codes.py +18 -0
- recurvedata/dbt/schemas.py +98 -0
- recurvedata/dbt/service.py +451 -0
- recurvedata/dbt/utils.py +246 -0
- recurvedata/error_codes.py +71 -0
- recurvedata/exceptions.py +72 -0
- recurvedata/executors/__init__.py +4 -0
- recurvedata/executors/cli/__init__.py +7 -0
- recurvedata/executors/cli/connector.py +117 -0
- recurvedata/executors/cli/dbt.py +118 -0
- recurvedata/executors/cli/main.py +82 -0
- recurvedata/executors/cli/parameters.py +18 -0
- recurvedata/executors/client.py +190 -0
- recurvedata/executors/consts.py +50 -0
- recurvedata/executors/debug_executor.py +100 -0
- recurvedata/executors/executor.py +300 -0
- recurvedata/executors/link_executor.py +189 -0
- recurvedata/executors/models.py +34 -0
- recurvedata/executors/schemas.py +222 -0
- recurvedata/executors/service/__init__.py +0 -0
- recurvedata/executors/service/connector.py +380 -0
- recurvedata/executors/utils.py +172 -0
- recurvedata/filestorage/__init__.py +11 -0
- recurvedata/filestorage/_factory.py +33 -0
- recurvedata/filestorage/backends/__init__.py +0 -0
- recurvedata/filestorage/backends/fsspec.py +45 -0
- recurvedata/filestorage/backends/local.py +67 -0
- recurvedata/filestorage/backends/oss.py +56 -0
- recurvedata/filestorage/interface.py +84 -0
- recurvedata/operators/__init__.py +10 -0
- recurvedata/operators/base.py +28 -0
- recurvedata/operators/config.py +21 -0
- recurvedata/operators/context.py +255 -0
- recurvedata/operators/dbt_operator/__init__.py +2 -0
- recurvedata/operators/dbt_operator/model_pipeline_link_operator.py +55 -0
- recurvedata/operators/dbt_operator/operator.py +353 -0
- recurvedata/operators/link_operator/__init__.py +1 -0
- recurvedata/operators/link_operator/operator.py +120 -0
- recurvedata/operators/models.py +55 -0
- recurvedata/operators/notify_operator/__init__.py +1 -0
- recurvedata/operators/notify_operator/operator.py +180 -0
- recurvedata/operators/operator.py +119 -0
- recurvedata/operators/python_operator/__init__.py +1 -0
- recurvedata/operators/python_operator/operator.py +132 -0
- recurvedata/operators/sensor_operator/__init__.py +1 -0
- recurvedata/operators/sensor_operator/airflow_utils.py +63 -0
- recurvedata/operators/sensor_operator/operator.py +172 -0
- recurvedata/operators/spark_operator/__init__.py +1 -0
- recurvedata/operators/spark_operator/operator.py +200 -0
- recurvedata/operators/spark_operator/spark_sample.py +47 -0
- recurvedata/operators/sql_operator/__init__.py +1 -0
- recurvedata/operators/sql_operator/operator.py +90 -0
- recurvedata/operators/task.py +211 -0
- recurvedata/operators/transfer_operator/__init__.py +40 -0
- recurvedata/operators/transfer_operator/const.py +10 -0
- recurvedata/operators/transfer_operator/dump_aliyun_sls.py +82 -0
- recurvedata/operators/transfer_operator/dump_sheet_task_base.py +292 -0
- recurvedata/operators/transfer_operator/dump_task_cass.py +155 -0
- recurvedata/operators/transfer_operator/dump_task_dbapi.py +209 -0
- recurvedata/operators/transfer_operator/dump_task_es.py +113 -0
- recurvedata/operators/transfer_operator/dump_task_feishu_sheet.py +114 -0
- recurvedata/operators/transfer_operator/dump_task_ftp.py +234 -0
- recurvedata/operators/transfer_operator/dump_task_google_sheet.py +66 -0
- recurvedata/operators/transfer_operator/dump_task_mongodb.py +168 -0
- recurvedata/operators/transfer_operator/dump_task_oss.py +285 -0
- recurvedata/operators/transfer_operator/dump_task_python.py +212 -0
- recurvedata/operators/transfer_operator/dump_task_s3.py +270 -0
- recurvedata/operators/transfer_operator/dump_task_sftp.py +229 -0
- recurvedata/operators/transfer_operator/load_task_aliyun_oss.py +107 -0
- recurvedata/operators/transfer_operator/load_task_azure_blob.py +115 -0
- recurvedata/operators/transfer_operator/load_task_azure_synapse.py +90 -0
- recurvedata/operators/transfer_operator/load_task_clickhouse.py +167 -0
- recurvedata/operators/transfer_operator/load_task_doris.py +164 -0
- recurvedata/operators/transfer_operator/load_task_email.py +188 -0
- recurvedata/operators/transfer_operator/load_task_es.py +86 -0
- recurvedata/operators/transfer_operator/load_task_filebrowser.py +151 -0
- recurvedata/operators/transfer_operator/load_task_ftp.py +19 -0
- recurvedata/operators/transfer_operator/load_task_google_bigquery.py +90 -0
- recurvedata/operators/transfer_operator/load_task_google_cloud_storage.py +127 -0
- recurvedata/operators/transfer_operator/load_task_google_sheet.py +130 -0
- recurvedata/operators/transfer_operator/load_task_hive.py +158 -0
- recurvedata/operators/transfer_operator/load_task_microsoft_fabric.py +105 -0
- recurvedata/operators/transfer_operator/load_task_mssql.py +153 -0
- recurvedata/operators/transfer_operator/load_task_mysql.py +157 -0
- recurvedata/operators/transfer_operator/load_task_owncloud.py +135 -0
- recurvedata/operators/transfer_operator/load_task_postgresql.py +109 -0
- recurvedata/operators/transfer_operator/load_task_qcloud_cos.py +119 -0
- recurvedata/operators/transfer_operator/load_task_recurve_data_prep.py +75 -0
- recurvedata/operators/transfer_operator/load_task_redshift.py +95 -0
- recurvedata/operators/transfer_operator/load_task_s3.py +150 -0
- recurvedata/operators/transfer_operator/load_task_sftp.py +90 -0
- recurvedata/operators/transfer_operator/load_task_starrocks.py +169 -0
- recurvedata/operators/transfer_operator/load_task_yicrowds.py +97 -0
- recurvedata/operators/transfer_operator/mixin.py +31 -0
- recurvedata/operators/transfer_operator/operator.py +231 -0
- recurvedata/operators/transfer_operator/task.py +223 -0
- recurvedata/operators/transfer_operator/utils.py +134 -0
- recurvedata/operators/ui.py +80 -0
- recurvedata/operators/utils/__init__.py +51 -0
- recurvedata/operators/utils/file_factory.py +150 -0
- recurvedata/operators/utils/fs.py +10 -0
- recurvedata/operators/utils/lineage.py +265 -0
- recurvedata/operators/web_init.py +15 -0
- recurvedata/pigeon/connector/__init__.py +294 -0
- recurvedata/pigeon/connector/_registry.py +17 -0
- recurvedata/pigeon/connector/aliyun_oss.py +80 -0
- recurvedata/pigeon/connector/awss3.py +123 -0
- recurvedata/pigeon/connector/azure_blob.py +176 -0
- recurvedata/pigeon/connector/azure_synapse.py +51 -0
- recurvedata/pigeon/connector/cass.py +151 -0
- recurvedata/pigeon/connector/clickhouse.py +403 -0
- recurvedata/pigeon/connector/clickhouse_native.py +351 -0
- recurvedata/pigeon/connector/dbapi.py +571 -0
- recurvedata/pigeon/connector/doris.py +166 -0
- recurvedata/pigeon/connector/es.py +176 -0
- recurvedata/pigeon/connector/feishu.py +1135 -0
- recurvedata/pigeon/connector/ftp.py +163 -0
- recurvedata/pigeon/connector/google_bigquery.py +283 -0
- recurvedata/pigeon/connector/google_cloud_storage.py +130 -0
- recurvedata/pigeon/connector/hbase_phoenix.py +108 -0
- recurvedata/pigeon/connector/hdfs.py +204 -0
- recurvedata/pigeon/connector/hive_impala.py +383 -0
- recurvedata/pigeon/connector/microsoft_fabric.py +95 -0
- recurvedata/pigeon/connector/mongodb.py +56 -0
- recurvedata/pigeon/connector/mssql.py +467 -0
- recurvedata/pigeon/connector/mysql.py +175 -0
- recurvedata/pigeon/connector/owncloud.py +92 -0
- recurvedata/pigeon/connector/postgresql.py +267 -0
- recurvedata/pigeon/connector/power_bi.py +179 -0
- recurvedata/pigeon/connector/qcloud_cos.py +79 -0
- recurvedata/pigeon/connector/redshift.py +123 -0
- recurvedata/pigeon/connector/sftp.py +73 -0
- recurvedata/pigeon/connector/sqlite.py +42 -0
- recurvedata/pigeon/connector/starrocks.py +144 -0
- recurvedata/pigeon/connector/tableau.py +162 -0
- recurvedata/pigeon/const.py +21 -0
- recurvedata/pigeon/csv.py +172 -0
- recurvedata/pigeon/docs/datasources-example.json +82 -0
- recurvedata/pigeon/docs/images/pigeon_design.png +0 -0
- recurvedata/pigeon/docs/lightweight-data-sync-solution.md +111 -0
- recurvedata/pigeon/dumper/__init__.py +171 -0
- recurvedata/pigeon/dumper/aliyun_sls.py +415 -0
- recurvedata/pigeon/dumper/base.py +141 -0
- recurvedata/pigeon/dumper/cass.py +213 -0
- recurvedata/pigeon/dumper/dbapi.py +346 -0
- recurvedata/pigeon/dumper/es.py +112 -0
- recurvedata/pigeon/dumper/ftp.py +64 -0
- recurvedata/pigeon/dumper/mongodb.py +103 -0
- recurvedata/pigeon/handler/__init__.py +4 -0
- recurvedata/pigeon/handler/base.py +153 -0
- recurvedata/pigeon/handler/csv_handler.py +290 -0
- recurvedata/pigeon/loader/__init__.py +87 -0
- recurvedata/pigeon/loader/base.py +83 -0
- recurvedata/pigeon/loader/csv_to_azure_synapse.py +214 -0
- recurvedata/pigeon/loader/csv_to_clickhouse.py +152 -0
- recurvedata/pigeon/loader/csv_to_doris.py +215 -0
- recurvedata/pigeon/loader/csv_to_es.py +51 -0
- recurvedata/pigeon/loader/csv_to_google_bigquery.py +169 -0
- recurvedata/pigeon/loader/csv_to_hive.py +468 -0
- recurvedata/pigeon/loader/csv_to_microsoft_fabric.py +242 -0
- recurvedata/pigeon/loader/csv_to_mssql.py +174 -0
- recurvedata/pigeon/loader/csv_to_mysql.py +180 -0
- recurvedata/pigeon/loader/csv_to_postgresql.py +248 -0
- recurvedata/pigeon/loader/csv_to_redshift.py +240 -0
- recurvedata/pigeon/loader/csv_to_starrocks.py +233 -0
- recurvedata/pigeon/meta.py +116 -0
- recurvedata/pigeon/row_factory.py +42 -0
- recurvedata/pigeon/schema/__init__.py +124 -0
- recurvedata/pigeon/schema/types.py +13 -0
- recurvedata/pigeon/sync.py +283 -0
- recurvedata/pigeon/transformer.py +146 -0
- recurvedata/pigeon/utils/__init__.py +134 -0
- recurvedata/pigeon/utils/bloomfilter.py +181 -0
- recurvedata/pigeon/utils/date_time.py +323 -0
- recurvedata/pigeon/utils/escape.py +15 -0
- recurvedata/pigeon/utils/fs.py +266 -0
- recurvedata/pigeon/utils/json.py +44 -0
- recurvedata/pigeon/utils/keyed_tuple.py +85 -0
- recurvedata/pigeon/utils/mp.py +156 -0
- recurvedata/pigeon/utils/sql.py +328 -0
- recurvedata/pigeon/utils/timing.py +155 -0
- recurvedata/provider_manager.py +0 -0
- recurvedata/providers/__init__.py +0 -0
- recurvedata/providers/dbapi/__init__.py +0 -0
- recurvedata/providers/flywheel/__init__.py +0 -0
- recurvedata/providers/mysql/__init__.py +0 -0
- recurvedata/schedulers/__init__.py +1 -0
- recurvedata/schedulers/airflow.py +974 -0
- recurvedata/schedulers/airflow_db_process.py +331 -0
- recurvedata/schedulers/airflow_operators.py +61 -0
- recurvedata/schedulers/airflow_plugin.py +9 -0
- recurvedata/schedulers/airflow_trigger_dag_patch.py +117 -0
- recurvedata/schedulers/base.py +99 -0
- recurvedata/schedulers/cli.py +228 -0
- recurvedata/schedulers/client.py +56 -0
- recurvedata/schedulers/consts.py +52 -0
- recurvedata/schedulers/debug_celery.py +62 -0
- recurvedata/schedulers/model.py +63 -0
- recurvedata/schedulers/schemas.py +97 -0
- recurvedata/schedulers/service.py +20 -0
- recurvedata/schedulers/system_dags.py +59 -0
- recurvedata/schedulers/task_status.py +279 -0
- recurvedata/schedulers/utils.py +73 -0
- recurvedata/schema/__init__.py +0 -0
- recurvedata/schema/field.py +88 -0
- recurvedata/schema/schema.py +55 -0
- recurvedata/schema/types.py +17 -0
- recurvedata/schema.py +0 -0
- recurvedata/server/__init__.py +0 -0
- recurvedata/server/app.py +7 -0
- recurvedata/server/connector/__init__.py +0 -0
- recurvedata/server/connector/api.py +79 -0
- recurvedata/server/connector/schemas.py +28 -0
- recurvedata/server/data_service/__init__.py +0 -0
- recurvedata/server/data_service/api.py +126 -0
- recurvedata/server/data_service/client.py +18 -0
- recurvedata/server/data_service/consts.py +1 -0
- recurvedata/server/data_service/schemas.py +68 -0
- recurvedata/server/data_service/service.py +218 -0
- recurvedata/server/dbt/__init__.py +0 -0
- recurvedata/server/dbt/api.py +116 -0
- recurvedata/server/error_code.py +49 -0
- recurvedata/server/exceptions.py +19 -0
- recurvedata/server/executor/__init__.py +0 -0
- recurvedata/server/executor/api.py +37 -0
- recurvedata/server/executor/schemas.py +30 -0
- recurvedata/server/executor/service.py +220 -0
- recurvedata/server/main.py +32 -0
- recurvedata/server/schedulers/__init__.py +0 -0
- recurvedata/server/schedulers/api.py +252 -0
- recurvedata/server/schedulers/schemas.py +50 -0
- recurvedata/server/schemas.py +50 -0
- recurvedata/utils/__init__.py +15 -0
- recurvedata/utils/_typer.py +61 -0
- recurvedata/utils/attrdict.py +19 -0
- recurvedata/utils/command_helper.py +20 -0
- recurvedata/utils/compat.py +12 -0
- recurvedata/utils/compression.py +203 -0
- recurvedata/utils/crontab.py +42 -0
- recurvedata/utils/crypto_util.py +305 -0
- recurvedata/utils/dataclass.py +11 -0
- recurvedata/utils/date_time.py +464 -0
- recurvedata/utils/dispatch.py +114 -0
- recurvedata/utils/email_util.py +104 -0
- recurvedata/utils/files.py +386 -0
- recurvedata/utils/helpers.py +170 -0
- recurvedata/utils/httputil.py +117 -0
- recurvedata/utils/imports.py +132 -0
- recurvedata/utils/json.py +80 -0
- recurvedata/utils/log.py +117 -0
- recurvedata/utils/log_capture.py +153 -0
- recurvedata/utils/mp.py +178 -0
- recurvedata/utils/normalizer.py +102 -0
- recurvedata/utils/redis_lock.py +474 -0
- recurvedata/utils/registry.py +54 -0
- recurvedata/utils/shell.py +15 -0
- recurvedata/utils/singleton.py +33 -0
- recurvedata/utils/sql.py +6 -0
- recurvedata/utils/timeout.py +28 -0
- recurvedata/utils/tracing.py +14 -0
- recurvedata_lib-0.1.487.dist-info/METADATA +605 -0
- recurvedata_lib-0.1.487.dist-info/RECORD +333 -0
- recurvedata_lib-0.1.487.dist-info/WHEEL +5 -0
- recurvedata_lib-0.1.487.dist-info/entry_points.txt +6 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
try:
|
|
2
|
+
from recurvedata.pigeon.loader.csv_to_mysql import CSVToMySQLLoader
|
|
3
|
+
except ImportError:
|
|
4
|
+
pass
|
|
5
|
+
|
|
6
|
+
from recurvedata.core.translation import _l
|
|
7
|
+
from recurvedata.operators.transfer_operator import const
|
|
8
|
+
from recurvedata.operators.transfer_operator.task import LoadTask
|
|
9
|
+
from recurvedata.operators.transfer_operator.utils import allowed_modes
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MySQLLoadTask(LoadTask):
|
|
13
|
+
ds_name_fields = ("mysql_data_source_name",)
|
|
14
|
+
ds_types = ("mysql", "tidb")
|
|
15
|
+
worker_install_require = [
|
|
16
|
+
"pigeon[mysql]",
|
|
17
|
+
]
|
|
18
|
+
default_dumper_handler_options = {
|
|
19
|
+
"null": r"\N",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
def execute_impl(self, *args, **kwargs):
|
|
23
|
+
mysql_ds = self.must_get_connection_by_name(self.config["mysql_data_source_name"])
|
|
24
|
+
load_options = self.rendered_config.copy()
|
|
25
|
+
for k in ["mysql_data_source_name"]:
|
|
26
|
+
load_options.pop(k, None)
|
|
27
|
+
load_options.update(
|
|
28
|
+
{
|
|
29
|
+
"filename": self.filename,
|
|
30
|
+
"connector": mysql_ds.connector,
|
|
31
|
+
"delete_file": True,
|
|
32
|
+
"database": mysql_ds.database,
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
loader = CSVToMySQLLoader(**load_options)
|
|
36
|
+
return loader.execute()
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def config_schema(cls):
|
|
40
|
+
# get_choices_by_type = cls.get_connection_names_by_type
|
|
41
|
+
# dss = get_choices_by_type(cls.ds_types)
|
|
42
|
+
|
|
43
|
+
schema = {
|
|
44
|
+
"type": "object",
|
|
45
|
+
"properties": {
|
|
46
|
+
"mysql_data_source_name": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"title": _l("MySQL Connection"),
|
|
49
|
+
"ui:field": "ProjectConnectionSelectorField",
|
|
50
|
+
"ui:options": {
|
|
51
|
+
"supportTypes": cls.ds_types,
|
|
52
|
+
},
|
|
53
|
+
# 'default': cls.first_or_default(dss),
|
|
54
|
+
},
|
|
55
|
+
# "database": {
|
|
56
|
+
# "type": "string",
|
|
57
|
+
# "title": "Database",
|
|
58
|
+
# "ui:field": "CodeEditorWithReferencesField",
|
|
59
|
+
# "ui:options": {
|
|
60
|
+
# "type": "plain",
|
|
61
|
+
# },
|
|
62
|
+
# },
|
|
63
|
+
"table": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"title": _l("Target Table"),
|
|
66
|
+
"description": _l("Name of the table to load data into"),
|
|
67
|
+
"ui:field": "CodeEditorWithReferencesField",
|
|
68
|
+
"ui:options": {
|
|
69
|
+
"type": "plain",
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
"create_table_ddl": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"title": _l("Table Creation SQL"),
|
|
75
|
+
"description": _l("SQL statement to create the target table if it doesn't exist"),
|
|
76
|
+
"ui:field": "CodeEditorWithReferencesField",
|
|
77
|
+
"ui:options": {
|
|
78
|
+
"type": "code",
|
|
79
|
+
"lang": "sql",
|
|
80
|
+
"sqlLang": "mysql",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
"mode": {
|
|
84
|
+
"type": "string",
|
|
85
|
+
"title": _l("Load Mode"),
|
|
86
|
+
"description": _l("How to handle existing data in the target table"),
|
|
87
|
+
"enum": list(allowed_modes),
|
|
88
|
+
"default": const.LOAD_OVERWRITE,
|
|
89
|
+
},
|
|
90
|
+
"primary_keys": {
|
|
91
|
+
"ui:hidden": '{{parentFormData.mode !== "MERGE"}}',
|
|
92
|
+
"type": "string",
|
|
93
|
+
"title": _l("Primary Keys"),
|
|
94
|
+
"description": _l(
|
|
95
|
+
"Comma-separated list of columns used for deduplication in MERGE mode. "
|
|
96
|
+
"Should be primary or unique key columns."
|
|
97
|
+
),
|
|
98
|
+
"ui:field": "CodeEditorWithReferencesField",
|
|
99
|
+
"ui:options": {
|
|
100
|
+
"type": "plain",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
"using_insert": {
|
|
104
|
+
"type": "boolean",
|
|
105
|
+
"title": _l("Use INSERT Statements"),
|
|
106
|
+
"default": False,
|
|
107
|
+
"description": _l(
|
|
108
|
+
"If disabled (default), uses fast bulk loading via `LOAD DATA LOCAL INFILE`. "
|
|
109
|
+
"If enabled, uses standard `INSERT` statements instead."
|
|
110
|
+
),
|
|
111
|
+
},
|
|
112
|
+
"insert_batch_size": {
|
|
113
|
+
"ui:hidden": "{{!parentFormData.using_insert}}",
|
|
114
|
+
"type": "number",
|
|
115
|
+
"ui:options": {"controls": False},
|
|
116
|
+
"title": _l("Batch Size"),
|
|
117
|
+
"default": 1000,
|
|
118
|
+
"minimum": 1,
|
|
119
|
+
"maximum": 2000,
|
|
120
|
+
"description": _l("Number of rows to insert in each batch"),
|
|
121
|
+
},
|
|
122
|
+
"insert_concurrency": {
|
|
123
|
+
"ui:hidden": "{{!parentFormData.using_insert}}",
|
|
124
|
+
"type": "number",
|
|
125
|
+
"ui:options": {"controls": False},
|
|
126
|
+
"title": _l("Concurrent Inserts"),
|
|
127
|
+
"default": 1,
|
|
128
|
+
"minimum": 1,
|
|
129
|
+
"maximum": 10,
|
|
130
|
+
"description": _l("Number of parallel insert operations"),
|
|
131
|
+
},
|
|
132
|
+
# "pre_queries": {
|
|
133
|
+
# "type": "string",
|
|
134
|
+
# "title": "Queries Ran Before Loading",
|
|
135
|
+
# "description": '新数据导入前运行的 SQL,多条 SQL 用 `;` 分隔;支持传入变量,详见 <a target="_blank" href="http://bit.ly/2JMutjn">文档</a>',
|
|
136
|
+
# "ui:field": "CodeEditorWithReferencesField",
|
|
137
|
+
# "ui:options": {
|
|
138
|
+
# "type": "code",
|
|
139
|
+
# "lang": "sql",
|
|
140
|
+
# "sqlLang": "mysql",
|
|
141
|
+
# },
|
|
142
|
+
# },
|
|
143
|
+
# "post_queries": {
|
|
144
|
+
# "type": "string",
|
|
145
|
+
# "title": "Queries Ran After Loading",
|
|
146
|
+
# "description": '新数据导入后运行的 SQL,多条 SQL 用 `;` 分隔;支持传入变量,详见 <a target="_blank" href="http://bit.ly/2JMutjn">文档</a>',
|
|
147
|
+
# "ui:field": "CodeEditorWithReferencesField",
|
|
148
|
+
# "ui:options": {
|
|
149
|
+
# "type": "code",
|
|
150
|
+
# "lang": "sql",
|
|
151
|
+
# "sqlLang": "mysql",
|
|
152
|
+
# },
|
|
153
|
+
# },
|
|
154
|
+
},
|
|
155
|
+
"required": ["mysql_data_source_name", "table"],
|
|
156
|
+
}
|
|
157
|
+
return schema
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
import owncloud
|
|
5
|
+
except ImportError:
|
|
6
|
+
pass
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
from recurvedata.core.translation import _l
|
|
10
|
+
from recurvedata.operators.transfer_operator.task import LoadTask
|
|
11
|
+
from recurvedata.pigeon.utils import fs, trim_suffix
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class OwnCloudLoadTask(LoadTask):
|
|
17
|
+
ds_name_fields = ("data_source_name",)
|
|
18
|
+
ds_types = ("owncloud",)
|
|
19
|
+
should_write_header = True
|
|
20
|
+
worker_install_require = [
|
|
21
|
+
"pyocclient>=0.6",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
def execute_impl(self, *args, **kwargs):
|
|
25
|
+
conf = self.rendered_config
|
|
26
|
+
ds = self.must_get_connection_by_name(conf["data_source_name"])
|
|
27
|
+
file_to_upload = self.filename
|
|
28
|
+
remote_filename = conf["filename"]
|
|
29
|
+
|
|
30
|
+
cm = conf["compress_method"]
|
|
31
|
+
if cm != "None":
|
|
32
|
+
logger.info("compressing file using %s...", cm)
|
|
33
|
+
if cm == "Gzip":
|
|
34
|
+
ext = ".gz"
|
|
35
|
+
file_to_upload = fs.gzip_compress(self.filename, using_cmd=True)
|
|
36
|
+
elif cm == "Zip":
|
|
37
|
+
ext = ".zip"
|
|
38
|
+
arcname = trim_suffix(os.path.basename(remote_filename), ext)
|
|
39
|
+
file_to_upload = fs.zip_compress(self.filename, using_cmd=False, arcname=arcname)
|
|
40
|
+
else:
|
|
41
|
+
# won't reach here
|
|
42
|
+
raise ValueError(f"compress method {cm} is not supported")
|
|
43
|
+
|
|
44
|
+
if not remote_filename.endswith(ext):
|
|
45
|
+
remote_filename = f"{remote_filename}{ext}"
|
|
46
|
+
|
|
47
|
+
client = OwnCloudClient(ds.host, ds.user, ds.password)
|
|
48
|
+
|
|
49
|
+
remote_fold = conf["directory"]
|
|
50
|
+
remote_filename = os.path.join(conf["directory"], remote_filename)
|
|
51
|
+
logger.info("uploading %s to %s", file_to_upload, remote_filename)
|
|
52
|
+
client.upload(file_to_upload, remote_fold, remote_filename)
|
|
53
|
+
fs.remove_files_safely([self.filename, file_to_upload])
|
|
54
|
+
logger.info(f"remove {self.filename} local_file: {file_to_upload} success!")
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def config_schema(cls):
|
|
58
|
+
schema = {
|
|
59
|
+
"type": "object",
|
|
60
|
+
"properties": {
|
|
61
|
+
"data_source_name": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"title": _l("OwnCloud Connection"),
|
|
64
|
+
"ui:field": "ProjectConnectionSelectorField",
|
|
65
|
+
"ui:options": {
|
|
66
|
+
"supportTypes": cls.ds_types,
|
|
67
|
+
},
|
|
68
|
+
# 'default': cls.first_or_default(dss, ''),
|
|
69
|
+
},
|
|
70
|
+
"directory": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"title": _l("Target Directory"),
|
|
73
|
+
"description": _l("Target directory to upload files to"),
|
|
74
|
+
"ui:field": "CodeEditorWithReferencesField",
|
|
75
|
+
"ui:options": {
|
|
76
|
+
"type": "plain",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
"filename": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"title": _l("Filename"),
|
|
82
|
+
"description": _l("Uploaded file name, supports template variables"),
|
|
83
|
+
"ui:field": "CodeEditorWithReferencesField",
|
|
84
|
+
"ui:options": {
|
|
85
|
+
"type": "plain",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
"compress_method": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"title": _l("Compression Method"),
|
|
91
|
+
"description": _l("Compress file before uploading using specified method"),
|
|
92
|
+
"enum": ["None", "Gzip", "Zip"],
|
|
93
|
+
"enumNames": ["None", "Gzip", "Zip"],
|
|
94
|
+
"default": "None",
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
"required": ["data_source_name", "directory", "filename", "compress_method"],
|
|
98
|
+
}
|
|
99
|
+
return schema
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class OwnCloudClient(object):
|
|
103
|
+
# ownCloud没有提供API关闭客户端,只需要停止与ownCloud服务器交互,Python脚本就会自动关闭连接。
|
|
104
|
+
def __init__(self, host, username, password):
|
|
105
|
+
self.host = host
|
|
106
|
+
self.username = username
|
|
107
|
+
self.password = password
|
|
108
|
+
self.oc = self.login()
|
|
109
|
+
|
|
110
|
+
def login(self):
|
|
111
|
+
try:
|
|
112
|
+
owncloud_client = owncloud.Client(self.host)
|
|
113
|
+
owncloud_client.login(self.username, self.password)
|
|
114
|
+
logger.info("login owncloud success.")
|
|
115
|
+
except Exception as e:
|
|
116
|
+
logger.info("login owncloud failed. http error is: {}".format(e))
|
|
117
|
+
return owncloud_client
|
|
118
|
+
|
|
119
|
+
def create_owncloud_fold(self, fold):
|
|
120
|
+
try:
|
|
121
|
+
self.oc.file_info(fold)
|
|
122
|
+
logger.info("fold {} is exists.".format(fold))
|
|
123
|
+
except Exception as e:
|
|
124
|
+
logger.info("{} does not exists, start creating the folder. error is: {}".format(fold, e))
|
|
125
|
+
self.oc.mkdir(fold)
|
|
126
|
+
logger.info("create {} success.".format(fold))
|
|
127
|
+
|
|
128
|
+
def upload(self, local_filename, remote_fold, remote_filename):
|
|
129
|
+
self.create_owncloud_fold(remote_fold)
|
|
130
|
+
logger.info("start put {} to {}.".format(local_filename, remote_filename))
|
|
131
|
+
try:
|
|
132
|
+
self.oc.put_file(remote_path=remote_filename, local_source_file=local_filename)
|
|
133
|
+
logger.info("upload {} success.".format(remote_filename))
|
|
134
|
+
except Exception as e:
|
|
135
|
+
logger.info("upload {} failed. http error is: {}".format(remote_filename, e))
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
from recurvedata.pigeon.loader.csv_to_postgresql import CSVToPostgresqlLoader
|
|
5
|
+
except ImportError:
|
|
6
|
+
pass
|
|
7
|
+
|
|
8
|
+
from recurvedata.core.translation import _l
|
|
9
|
+
from recurvedata.operators.transfer_operator import utils
|
|
10
|
+
from recurvedata.operators.transfer_operator.task import LoadTask
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PostgresqlLoadTask(LoadTask):
|
|
14
|
+
ds_name_fields = ("data_source_name",)
|
|
15
|
+
ds_types = ("postgres",)
|
|
16
|
+
worker_install_require = ["pigeon[postgres]"]
|
|
17
|
+
|
|
18
|
+
def execute_impl(self, *args, **kwargs):
|
|
19
|
+
ds = self.must_get_connection_by_name(self.config["data_source_name"])
|
|
20
|
+
load_options = self.rendered_config.copy()
|
|
21
|
+
for k in ["data_source_name"]:
|
|
22
|
+
load_options.pop(k, None)
|
|
23
|
+
load_options.setdefault("database", ds.database)
|
|
24
|
+
load_options.update(
|
|
25
|
+
{
|
|
26
|
+
"filename": self.filename,
|
|
27
|
+
"connector": ds.connector,
|
|
28
|
+
"delete_file": True,
|
|
29
|
+
"database": ds.database,
|
|
30
|
+
"schema": ds.data.get("schema"),
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
loader = CSVToPostgresqlLoader(**load_options)
|
|
34
|
+
return loader.execute()
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def config_schema(cls):
|
|
38
|
+
# get_choices_by_type = cls.get_connection_names_by_type
|
|
39
|
+
# dss = get_choices_by_type(cls.ds_types)
|
|
40
|
+
|
|
41
|
+
schema = {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"properties": {
|
|
44
|
+
"data_source_name": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"title": _l("PostgreSQL Connection"),
|
|
47
|
+
"ui:field": "ProjectConnectionSelectorField",
|
|
48
|
+
"ui:options": {
|
|
49
|
+
"supportTypes": cls.ds_types,
|
|
50
|
+
},
|
|
51
|
+
# 'default': cls.first_or_default(dss),
|
|
52
|
+
},
|
|
53
|
+
# "database": {
|
|
54
|
+
# "type": "string",
|
|
55
|
+
# "title": "Database",
|
|
56
|
+
# "ui:field": "CodeEditorWithReferencesField",
|
|
57
|
+
# "ui:options": {
|
|
58
|
+
# "type": "plain",
|
|
59
|
+
# },
|
|
60
|
+
# },
|
|
61
|
+
"table": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"title": _l("Target Table"),
|
|
64
|
+
"description": _l("Name of the table to load data into"),
|
|
65
|
+
"ui:field": "CodeEditorWithReferencesField",
|
|
66
|
+
"ui:options": {
|
|
67
|
+
"type": "plain",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
"create_table_ddl": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"title": _l("Create Table DDL"),
|
|
73
|
+
"description": _l("SQL statement to create the target table if it doesn't exist"),
|
|
74
|
+
"ui:field": "CodeEditorWithReferencesField",
|
|
75
|
+
"ui:options": {
|
|
76
|
+
"type": "code",
|
|
77
|
+
"lang": "sql",
|
|
78
|
+
"sqlLang": "postgresql",
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
# 'using_insert': {
|
|
82
|
+
# 'type': 'boolean',
|
|
83
|
+
# 'title': 'Using INSERT',
|
|
84
|
+
# 'default': False,
|
|
85
|
+
# 'description': '默认使用 `LOAD DATA LOCAL INFILE` 导入数据,也可以选择使用 INSERT 语句'
|
|
86
|
+
# },
|
|
87
|
+
"insert_batch_size": {
|
|
88
|
+
"type": "number",
|
|
89
|
+
"ui:options": {"controls": False},
|
|
90
|
+
"title": _l("Batch Size"),
|
|
91
|
+
"default": 1000,
|
|
92
|
+
"minimum": 1,
|
|
93
|
+
"maximum": 20000,
|
|
94
|
+
"description": _l("Number of rows inserted in each batch"),
|
|
95
|
+
},
|
|
96
|
+
"insert_concurrency": {
|
|
97
|
+
"type": "number",
|
|
98
|
+
"ui:options": {"controls": False},
|
|
99
|
+
"title": _l("Concurrent Inserts"),
|
|
100
|
+
"default": 1,
|
|
101
|
+
"minimum": 1,
|
|
102
|
+
"maximum": 20,
|
|
103
|
+
"description": _l("Number of parallel insert operations"),
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
"required": ["data_source_name", "table"],
|
|
107
|
+
}
|
|
108
|
+
schema["properties"].update(copy.deepcopy(utils.LOAD_COMMON))
|
|
109
|
+
return schema
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from recurvedata.pigeon.connector.qcloud_cos import COSConnector
|
|
6
|
+
except ImportError:
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
from recurvedata.core.translation import _l
|
|
10
|
+
from recurvedata.operators.transfer_operator.task import LoadTask
|
|
11
|
+
from recurvedata.utils import extract_dict
|
|
12
|
+
from recurvedata.utils.files import is_file_empty, remove_files_safely
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TencentCOSLoadTask(LoadTask):
|
|
18
|
+
ds_name_fields = ("data_source_name",)
|
|
19
|
+
ds_types = ("cos",)
|
|
20
|
+
should_write_header = True
|
|
21
|
+
worker_install_require = ["pigeon[qcloud]"]
|
|
22
|
+
|
|
23
|
+
def execute_impl(self, *args, **kwargs):
|
|
24
|
+
if is_file_empty(self.filename):
|
|
25
|
+
logger.warning("file %s not exists or has no content, skip.", self.filename)
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
ds = self.must_get_connection_by_name(self.config["data_source_name"])
|
|
29
|
+
|
|
30
|
+
load_options = self.rendered_config.copy()
|
|
31
|
+
ds_extra_bucket = ds.extra.get("bucket")
|
|
32
|
+
config_bucket = load_options.get("bucket_name")
|
|
33
|
+
bucket_upload = config_bucket if config_bucket else ds_extra_bucket
|
|
34
|
+
|
|
35
|
+
opt_keys = ["secret_id", "secret_key", "region", "endpoint", "proxies"]
|
|
36
|
+
cos = COSConnector(**extract_dict(ds.extra, opt_keys))
|
|
37
|
+
|
|
38
|
+
compress_mode = load_options["compress_mode"]
|
|
39
|
+
if compress_mode != "None" and not load_options["key"].endswith(("/",)):
|
|
40
|
+
target_filename = os.path.join(os.path.dirname(self.filename), os.path.basename(load_options["key"]))
|
|
41
|
+
else:
|
|
42
|
+
target_filename = None
|
|
43
|
+
file_upload, ext = self.compress_file(
|
|
44
|
+
filename=self.filename, target_filename=target_filename, compress_mode=compress_mode
|
|
45
|
+
)
|
|
46
|
+
if compress_mode != "None" and not load_options["key"].endswith(("/", ext)):
|
|
47
|
+
load_options["key"] = f"{load_options['key']}{ext}"
|
|
48
|
+
|
|
49
|
+
upload_conf = {
|
|
50
|
+
"bucket_name": bucket_upload,
|
|
51
|
+
"filename": file_upload,
|
|
52
|
+
"overwrite": load_options["overwrite"],
|
|
53
|
+
}
|
|
54
|
+
if load_options["key"].endswith("/"):
|
|
55
|
+
upload_conf.update({"folder": load_options["key"]})
|
|
56
|
+
elif load_options["key"]:
|
|
57
|
+
upload_conf.update({"key": load_options["key"]})
|
|
58
|
+
else:
|
|
59
|
+
upload_conf.update({"key": os.path.basename(file_upload)})
|
|
60
|
+
|
|
61
|
+
logger.info("uploading...")
|
|
62
|
+
cos.upload(**upload_conf)
|
|
63
|
+
return remove_files_safely([self.filename, file_upload])
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def config_schema(cls):
|
|
67
|
+
# get_choices_by_type = cls.get_connection_names_by_type
|
|
68
|
+
# dss = get_choices_by_type(cls.ds_types)
|
|
69
|
+
schema = {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {
|
|
72
|
+
"data_source_name": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"title": _l("Tencent COS Connection"),
|
|
75
|
+
"ui:field": "ProjectConnectionSelectorField",
|
|
76
|
+
"ui:options": {
|
|
77
|
+
"supportTypes": cls.ds_types,
|
|
78
|
+
},
|
|
79
|
+
# 'default': cls.first_or_default(dss, ''),
|
|
80
|
+
},
|
|
81
|
+
"bucket_name": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"title": _l("Bucket"),
|
|
84
|
+
"description": _l("Bucket name, required if not set in data source"),
|
|
85
|
+
"ui:field": "CodeEditorWithReferencesField",
|
|
86
|
+
"ui:options": {
|
|
87
|
+
"type": "plain",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
"key": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"title": _l("Upload Path"),
|
|
93
|
+
"description": _l(
|
|
94
|
+
"Target path in the bucket. Can be an object key or folder path (ending with /). "
|
|
95
|
+
"Supports Jinja templating."
|
|
96
|
+
),
|
|
97
|
+
"ui:field": "CodeEditorWithReferencesField",
|
|
98
|
+
"ui:options": {
|
|
99
|
+
"type": "plain",
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
"compress_mode": {
|
|
103
|
+
"type": "string",
|
|
104
|
+
"title": _l("Compression Method"),
|
|
105
|
+
"description": _l("Compress file before uploading using specified method"),
|
|
106
|
+
"enum": ["None", "Gzip", "Zip"],
|
|
107
|
+
"enumNames": ["None", "Gzip", "Zip"],
|
|
108
|
+
"default": "None",
|
|
109
|
+
},
|
|
110
|
+
"overwrite": {
|
|
111
|
+
"type": "boolean",
|
|
112
|
+
"title": _l("Overwrite Existing"),
|
|
113
|
+
"description": _l("Whether to overwrite if target object already exists"),
|
|
114
|
+
"default": True,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
"required": ["compress_mode", "data_source_name"],
|
|
118
|
+
}
|
|
119
|
+
return schema
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from recurvedata.operators.context import context
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
from recurvedata.pigeon.utils import fs
|
|
8
|
+
except ImportError:
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
from recurvedata.operators.transfer_operator.task import LoadTask
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DataPrepLoadTask(LoadTask):
|
|
17
|
+
should_write_header = True
|
|
18
|
+
enabled = False
|
|
19
|
+
|
|
20
|
+
def _rename_filename_to_csv(self):
|
|
21
|
+
filename2 = self.filename + ".csv"
|
|
22
|
+
if not os.path.exists(filename2):
|
|
23
|
+
if os.path.exists(self.filename):
|
|
24
|
+
os.rename(self.filename, filename2)
|
|
25
|
+
self.filename = filename2
|
|
26
|
+
|
|
27
|
+
def execute_impl(self, *args, **kwargs):
|
|
28
|
+
self._rename_filename_to_csv()
|
|
29
|
+
if fs.is_file_empty(self.filename):
|
|
30
|
+
logger.warning("file %s not exists or has no content, skip.", self.filename)
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
conf = self.rendered_config
|
|
34
|
+
context.client.upload_file_to_data_preparation(
|
|
35
|
+
project_id=conf.get("project_id") and int(conf["project_id"]),
|
|
36
|
+
file_name=self.filename,
|
|
37
|
+
table_id=conf.get("table_id") and int(conf["table_id"]),
|
|
38
|
+
import_strategy=conf.get("import_strategy"),
|
|
39
|
+
keep_user_modified_data=conf.get("keep_user_modified_data"),
|
|
40
|
+
publish=conf.get("publish"),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def config_schema(cls):
|
|
45
|
+
schema = {
|
|
46
|
+
"type": "object",
|
|
47
|
+
"properties": {
|
|
48
|
+
"project_id": {"type": "string", "title": "Project ID"},
|
|
49
|
+
"table_id": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"title": "Table ID",
|
|
52
|
+
},
|
|
53
|
+
"keep_user_modified_data": {
|
|
54
|
+
"type": "boolean",
|
|
55
|
+
"title": "Keep User Modified Data",
|
|
56
|
+
"default": False,
|
|
57
|
+
"description": "是否保留用户修改的数据",
|
|
58
|
+
},
|
|
59
|
+
"import_strategy": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"title": "Import Strategy",
|
|
62
|
+
"description": "导入策略",
|
|
63
|
+
"enum": ["overwrite", "replace", "merge"],
|
|
64
|
+
"enumNames": ["overwrite", "replace", "merge"],
|
|
65
|
+
},
|
|
66
|
+
"publish": {
|
|
67
|
+
"type": "boolean",
|
|
68
|
+
"title": "Publish",
|
|
69
|
+
"default": False,
|
|
70
|
+
"description": "是否发布",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
"required": ["project_id", "table_id"],
|
|
74
|
+
}
|
|
75
|
+
return schema
|