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.
Files changed (18) hide show
  1. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/PKG-INFO +1 -1
  2. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/__init__.py +44 -35
  3. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk.egg-info/PKG-INFO +1 -1
  4. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/README.md +0 -0
  5. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/pyproject.toml +0 -0
  6. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/setup.cfg +0 -0
  7. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/protos/__init__.py +0 -0
  8. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/protos/common_pb2.py +0 -0
  9. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk/protos/common_pb2.pyi +0 -0
  10. {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
  11. {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
  12. {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
  13. {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
  14. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk.egg-info/SOURCES.txt +0 -0
  15. {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
  16. {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
  17. {fivetran_connector_sdk-0.13.22.1 → fivetran_connector_sdk-0.13.30.1}/src/fivetran_connector_sdk.egg-info/requires.txt +0 -0
  18. {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.22.1
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.22.1"
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.0117.001"
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 = for_table(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
- columns[field] = common_pb2.Column(
170
- name=field, type=common_pb2.DataType.UNSPECIFIED, primary_key=False)
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 = for_table(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 = for_table(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[k] = common_pb2.ValueType(null=True)
335
- elif (k in columns) and columns[k].type != common_pb2.DataType.UNSPECIFIED:
336
- map_defined_data_type(columns, k, mapped_data, v)
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(k, mapped_data, v)
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 for_table(source_table):
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", "tmp_requirements.txt", "--ignore"] + EXCLUDED_PIPREQS_DIRS,
735
+ ["pipreqs", project_path, "--savepath", tmp_requirements_file_path, "--ignore"] + EXCLUDED_PIPREQS_DIRS,
725
736
  stderr=subprocess.PIPE,
726
- text=True # Ensures output is in string format
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 connection_config["secrets_list"]:
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 config["secrets_list"]:
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"Unable to retrieve destination details. 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)
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) -> bool:
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.WARNING)
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 = for_table(entry['table'])
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
- column = columns[pkey_name] if pkey_name in columns else common_pb2.Column(name=pkey_name)
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[pkey_name] = column
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
- column = columns[name] if name in columns else common_pb2.Column(name=name)
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[name] = column
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.WARNING)
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 api key for deployment to production")
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.22.1
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