fivetran-connector-sdk 1.5.1__tar.gz → 1.6.0__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 (23) hide show
  1. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/PKG-INFO +1 -1
  2. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/__init__.py +4 -4
  3. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/connector_helper.py +16 -15
  4. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/helpers.py +6 -2
  5. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/operations.py +17 -2
  6. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk.egg-info/PKG-INFO +1 -1
  7. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/README.md +0 -0
  8. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/pyproject.toml +0 -0
  9. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/setup.cfg +0 -0
  10. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/constants.py +0 -0
  11. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/logger.py +0 -0
  12. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/protos/__init__.py +0 -0
  13. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/protos/common_pb2.py +0 -0
  14. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/protos/common_pb2.pyi +0 -0
  15. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/protos/common_pb2_grpc.py +0 -0
  16. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.py +0 -0
  17. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.pyi +0 -0
  18. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk/protos/connector_sdk_pb2_grpc.py +0 -0
  19. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk.egg-info/SOURCES.txt +0 -0
  20. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk.egg-info/dependency_links.txt +0 -0
  21. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk.egg-info/entry_points.txt +0 -0
  22. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk.egg-info/requires.txt +0 -0
  23. {fivetran_connector_sdk-1.5.1 → fivetran_connector_sdk-1.6.0}/src/fivetran_connector_sdk.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fivetran_connector_sdk
3
- Version: 1.5.1
3
+ Version: 1.6.0
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
@@ -39,7 +39,7 @@ from fivetran_connector_sdk.connector_helper import (
39
39
 
40
40
  # Version format: <major_version>.<minor_version>.<patch_version>
41
41
  # (where Major Version = 1 for GA, Minor Version is incremental MM from Jan 25 onwards, Patch Version is incremental within a month)
42
- __version__ = "1.5.1"
42
+ __version__ = "1.6.0"
43
43
  TESTER_VERSION = TESTER_VER
44
44
  MAX_MESSAGE_LENGTH = 32 * 1024 * 1024 # 32MB
45
45
 
@@ -104,7 +104,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
104
104
  if service != 'connector_sdk':
105
105
  print_library_log(
106
106
  f"The connection '{connection}' already exists and does not use the 'Connector SDK' service. You cannot update this connection.", Logging.Level.SEVERE)
107
- os._exit(1)
107
+ sys.exit(1)
108
108
  else:
109
109
  if args.force:
110
110
  confirm = "y"
@@ -129,7 +129,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
129
129
  f"Visit the Fivetran dashboard to manage the connection: https://fivetran.com/dashboard/connectors/{connection_id}/status")
130
130
  else:
131
131
  print_library_log("Update canceled. The process is now terminating.")
132
- os._exit(1)
132
+ sys.exit(1)
133
133
  else:
134
134
  upload_project(args.project_path, deploy_key,
135
135
  group_id, group_name, connection)
@@ -152,7 +152,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
152
152
  f"Unable to create a new connection, failed with error: {response.json()['message']}", Logging.Level.SEVERE)
153
153
  cleanup_uploaded_project(deploy_key,group_id, connection)
154
154
  print_library_log("Please try again with the deploy command after resolving the issue!")
155
- os._exit(1)
155
+ sys.exit(1)
156
156
 
157
157
  # Call this method to run the connector in production
158
158
  def run(self,
@@ -2,6 +2,7 @@ import os
2
2
  import re
3
3
  import ast
4
4
  import json
5
+ import sys
5
6
  import time
6
7
  import socket
7
8
  import platform
@@ -140,7 +141,7 @@ def check_dict(incoming: dict, string_only: bool = False) -> dict:
140
141
  if not isinstance(v, str):
141
142
  print_library_log(
142
143
  "All values in the configuration must be STRING. Please check your configuration and ensure that every value is a STRING.", Logging.Level.SEVERE)
143
- os._exit(1)
144
+ sys.exit(1)
144
145
 
145
146
  return incoming
146
147
 
@@ -173,12 +174,12 @@ def validate_deploy_parameters(connection, deploy_key):
173
174
  "\t(Optional):\n"
174
175
  "\t\t--destination <DESTINATION_NAME> (Becomes required if there are multiple destinations)\n"
175
176
  "\t\t--configuration <CONFIGURATION_FILE> (Completely replaces the existing configuration)", Logging.Level.SEVERE)
176
- os._exit(1)
177
+ sys.exit(1)
177
178
  elif not is_connection_name_valid(connection):
178
179
  print_library_log(f"Connection name: {connection} is invalid!\n The connection name should start with an "
179
180
  f"underscore or a lowercase letter (a-z), followed by any combination of underscores, lowercase "
180
181
  f"letters, or digits (0-9). Uppercase characters are not allowed.", Logging.Level.SEVERE)
181
- os._exit(1)
182
+ sys.exit(1)
182
183
 
183
184
 
184
185
  def is_port_in_use(port: int):
