fivetran-connector-sdk 0.13.22.1__tar.gz → 0.13.30.1__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.
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/PKG-INFO +1 -1
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/__init__.py +44 -35
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk.egg-info/PKG-INFO +1 -1
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/README.md +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/pyproject.toml +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/setup.cfg +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/protos/__init__.py +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/protos/common_pb2.py +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/protos/common_pb2.pyi +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/protos/common_pb2_grpc.py +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.py +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.pyi +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/protos/connector_sdk_pb2_grpc.py +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk.egg-info/SOURCES.txt +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk.egg-info/dependency_links.txt +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk.egg-info/entry_points.txt +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk.egg-info/requires.txt +0 -0
- {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: fivetran_connector_sdk
|
3
|
-
Version: 0.13.
|
3
|
+
Version: 0.13.30.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
|
@@ -29,13 +29,13 @@ from fivetran_connector_sdk.protos import connector_sdk_pb2
|
|
29
29
|
from fivetran_connector_sdk.protos import connector_sdk_pb2_grpc
|
30
30
|
|
31
31
|
# Version format: <major_version>.<MM>.<DD>.<iteration> (where MM is incremental value from Jan 2024)
|
32
|
-
__version__ = "0.13.
|
32
|
+
__version__ = "0.13.30.1"
|
33
33
|
|
34
34
|
MAC_OS = "mac"
|
35
35
|
WIN_OS = "windows"
|
36
36
|
LINUX_OS = "linux"
|
37
37
|
|
38
|
-
TESTER_VERSION = "0.25.
|
38
|
+
TESTER_VERSION = "0.25.0130.001"
|
39
39
|
TESTER_FILENAME = "run_sdk_tester.jar"
|
40
40
|
VERSION_FILENAME = "version.txt"
|
41
41
|
UPLOAD_FILENAME = "code.zip"
|
@@ -161,13 +161,14 @@ class Operations:
|
|
161
161
|
|
162
162
|
responses = []
|
163
163
|
|
164
|
-
table =
|
164
|
+
table = get_renamed_table_name(table)
|
165
165
|
columns = _get_columns(table)
|
166
166
|
if not columns:
|
167
167
|
global TABLES
|
168
168
|
for field in data.keys():
|
169
|
-
|
170
|
-
|
169
|
+
field_name = get_renamed_column_name(field)
|
170
|
+
columns[field_name] = common_pb2.Column(
|
171
|
+
name=field_name, type=common_pb2.DataType.UNSPECIFIED, primary_key=False)
|
171
172
|
|
172
173
|
mapped_data = _map_data_to_columns(data, columns)
|
173
174
|
record = connector_sdk_pb2.Record(
|
@@ -196,7 +197,7 @@ class Operations:
|
|
196
197
|
"""
|
197
198
|
_yield_check(inspect.stack())
|
198
199
|
|
199
|
-
table =
|
200
|
+
table = get_renamed_table_name(table)
|
200
201
|
columns = _get_columns(table)
|
201
202
|
mapped_data = _map_data_to_columns(modified, columns)
|
202
203
|
record = connector_sdk_pb2.Record(
|
@@ -222,7 +223,7 @@ class Operations:
|
|
222
223
|
"""
|
223
224
|
_yield_check(inspect.stack())
|
224
225
|
|
225
|
-
table =
|
226
|
+
table = get_renamed_table_name(table)
|
226
227
|
columns = _get_columns(table)
|
227
228
|
mapped_data = _map_data_to_columns(keys, columns)
|
228
229
|
record = connector_sdk_pb2.Record(
|
@@ -313,6 +314,7 @@ def _get_columns(table: str) -> dict:
|
|
313
314
|
columns = {}
|
314
315
|
if table in TABLES:
|
315
316
|
for column in TABLES[table].columns:
|
317
|
+
column.name = get_renamed_column_name(column.name)
|
316
318
|
columns[column.name] = column
|
317
319
|
|
318
320
|
return columns
|
@@ -330,12 +332,13 @@ def _map_data_to_columns(data: dict, columns: dict) -> dict:
|
|
330
332
|
"""
|
331
333
|
mapped_data = {}
|
332
334
|
for k, v in data.items():
|
335
|
+
key = get_renamed_column_name(k)
|
333
336
|
if v is None:
|
334
|
-
mapped_data[
|
335
|
-
elif (
|
336
|
-
map_defined_data_type(columns,
|
337
|
+
mapped_data[key] = common_pb2.ValueType(null=True)
|
338
|
+
elif (key in columns) and columns[key].type != common_pb2.DataType.UNSPECIFIED:
|
339
|
+
map_defined_data_type(columns, key, mapped_data, v)
|
337
340
|
else:
|
338
|
-
map_inferred_data_type(
|
341
|
+
map_inferred_data_type(key, mapped_data, v)
|
339
342
|
|
340
343
|
return mapped_data
|
341
344
|
|
@@ -643,13 +646,19 @@ def safe_drop_underscores(name):
|
|
643
646
|
return safe_name
|
644
647
|
|
645
648
|
|
646
|
-
def
|
649
|
+
def get_renamed_table_name(source_table):
|
647
650
|
"""
|
648
651
|
Process a source table name to ensure it conforms to naming rules.
|
649
652
|
"""
|
650
653
|
return safe_drop_underscores(source_table)
|
651
654
|
|
652
655
|
|
656
|
+
def get_renamed_column_name(source_column):
|
657
|
+
"""
|
658
|
+
Process a source column name to ensure it conforms to naming rules.
|
659
|
+
"""
|
660
|
+
return redshift_safe(source_column)
|
661
|
+
|
653
662
|
class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
654
663
|
def __init__(self, update, schema=None):
|
655
664
|
"""Initializes the Connector instance.
|
@@ -716,14 +725,16 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
716
725
|
force (bool): Force update an existing connection.
|
717
726
|
|
718
727
|
"""
|
728
|
+
# tmp_requirements is only generated when pipreqs command is successful
|
729
|
+
tmp_requirements_file_path = os.path.join(project_path, 'tmp_requirements.txt')
|
719
730
|
# Run the pipreqs command and capture stderr
|
720
731
|
attempt = 0
|
721
732
|
while attempt < MAX_RETRIES:
|
722
733
|
attempt += 1
|
723
734
|
result = subprocess.run(
|
724
|
-
["pipreqs", "--savepath",
|
735
|
+
["pipreqs", project_path, "--savepath", tmp_requirements_file_path, "--ignore"] + EXCLUDED_PIPREQS_DIRS,
|
725
736
|
stderr=subprocess.PIPE,
|
726
|
-
text=True
|
737
|
+
text=True # Ensures output is in string format
|
727
738
|
)
|
728
739
|
|
729
740
|
if result.returncode == 0:
|
@@ -740,9 +751,6 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
740
751
|
print(result.stderr)
|
741
752
|
sys.exit(1)
|
742
753
|
|
743
|
-
# tmp_requirements is only generated when pipreqs command is successful
|
744
|
-
tmp_requirements_file_path = os.path.join(project_path, 'tmp_requirements.txt')
|
745
|
-
|
746
754
|
tmp_requirements = self.fetch_requirements_as_dict(self, tmp_requirements_file_path)
|
747
755
|
tmp_requirements.pop("fivetran_connector_sdk")
|
748
756
|
if tmp_requirements.get('requests') is not None:
|
@@ -875,14 +883,14 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
875
883
|
else:
|
876
884
|
confirm = input(
|
877
885
|
f"The connection '{connection}' already exists in the destination '{group}'. Updating it will overwrite the existing code. Do you want to proceed with the update? (Y/N): ")
|
878
|
-
if confirm.lower() == "y" and
|
886
|
+
if confirm.lower() == "y" and args.configuration:
|
879
887
|
confirm_config = input(f"Your deploy will overwrite the configuration using the values provided in '{args.configuration}': key-value pairs not present in the new configuration will be removed; existing keys' values set in the cofiguration file or in the dashboard will be overwritten with new (empty or non-empty) values; new key-value pairs will be added. Do you want to proceed with the update? (Y/N): ")
|
880
888
|
if confirm.lower() == "y" and (not connection_config["secrets_list"] or (confirm_config.lower() == "y")):
|
881
889
|
print_library_log("Updating the connection...\n")
|
882
890
|
self.__upload_project(
|
883
891
|
args.project_path, deploy_key, group_id, group_name, connection)
|
884
892
|
self.__update_connection(
|
885
|
-
connection_id, connection, group_name, connection_config, deploy_key)
|
893
|
+
args, connection_id, connection, group_name, connection_config, deploy_key)
|
886
894
|
print("✓")
|
887
895
|
print_library_log(f"Connector ID: {connection_id}")
|
888
896
|
print_library_log(
|
@@ -925,17 +933,18 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
925
933
|
os._exit(1)
|
926
934
|
|
927
935
|
@staticmethod
|
928
|
-
def __update_connection(id: str, name: str, group: str, config: dict, deploy_key: str):
|
936
|
+
def __update_connection(args: dict, id: str, name: str, group: str, config: dict, deploy_key: str):
|
929
937
|
"""Updates the connection with the given ID, name, group, configuration, and deployment key.
|
930
938
|
|
931
939
|
Args:
|
940
|
+
args (dict): The command arguments.
|
932
941
|
id (str): The connection ID.
|
933
942
|
name (str): The connection name.
|
934
943
|
group (str): The group name.
|
935
944
|
config (dict): The configuration dictionary.
|
936
945
|
deploy_key (str): The deployment key.
|
937
946
|
"""
|
938
|
-
if not
|
947
|
+
if not args.configuration:
|
939
948
|
del config["secrets_list"]
|
940
949
|
|
941
950
|
resp = rq.patch(f"{PRODUCTION_BASE_URL}/v1/connectors/{id}",
|
@@ -1161,7 +1170,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1161
1170
|
|
1162
1171
|
if not resp.ok:
|
1163
1172
|
print_library_log(
|
1164
|
-
f"
|
1173
|
+
f"The request failed with status code: {resp.status_code}. Please ensure you're using a valid base64-encoded API key and try again.", Logging.Level.SEVERE)
|
1165
1174
|
os._exit(1)
|
1166
1175
|
|
1167
1176
|
data = resp.json().get("data", {})
|
@@ -1234,7 +1243,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1234
1243
|
project_path: str = None,
|
1235
1244
|
configuration: dict = None,
|
1236
1245
|
state: dict = None,
|
1237
|
-
log_level: Logging.Level = Logging.Level.FINE)
|
1246
|
+
log_level: Logging.Level = Logging.Level.FINE):
|
1238
1247
|
"""Tests the connector code by running it with the connector tester.\n
|
1239
1248
|
state.json docs: https://fivetran.com/docs/connectors/connector-sdk/detailed-guide#workingwithstatejsonfile\n
|
1240
1249
|
configuration.json docs: https://fivetran.com/docs/connectors/connector-sdk/detailed-guide#workingwithconfigurationjsonfile
|
@@ -1244,9 +1253,6 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1244
1253
|
configuration (dict): The configuration dictionary, same as configuration.json if present.
|
1245
1254
|
state (dict): The state dictionary, same as state.json if present.
|
1246
1255
|
log_level (Logging.Level): The logging level.
|
1247
|
-
|
1248
|
-
Returns:
|
1249
|
-
bool: True if there was an error, False otherwise.
|
1250
1256
|
"""
|
1251
1257
|
global DEBUGGING
|
1252
1258
|
DEBUGGING = True
|
@@ -1443,7 +1449,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1443
1449
|
else:
|
1444
1450
|
try:
|
1445
1451
|
configuration = self.configuration if self.configuration else request.configuration
|
1446
|
-
print_library_log("Initiating the 'schema' method call...", Logging.Level.
|
1452
|
+
print_library_log("Initiating the 'schema' method call...", Logging.Level.INFO)
|
1447
1453
|
response = self.schema_method(configuration)
|
1448
1454
|
self.process_tables(response)
|
1449
1455
|
return connector_sdk_pb2.SchemaResponse(without_schema=common_pb2.TableList(tables=TABLES.values()))
|
@@ -1459,7 +1465,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1459
1465
|
if 'table' not in entry:
|
1460
1466
|
raise ValueError("Entry missing table name: " + entry)
|
1461
1467
|
|
1462
|
-
table_name =
|
1468
|
+
table_name = get_renamed_table_name(entry['table'])
|
1463
1469
|
|
1464
1470
|
if table_name in TABLES:
|
1465
1471
|
raise ValueError("Table already defined: " + table_name)
|
@@ -1478,13 +1484,15 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1478
1484
|
|
1479
1485
|
def process_primary_keys(self, columns, entry):
|
1480
1486
|
for pkey_name in entry["primary_key"]:
|
1481
|
-
|
1487
|
+
column_name = get_renamed_column_name(pkey_name)
|
1488
|
+
column = columns[column_name] if column_name in columns else common_pb2.Column(name=column_name)
|
1482
1489
|
column.primary_key = True
|
1483
|
-
columns[
|
1490
|
+
columns[column_name] = column
|
1484
1491
|
|
1485
1492
|
def process_columns(self, columns, entry):
|
1486
1493
|
for name, type in entry["columns"].items():
|
1487
|
-
|
1494
|
+
column_name = get_renamed_column_name(name)
|
1495
|
+
column = columns[column_name] if column_name in columns else common_pb2.Column(name=column_name)
|
1488
1496
|
|
1489
1497
|
if isinstance(type, str):
|
1490
1498
|
self.process_data_type(column, type)
|
@@ -1502,7 +1510,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1502
1510
|
if "primary_key" in entry and name in entry["primary_key"]:
|
1503
1511
|
column.primary_key = True
|
1504
1512
|
|
1505
|
-
columns[
|
1513
|
+
columns[column_name] = column
|
1506
1514
|
|
1507
1515
|
def process_data_type(self, column, type):
|
1508
1516
|
if type.upper() == "BOOLEAN":
|
@@ -1550,7 +1558,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
|
|
1550
1558
|
state = self.state if self.state else json.loads(request.state_json)
|
1551
1559
|
|
1552
1560
|
try:
|
1553
|
-
print_library_log("Initiating the 'update' method call...", Logging.Level.
|
1561
|
+
print_library_log("Initiating the 'update' method call...", Logging.Level.INFO)
|
1554
1562
|
for resp in self.update_method(configuration=configuration, state=state):
|
1555
1563
|
if isinstance(resp, list):
|
1556
1564
|
for r in resp:
|
@@ -1667,7 +1675,8 @@ def main():
|
|
1667
1675
|
global EXECUTED_VIA_CLI
|
1668
1676
|
EXECUTED_VIA_CLI = True
|
1669
1677
|
|
1670
|
-
parser = argparse.ArgumentParser(allow_abbrev=False)
|
1678
|
+
parser = argparse.ArgumentParser(allow_abbrev=False, add_help=True)
|
1679
|
+
parser._option_string_actions["-h"].help = "Show this help message and exit"
|
1671
1680
|
|
1672
1681
|
# Positional
|
1673
1682
|
parser.add_argument("command", help="|".join(VALID_COMMANDS))
|
@@ -1676,7 +1685,7 @@ def main():
|
|
1676
1685
|
# Optional (Not all of these are valid with every mutually exclusive option below)
|
1677
1686
|
parser.add_argument("--state", type=str, default=None, help="Provide state as JSON string or file")
|
1678
1687
|
parser.add_argument("--configuration", type=str, default=None, help="Provide secrets as JSON file")
|
1679
|
-
parser.add_argument("--api-key", type=str, default=None, help="Provide
|
1688
|
+
parser.add_argument("--api-key", type=str, default=None, help="Provide your base64-encoded API key for deployment")
|
1680
1689
|
parser.add_argument("--destination", type=str, default=None, help="Destination name (aka 'group name')")
|
1681
1690
|
parser.add_argument("--connection", type=str, default=None, help="Connection name (aka 'destination schema')")
|
1682
1691
|
parser.add_argument("-f", "--force", action="store_true", help="Force update an existing connection")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: fivetran_connector_sdk
|
3
|
-
Version: 0.13.
|
3
|
+
Version: 0.13.30.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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|