fivetran-connector-sdk 1.2.1__py3-none-any.whl → 1.3.1__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.
- fivetran_connector_sdk/__init__.py +43 -23
- {fivetran_connector_sdk-1.2.1.dist-info → fivetran_connector_sdk-1.3.1.dist-info}/METADATA +2 -2
- {fivetran_connector_sdk-1.2.1.dist-info → fivetran_connector_sdk-1.3.1.dist-info}/RECORD +6 -6
- {fivetran_connector_sdk-1.2.1.dist-info → fivetran_connector_sdk-1.3.1.dist-info}/WHEEL +1 -1
- {fivetran_connector_sdk-1.2.1.dist-info → fivetran_connector_sdk-1.3.1.dist-info}/entry_points.txt +0 -0
- {fivetran_connector_sdk-1.2.1.dist-info → fivetran_connector_sdk-1.3.1.dist-info}/top_level.txt +0 -0
@@ -31,13 +31,13 @@ from fivetran_connector_sdk.protos import connector_sdk_pb2_grpc
|
|
31
31
|
|
32
32
|
# Version format: <major_version>.<minor_version>.<patch_version>
|
33
33
|
# (where Major Version = 1 for GA, Minor Version is incremental MM from Jan 25 onwards, Patch Version is incremental within a month)
|
34
|
-
__version__ = "1.
|
34
|
+
__version__ = "1.3.1"
|
35
35
|
|
36
36
|
MAC_OS = "mac"
|
37
37
|
WIN_OS = "windows"
|
38
38
|
LINUX_OS = "linux"
|
39
39
|
|
40
|
-
TESTER_VERSION = "0.25.
|
40
|
+
TESTER_VERSION = "0.25.0411.001"
|
41
41
|
TESTER_FILENAME = "run_sdk_tester.jar"
|
42
42
|
VERSION_FILENAME = "version.txt"
|
43
43
|
UPLOAD_FILENAME = "code.zip"
|
@@ -49,6 +49,8 @@ REQUIREMENTS_TXT = "requirements.txt"
|
|
49
49
|
PYPI_PACKAGE_DETAILS_URL = "https://pypi.org/pypi/fivetran_connector_sdk/json"
|
50
50
|
ONE_DAY_IN_SEC = 24 * 60 * 60
|
51
51
|
MAX_RETRIES = 3
|
52
|
+
LOGGING_PREFIX = "Fivetran-Connector-SDK"
|
53
|
+
LOGGING_DELIMITER = ": "
|
52
54
|
VIRTUAL_ENV_CONFIG = "pyvenv.cfg"
|
53
55
|
|
54
56
|
# Compile patterns used in the implementation
|
@@ -73,6 +75,8 @@ DEBUGGING = False
|
|
73
75
|
EXECUTED_VIA_CLI = False
|
74
76
|
PRODUCTION_BASE_URL = "https://api.fivetran.com"
|
75
77
|
TABLES = {}
|
78
|
+
RENAMED_TABLE_NAMES = {}
|
79
|
+
RENAMED_COL_NAMES = {}
|
76
80
|
INSTALLATION_SCRIPT_MISSING_MESSAGE = "The 'installation.sh' file is missing in the 'drivers' directory. Please ensure that 'installation.sh' is present to properly configure drivers."
|
77
81
|
INSTALLATION_SCRIPT = "installation.sh"
|
78
82
|
DRIVERS = "drivers"
|
@@ -175,6 +179,8 @@ class Operations:
|
|
175
179
|
field_name = get_renamed_column_name(field)
|
176
180
|
columns[field_name] = common_pb2.Column(
|
177
181
|
name=field_name, type=common_pb2.DataType.UNSPECIFIED, primary_key=False)
|
182
|
+
new_table = common_pb2.Table(name=table, columns=columns.values())
|
183
|
+
TABLES[table] = new_table
|
178
184
|
|
179
185
|
mapped_data = _map_data_to_columns(data, columns)
|
180
186
|
record = connector_sdk_pb2.Record(
|
@@ -324,7 +330,6 @@ def _get_columns(table: str) -> dict:
|
|
324
330
|
columns = {}
|
325
331
|
if table in TABLES:
|
326
332
|
for column in TABLES[table].columns:
|
327
|
-
column.name = get_renamed_column_name(column.name)
|
328
333
|
columns[column.name] = column
|
329
334
|
|
330
335
|
return columns
|
@@ -406,10 +411,7 @@ def map_defined_data_type(columns, k, mapped_data, v):
|
|
406
411
|
mapped_data[k] = common_pb2.ValueType(naive_datetime=timestamp)
|
407
412
|
elif columns[k].type == common_pb2.DataType.UTC_DATETIME:
|
408
413
|
timestamp = timestamp_pb2.Timestamp()
|
409
|
-
if
|
410
|
-
dt = datetime.strptime(v, "%Y-%m-%dT%H:%M:%S.%f%z")
|
411
|
-
else:
|
412
|
-
dt = datetime.strptime(v, "%Y-%m-%dT%H:%M:%S%z")
|
414
|
+
dt = v if isinstance(v, datetime) else _parse_datetime_str(v)
|
413
415
|
timestamp.FromDatetime(dt)
|
414
416
|
mapped_data[k] = common_pb2.ValueType(utc_datetime=timestamp)
|
415
417
|
elif columns[k].type == common_pb2.DataType.BINARY:
|
@@ -425,6 +427,10 @@ def map_defined_data_type(columns, k, mapped_data, v):
|
|
425
427
|
raise ValueError(f"Unsupported data type encountered: {columns[k].type}. Please use valid data types.")
|
426
428
|
|
427
429
|
|
430
|
+
def _parse_datetime_str(dt):
|
431
|
+
return datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S.%f%z" if '.' in dt else "%Y-%m-%dT%H:%M:%S%z")
|
432
|
+
|
433
|
+
|
428
434
|
def _yield_check(stack):
|
429
435
|
"""Checks for the presence of 'yield' in the calling code.
|
430
436
|
Args:
|
@@ -456,7 +462,7 @@ def _check_dict(incoming: dict, string_only: bool = False) -> dict:
|
|
456
462
|
Args:
|
457
463
|
incoming (dict): The dictionary to validate.
|
458
464
|
string_only (bool): Whether to allow only string values.
|
459
|
-
|
465
|
+
|
460
466
|
Returns:
|
461
467
|
dict: The validated dictionary.
|
462
468
|
"""
|
@@ -527,9 +533,9 @@ def print_library_log(message: str, level: Logging.Level = Logging.Level.INFO):
|
|
527
533
|
if DEBUGGING or EXECUTED_VIA_CLI:
|
528
534
|
current_time = datetime.now().strftime("%b %d, %Y %I:%M:%S %p")
|
529
535
|
escaped_message = json.dumps(message).strip('"')
|
530
|
-
print(f"{current_time} {level.name}: {escaped_message}")
|
536
|
+
print(f"{current_time} {level.name} {LOGGING_PREFIX}: {escaped_message}")
|
531
537
|
else:
|
532
|
-
escaped_message = json.dumps(message)
|
538
|
+
escaped_message = json.dumps(LOGGING_PREFIX + LOGGING_DELIMITER + message)
|
533
539
|
log_message = f'{{"level":"{level.name}", "message": {escaped_message}, "message_origin": "library"}}'
|
534
540
|
print(log_message)
|
535
541
|
|
@@ -658,14 +664,20 @@ def get_renamed_table_name(source_table):
|
|
658
664
|
"""
|
659
665
|
Process a source table name to ensure it conforms to naming rules.
|
660
666
|
"""
|
661
|
-
|
667
|
+
if source_table not in RENAMED_TABLE_NAMES:
|
668
|
+
RENAMED_TABLE_NAMES[source_table] = safe_drop_underscores(source_table)
|
669
|
+
|
670
|
+
return RENAMED_TABLE_NAMES[source_table]
|
662
671
|
|
663
672
|
|
664
673
|
def get_renamed_column_name(source_column):
|
665
674
|
"""
|
666
675
|
Process a source column name to ensure it conforms to naming rules.
|
667
676
|
"""
|
668
|
-
|
677
|
+
if source_column not in RENAMED_COL_NAMES:
|
678
|
+
RENAMED_COL_NAMES[source_column] = redshift_safe(source_column)
|
679
|
+
|
680
|
+
return RENAMED_COL_NAMES[source_column]
|
669
681
|
|
670
682
|
class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
671
683
|
def __init__(self, update, schema=None):
|
@@ -928,7 +940,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
928
940
|
self.__update_connection(
|
929
941
|
args, connection_id, connection, group_name, connection_config, deploy_key, hd_agent_id)
|
930
942
|
print("✓")
|
931
|
-
print_library_log(f"
|
943
|
+
print_library_log(f"Connection ID: {connection_id}")
|
932
944
|
print_library_log(
|
933
945
|
f"Visit the Fivetran dashboard to manage the connection: https://fivetran.com/dashboard/connectors/{connection_id}/status")
|
934
946
|
else:
|
@@ -948,7 +960,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
948
960
|
connection_id = response.json()['data']['id']
|
949
961
|
# Python Version is not passed into connection_config as default value will be picked up from ConnectorSdkCredentials.java class.
|
950
962
|
print_library_log(f"Python Version: {args.python_version if args.python_version else DEFAULT_PYTHON_VERSION}", Logging.Level.INFO)
|
951
|
-
print_library_log(f"
|
963
|
+
print_library_log(f"Connection ID: {connection_id}")
|
952
964
|
print_library_log(
|
953
965
|
f"Visit the Fivetran dashboard to start the initial sync: https://fivetran.com/dashboard/connectors/{connection_id}/status")
|
954
966
|
else:
|
@@ -989,13 +1001,19 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
989
1001
|
if not args.configuration:
|
990
1002
|
del config["secrets_list"]
|
991
1003
|
|
1004
|
+
json_payload = {
|
1005
|
+
"config": config,
|
1006
|
+
"run_setup_tests": True
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
# hybrid_deployment_agent_id is optional when redeploying your connection.
|
1010
|
+
# Customer can use it to change existing hybrid_deployment_agent_id.
|
1011
|
+
if hd_agent_id:
|
1012
|
+
json_payload["hybrid_deployment_agent_id"] = hd_agent_id
|
1013
|
+
|
992
1014
|
response = rq.patch(f"{PRODUCTION_BASE_URL}/v1/connectors/{id}",
|
993
1015
|
headers={"Authorization": f"Basic {deploy_key}"},
|
994
|
-
json=
|
995
|
-
"config": config,
|
996
|
-
"hybrid_deployment_agent_id": hd_agent_id,
|
997
|
-
"run_setup_tests": True
|
998
|
-
})
|
1016
|
+
json=json_payload)
|
999
1017
|
|
1000
1018
|
if response.ok and response.status_code == HTTPStatus.OK:
|
1001
1019
|
if Connector.__are_setup_tests_failing(response):
|
@@ -1013,7 +1031,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1013
1031
|
print_library_log(log_message, Logging.Level.SEVERE)
|
1014
1032
|
Connector.__print_failing_setup_tests(resp)
|
1015
1033
|
connection_id = resp.json().get('data', {}).get('id')
|
1016
|
-
print_library_log(f"
|
1034
|
+
print_library_log(f"Connection ID: {connection_id}")
|
1017
1035
|
print_library_log("Please try again with the deploy command after resolving the issue!")
|
1018
1036
|
os._exit(1)
|
1019
1037
|
|
@@ -1414,7 +1432,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1414
1432
|
|
1415
1433
|
try:
|
1416
1434
|
print_library_log("Running connector tester...")
|
1417
|
-
for log_msg in self.__run_tester(java_exe, tester_root_dir, project_path, available_port):
|
1435
|
+
for log_msg in self.__run_tester(java_exe, tester_root_dir, project_path, available_port, json.dumps(self.state), json.dumps(self.configuration)):
|
1418
1436
|
print(log_msg, end="")
|
1419
1437
|
except:
|
1420
1438
|
print(traceback.format_exc())
|
@@ -1455,7 +1473,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1455
1473
|
yield line
|
1456
1474
|
|
1457
1475
|
@staticmethod
|
1458
|
-
def __run_tester(java_exe: str, root_dir: str, project_path: str, port: int):
|
1476
|
+
def __run_tester(java_exe: str, root_dir: str, project_path: str, port: int, state_json: str, configuration_json: str):
|
1459
1477
|
"""Runs the connector tester.
|
1460
1478
|
|
1461
1479
|
Args:
|
@@ -1478,7 +1496,9 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1478
1496
|
"--connector-sdk=true",
|
1479
1497
|
f"--port={port}",
|
1480
1498
|
f"--working-dir={working_dir}",
|
1481
|
-
"--tester-type=source"
|
1499
|
+
"--tester-type=source",
|
1500
|
+
f"--state={state_json}",
|
1501
|
+
f"--configuration={configuration_json}"]
|
1482
1502
|
|
1483
1503
|
popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
|
1484
1504
|
for line in Connector.process_stream(popen.stderr):
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: fivetran_connector_sdk
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.3.1
|
4
4
|
Summary: Build custom connectors on Fivetran platform
|
5
5
|
Author-email: Fivetran <developers@fivetran.com>
|
6
6
|
Project-URL: Homepage, https://fivetran.com/docs/connectors/connector-sdk
|
@@ -1,4 +1,4 @@
|
|
1
|
-
fivetran_connector_sdk/__init__.py,sha256=
|
1
|
+
fivetran_connector_sdk/__init__.py,sha256=4ovEZ7G46t5JFEAUmyGNksa0RVs9x5eKsYfzmyBDuNs,81121
|
2
2
|
fivetran_connector_sdk/protos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
fivetran_connector_sdk/protos/common_pb2.py,sha256=kUwVcyZHgLigNR-KnHZn7dHrlxaMnUXqzprsRx6T72M,6831
|
4
4
|
fivetran_connector_sdk/protos/common_pb2.pyi,sha256=S0hdIzoXyyOKD5cjiGeDDLYpQ9J3LjAvu4rCj1JvJWE,9038
|
@@ -6,8 +6,8 @@ fivetran_connector_sdk/protos/common_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXH
|
|
6
6
|
fivetran_connector_sdk/protos/connector_sdk_pb2.py,sha256=9Ke_Ti1s0vAeXapfXT-EryrT2-TSGQb8mhs4gxTpUMk,7732
|
7
7
|
fivetran_connector_sdk/protos/connector_sdk_pb2.pyi,sha256=FWYxRgshEF3QDYAE0TM_mv4N2gGvkxCH_uPpxnMc4oA,8406
|
8
8
|
fivetran_connector_sdk/protos/connector_sdk_pb2_grpc.py,sha256=ZfJLp4DW7uP4pFOZ74s_wQ6tD3eIPi-08UfnLwe4tzo,7163
|
9
|
-
fivetran_connector_sdk-1.
|
10
|
-
fivetran_connector_sdk-1.
|
11
|
-
fivetran_connector_sdk-1.
|
12
|
-
fivetran_connector_sdk-1.
|
13
|
-
fivetran_connector_sdk-1.
|
9
|
+
fivetran_connector_sdk-1.3.1.dist-info/METADATA,sha256=qEnx2X-ac7iQhdJ7bx0p9yKhliRUAz_cxhRRgX3P-Jk,2967
|
10
|
+
fivetran_connector_sdk-1.3.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
11
|
+
fivetran_connector_sdk-1.3.1.dist-info/entry_points.txt,sha256=uQn0KPnFlQmXJfxlk0tifdNsSXWfVlnAFzNqjXZM_xM,57
|
12
|
+
fivetran_connector_sdk-1.3.1.dist-info/top_level.txt,sha256=-_xk2MFY4psIh7jw1lJePMzFb5-vask8_ZtX-UzYWUI,23
|
13
|
+
fivetran_connector_sdk-1.3.1.dist-info/RECORD,,
|
{fivetran_connector_sdk-1.2.1.dist-info → fivetran_connector_sdk-1.3.1.dist-info}/entry_points.txt
RENAMED
File without changes
|
{fivetran_connector_sdk-1.2.1.dist-info → fivetran_connector_sdk-1.3.1.dist-info}/top_level.txt
RENAMED
File without changes
|