@@ -346,7 +347,7 @@ def validate_requirements_file(project_path: str, is_deploy: bool, version: str
346
347
  if 'fivetran_connector_sdk' in unused_deps or 'requests' in unused_deps:
347
348
  print_library_log(
348
349
  f"Please fix your {REQUIREMENTS_TXT} file by removing pre-installed dependencies [fivetran_connector_sdk, requests] to proceed with the deployment.")
349
- os._exit(1)
350
+ sys.exit(1)
350
351
  print_library_log(f"Changes identified for unused libraries have been ignored. These changes have NOT been made to {REQUIREMENTS_TXT}.")
351
352
  elif confirm.lower() == "y":
352
353
  update_unused_requirements = True
@@ -420,13 +421,13 @@ def upload_project(project_path: str, deploy_key: str, group_id: str, group_name
420
421
  upload_file_path, deploy_key, group_id, connection)
421
422
  delete_file_if_exists(upload_file_path)
422
423
  if not upload_result:
423
- os._exit(1)
424
+ sys.exit(1)
424
425
 
425
426
 
426
427
  def cleanup_uploaded_project(deploy_key: str, group_id: str, connection: str):
427
428
  cleanup_result = cleanup_uploaded_code(deploy_key, group_id, connection)
428
429
  if not cleanup_result:
429
- os._exit(1)
430
+ sys.exit(1)
430
431
 
431
432
  def update_connection(args: dict, id: str, name: str, group: str, config: dict, deploy_key: str, hd_agent_id: str):
432
433
  """Updates the connection with the given ID, name, group, configuration, and deployment key.
@@ -467,7 +468,7 @@ def update_connection(args: dict, id: str, name: str, group: str, config: dict,
467
468
  print_library_log(
468
469
  f"Unable to update Connection '{name}' in destination '{group}', failed with error: '{response.json()['message']}'.",
469
470
  Logging.Level.SEVERE)
470
- os._exit(1)
471
+ sys.exit(1)
471
472
  return response
472
473
 
473
474
  def handle_failing_tests_message_and_exit(resp, log_message):
@@ -476,7 +477,7 @@ def handle_failing_tests_message_and_exit(resp, log_message):
476
477
  connection_id = resp.json().get('data', {}).get('id')
477
478
  print_library_log(f"Connection ID: {connection_id}")
478
479
  print_library_log("Please try again with the deploy command after resolving the issue!")
479
- os._exit(1)
480
+ sys.exit(1)
480
481
 
481
482
  def are_setup_tests_failing(response) -> bool:
482
483
  """Checks for failed setup tests in the response and returns True if any test has failed, otherwise False."""
@@ -520,7 +521,7 @@ def get_connection_id(name: str, group: str, group_id: str, deploy_key: str) ->
520
521
  if not resp.ok:
521
522
  print_library_log(
522
523
  f"Unable to fetch connection list in destination '{group}'", Logging.Level.SEVERE)
523
- os._exit(1)
524
+ sys.exit(1)
524
525
 
525
526
  if resp.json()['data']['items']:
526
527
  return resp.json()['data']['items'][0]['id'], resp.json()['data']['items'][0]['service']
@@ -599,11 +600,11 @@ def zip_folder(project_path: str) -> str:
599
600
  print_library_log(
600
601
  "The 'connector.py' file is missing. Please ensure that 'connector.py' is present in your project directory, and that the file name is in lowercase letters. All custom connectors require this file because Fivetran calls it to start a sync.",
601
602
  Logging.Level.SEVERE)
602
- os._exit(1)
603
+ sys.exit(1)
603
604
 
604
605
  if custom_drivers_exists and not custom_driver_installation_script_exists:
605
606
  print_library_log(INSTALLATION_SCRIPT_MISSING_MESSAGE, Logging.Level.SEVERE)
606
- os._exit(1)
607
+ sys.exit(1)
607
608
 
608
609
  return upload_filepath
609
610
 
@@ -719,14 +720,14 @@ def get_group_info(group: str, deploy_key: str) -> tuple[str, str]:
719
720
  print_library_log(
720
721
  f"The request failed with status code: {resp.status_code}. Please ensure you're using a valid base64-encoded API key and try again.",
721
722
  Logging.Level.SEVERE)
722
- os._exit(1)
723
+ sys.exit(1)
723
724
 
724
725
  data = resp.json().get("data", {})
725
726
  groups = data.get("items")
726
727
 
727
728
  if not groups:
728
729
  print_library_log("No destinations defined in the account", Logging.Level.SEVERE)
729
- os._exit(1)
730
+ sys.exit(1)
730
731
 
731
732
  if not group:
732
733
  if len(groups) == 1:
@@ -735,7 +736,7 @@ def get_group_info(group: str, deploy_key: str) -> tuple[str, str]:
735
736
  print_library_log(
736
737
  "Destination name is required when there are multiple destinations in the account",
737
738
  Logging.Level.SEVERE)
738
- os._exit(1)
739
+ sys.exit(1)
739
740
  else:
740
741
  while True:
741
742
  for grp in groups:
@@ -753,7 +754,7 @@ def get_group_info(group: str, deploy_key: str) -> tuple[str, str]:
753
754
 
754
755
  print_library_log(
755
756
  f"The specified destination '{group}' was not found in your account.", Logging.Level.SEVERE)
756
- os._exit(1)
757
+ sys.exit(1)
757
758
 
758
759
  def java_exe_helper(location: str, os_arch_suffix: str) -> str:
759
760
  """Returns the path to the Java executable.
@@ -29,19 +29,23 @@ from fivetran_connector_sdk.constants import (
29
29
  RENAMED_TABLE_NAMES = {}
30
30
  RENAMED_COL_NAMES = {}
31
31
 
32
- def print_library_log(message: str, level: Logging.Level = Logging.Level.INFO):
32
+ def print_library_log(message: str, level: Logging.Level = Logging.Level.INFO, dev_log: bool = False):
33
33
  """Logs a library message with the specified logging level.
34
34
 
35
35
  Args:
36
36
  level (Logging.Level): The logging level.
37
37
  message (str): The message to log.
38
+ dev_log (bool): Boolean value to check if it is dev log and shouldn't be visible to customer
38
39
  """
39
40
  if constants.DEBUGGING or constants.EXECUTED_VIA_CLI:
41
+ if dev_log:
42
+ return
40
43
  current_time = datetime.now().strftime("%b %d, %Y %I:%M:%S %p")
41
44
  print(f"{Logging.get_color(level)}{current_time} {level.name} {LOGGING_PREFIX}: {message} {Logging.reset_color()}")
42
45
  else:
46
+ message_origin = "library_dev" if dev_log else "library"
43
47
  escaped_message = json.dumps(LOGGING_PREFIX + LOGGING_DELIMITER + message)
44
- log_message = f'{{"level":"{level.name}", "message": {escaped_message}, "message_origin": "library"}}'
48
+ log_message = f'{{"level":"{level.name}", "message": {escaped_message}, "message_origin": "{message_origin}"}}'
45
49
  print(log_message)
46
50
 
47
51
  def is_special(c):
@@ -1,6 +1,6 @@
1
- import os
2
1
  import json
3
2
  import inspect
3
+ import sys
4
4
 
5
5
  from datetime import datetime
6
6
  from google.protobuf import timestamp_pb2
@@ -18,6 +18,12 @@ from fivetran_connector_sdk.helpers import (
18
18
  from fivetran_connector_sdk.logger import Logging
19
19
  from fivetran_connector_sdk.protos import connector_sdk_pb2, common_pb2
20
20
 
21
+ _LOG_DATA_TYPE_INFERENCE = {
22
+ "boolean": True,
23
+ "binary": True,
24
+ "json": True
25
+ }
26
+
21
27
  class Operations:
22
28
  @staticmethod
23
29
  def upsert(table: str, data: dict) -> list[connector_sdk_pb2.UpdateResponse]:
@@ -189,13 +195,22 @@ def map_inferred_data_type(k, mapped_data, v):
189
195
  elif isinstance(v, float):
190
196
  mapped_data[k] = common_pb2.ValueType(float=v)
191
197
  elif isinstance(v, bool):
198
+ if _LOG_DATA_TYPE_INFERENCE["boolean"]:
199
+ print_library_log("Fivetran: Boolean Datatype has been inferred", Logging.Level.INFO, True)
200
+ _LOG_DATA_TYPE_INFERENCE["boolean"] = False
192
201
  mapped_data[k] = common_pb2.ValueType(bool=v)
193
202
  elif isinstance(v, bytes):
203
+ if _LOG_DATA_TYPE_INFERENCE["binary"]:
204
+ print_library_log("Fivetran: Binary Datatype has been inferred", Logging.Level.INFO, True)
205
+ _LOG_DATA_TYPE_INFERENCE["binary"] = False
194
206
  mapped_data[k] = common_pb2.ValueType(binary=v)
195
207
  elif isinstance(v, list):
196
208
  raise ValueError(
197
209
  "Values for the columns cannot be of type 'list'. Please ensure that all values are of a supported type. Reference: https://fivetran.com/docs/connectors/connector-sdk/technical-reference#supporteddatatypes")
198
210
  elif isinstance(v, dict):
211
+ if _LOG_DATA_TYPE_INFERENCE["json"]:
212
+ print_library_log("Fivetran: JSON Datatype has been inferred", Logging.Level.INFO, True)
213
+ _LOG_DATA_TYPE_INFERENCE["json"] = False
199
214
  mapped_data[k] = common_pb2.ValueType(json=json.dumps(v))
200
215
  elif isinstance(v, str):
201
216
  mapped_data[k] = common_pb2.ValueType(string=v)
@@ -270,7 +285,7 @@ def _yield_check(stack):
270
285
  if 'yield' not in calling_code:
271
286
  print_library_log(
272
287
  f"Please add 'yield' to '{called_method}' operation on line {stack[1].lineno} in file '{stack[1].filename}'", Logging.Level.SEVERE)
273
- os._exit(1)
288
+ sys.exit(1)
274
289
  else:
275
290
  # This should never happen
276
291
  raise RuntimeError(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fivetran_connector_sdk
3
- Version: 1.5.1
3
+ Version: 1.6.0
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