fivetran-connector-sdk 1.2.0__py3-none-any.whl → 1.3.0__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.
@@ -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.2.0"
34
+ __version__ = "1.3.0"
35
35
 
36
36
  MAC_OS = "mac"
37
37
  WIN_OS = "windows"
38
38
  LINUX_OS = "linux"
39
39
 
40
- TESTER_VERSION = "0.25.0225.001"
40
+ TESTER_VERSION = "0.25.0403.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
@@ -162,7 +164,8 @@ class Operations:
162
164
  Returns:
163
165
  list[connector_sdk_pb2.UpdateResponse]: A list of update responses.
164
166
  """
165
- _yield_check(inspect.stack())
167
+ if DEBUGGING:
168
+ _yield_check(inspect.stack())
166
169
 
167
170
  responses = []
168
171
 
@@ -200,7 +203,8 @@ class Operations:
200
203
  Returns:
201
204
  connector_sdk_pb2.UpdateResponse: The update response.
202
205
  """
203
- _yield_check(inspect.stack())
206
+ if DEBUGGING:
207
+ _yield_check(inspect.stack())
204
208
 
205
209
  table = get_renamed_table_name(table)
206
210
  columns = _get_columns(table)
@@ -226,7 +230,8 @@ class Operations:
226
230
  Returns:
227
231
  connector_sdk_pb2.UpdateResponse: The delete response.
228
232
  """
229
- _yield_check(inspect.stack())
233
+ if DEBUGGING:
234
+ _yield_check(inspect.stack())
230
235
 
231
236
  table = get_renamed_table_name(table)
232
237
  columns = _get_columns(table)
@@ -262,7 +267,9 @@ class Operations:
262
267
  Returns:
263
268
  connector_sdk_pb2.UpdateResponse: The checkpoint response.
264
269
  """
265
- _yield_check(inspect.stack())
270
+ if DEBUGGING:
271
+ _yield_check(inspect.stack())
272
+
266
273
  return connector_sdk_pb2.UpdateResponse(
267
274
  operation=connector_sdk_pb2.Operation(checkpoint=connector_sdk_pb2.Checkpoint(
268
275
  state_json=json.dumps(state))))
@@ -401,10 +408,7 @@ def map_defined_data_type(columns, k, mapped_data, v):
401
408
  mapped_data[k] = common_pb2.ValueType(naive_datetime=timestamp)
402
409
  elif columns[k].type == common_pb2.DataType.UTC_DATETIME:
403
410
  timestamp = timestamp_pb2.Timestamp()
404
- if '.' in v:
405
- dt = datetime.strptime(v, "%Y-%m-%dT%H:%M:%S.%f%z")
406
- else:
407
- dt = datetime.strptime(v, "%Y-%m-%dT%H:%M:%S%z")
411
+ dt = v if isinstance(v, datetime) else _parse_datetime_str(v)
408
412
  timestamp.FromDatetime(dt)
409
413
  mapped_data[k] = common_pb2.ValueType(utc_datetime=timestamp)
410
414
  elif columns[k].type == common_pb2.DataType.BINARY:
@@ -420,6 +424,10 @@ def map_defined_data_type(columns, k, mapped_data, v):
420
424
  raise ValueError(f"Unsupported data type encountered: {columns[k].type}. Please use valid data types.")
421
425
 
422
426
 
427
+ def _parse_datetime_str(dt):
428
+ return datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S.%f%z" if '.' in dt else "%Y-%m-%dT%H:%M:%S%z")
429
+
430
+
423
431
  def _yield_check(stack):
424
432
  """Checks for the presence of 'yield' in the calling code.
425
433
  Args:
@@ -432,8 +440,6 @@ def _yield_check(stack):
432
440
  # the file paths. This can lead to unexpected behavior, such as yield returning None or
433
441
  # the failure to retrieve the module inside a frozen app
434
442
  # (Reference: https://github.com/pyinstaller/pyinstaller/issues/5963)
435
- if not DEBUGGING:
436
- return
437
443
 
438
444
  called_method = stack[0].function
439
445
  calling_code = stack[1].code_context[0]
@@ -524,9 +530,9 @@ def print_library_log(message: str, level: Logging.Level = Logging.Level.INFO):
524
530
  if DEBUGGING or EXECUTED_VIA_CLI:
525
531
  current_time = datetime.now().strftime("%b %d, %Y %I:%M:%S %p")
526
532
  escaped_message = json.dumps(message).strip('"')
527
- print(f"{current_time} {level.name}: {escaped_message}")
533
+ print(f"{current_time} {level.name} {LOGGING_PREFIX}: {escaped_message}")
528
534
  else:
529
- escaped_message = json.dumps(message)
535
+ escaped_message = json.dumps(LOGGING_PREFIX + LOGGING_DELIMITER + message)
530
536
  log_message = f'{{"level":"{level.name}", "message": {escaped_message}, "message_origin": "library"}}'
531
537
  print(log_message)
532
538
 
@@ -925,7 +931,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
925
931
  self.__update_connection(
926
932
  args, connection_id, connection, group_name, connection_config, deploy_key, hd_agent_id)
927
933
  print("✓")
928
- print_library_log(f"Connector ID: {connection_id}")
934
+ print_library_log(f"Connection ID: {connection_id}")
929
935
  print_library_log(
930
936
  f"Visit the Fivetran dashboard to manage the connection: https://fivetran.com/dashboard/connectors/{connection_id}/status")
931
937
  else:
@@ -945,7 +951,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
945
951
  connection_id = response.json()['data']['id']
946
952
  # Python Version is not passed into connection_config as default value will be picked up from ConnectorSdkCredentials.java class.
947
953
  print_library_log(f"Python Version: {args.python_version if args.python_version else DEFAULT_PYTHON_VERSION}", Logging.Level.INFO)
948
- print_library_log(f"Connector ID: {connection_id}")
954
+ print_library_log(f"Connection ID: {connection_id}")
949
955
  print_library_log(
950
956
  f"Visit the Fivetran dashboard to start the initial sync: https://fivetran.com/dashboard/connectors/{connection_id}/status")
951
957
  else:
@@ -986,13 +992,19 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
986
992
  if not args.configuration:
987
993
  del config["secrets_list"]
988
994
 
995
+ json_payload = {
996
+ "config": config,
997
+ "run_setup_tests": True
998
+ }
999
+
1000
+ # hybrid_deployment_agent_id is optional when redeploying your connection.
1001
+ # Customer can use it to change existing hybrid_deployment_agent_id.
1002
+ if hd_agent_id:
1003
+ json_payload["hybrid_deployment_agent_id"] = hd_agent_id
1004
+
989
1005
  response = rq.patch(f"{PRODUCTION_BASE_URL}/v1/connectors/{id}",
990
1006
  headers={"Authorization": f"Basic {deploy_key}"},
991
- json={
992
- "config": config,
993
- "hybrid_deployment_agent_id": hd_agent_id,
994
- "run_setup_tests": True
995
- })
1007
+ json=json_payload)
996
1008
 
997
1009
  if response.ok and response.status_code == HTTPStatus.OK:
998
1010
  if Connector.__are_setup_tests_failing(response):
@@ -1010,7 +1022,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
1010
1022
  print_library_log(log_message, Logging.Level.SEVERE)
1011
1023
  Connector.__print_failing_setup_tests(resp)
1012
1024
  connection_id = resp.json().get('data', {}).get('id')
1013
- print_library_log(f"Connector ID: {connection_id}")
1025
+ print_library_log(f"Connection ID: {connection_id}")
1014
1026
  print_library_log("Please try again with the deploy command after resolving the issue!")
1015
1027
  os._exit(1)
1016
1028
 
@@ -1755,6 +1767,20 @@ def edit_distance(first_string: str, second_string: str) -> int:
1755
1767
  return previous_row[second_string_length]
1756
1768
 
1757
1769
 
1770
+ def get_input_from_cli(prompt : str, default_value: str) -> str:
1771
+ """
1772
+ Prompts the user for input.
1773
+ """
1774
+ if default_value:
1775
+ value = input(f"{prompt} [Default : {default_value}]: ").strip() or default_value
1776
+ else:
1777
+ value = input(f"{prompt}: ").strip()
1778
+
1779
+ if not value:
1780
+ raise ValueError("Missing required input: Expected a value but received None")
1781
+ return value or None
1782
+
1783
+
1758
1784
  def main():
1759
1785
  """The main entry point for the script.
1760
1786
  Parses command line arguments and passes them to connector object methods
@@ -1794,9 +1820,9 @@ def main():
1794
1820
  sys.exit(1)
1795
1821
 
1796
1822
  # Process optional args
1797
- ft_group = args.destination if args.destination else os.getenv('FIVETRAN_DESTINATION_NAME', None)
1798
- ft_connection = args.connection if args.connection else os.getenv('FIVETRAN_CONNECTION_NAME', None)
1799
- ft_deploy_key = args.api_key if args.api_key else os.getenv('FIVETRAN_API_KEY', None)
1823
+ ft_group = args.destination if args.destination else None
1824
+ ft_connection = args.connection if args.connection else None
1825
+ ft_deploy_key = args.api_key if args.api_key else None
1800
1826
  hd_agent_id = args.hybrid_deployment_agent_id if args.hybrid_deployment_agent_id else os.getenv(FIVETRAN_HD_AGENT_ID, None)
1801
1827
  configuration = args.configuration if args.configuration else None
1802
1828
  state = args.state if args.state else os.getenv('FIVETRAN_STATE', None)
@@ -1804,14 +1830,27 @@ def main():
1804
1830
  configuration = validate_and_load_configuration(args, configuration)
1805
1831
  state = validate_and_load_state(args, state)
1806
1832
 
1833
+ FIVETRAN_API_KEY = os.getenv('FIVETRAN_API_KEY', None)
1834
+ FIVETRAN_DESTINATION_NAME = os.getenv('FIVETRAN_DESTINATION_NAME', None)
1835
+ FIVETRAN_CONNECTION_NAME = os.getenv('FIVETRAN_CONNECTION_NAME', None)
1836
+
1807
1837
  if args.command.lower() == "deploy":
1808
1838
  if args.state:
1809
1839
  print_library_log("'state' parameter is not used for 'deploy' command", Logging.Level.WARNING)
1840
+
1841
+ if not ft_deploy_key:
1842
+ ft_deploy_key = get_input_from_cli("Please provide the API Key", FIVETRAN_API_KEY)
1843
+
1844
+ if not ft_group:
1845
+ ft_group = get_input_from_cli("Please provide the destination", FIVETRAN_DESTINATION_NAME)
1846
+
1847
+ if not ft_connection:
1848
+ ft_connection = get_input_from_cli("Please provide the connection name",FIVETRAN_CONNECTION_NAME)
1849
+
1810
1850
  connector_object.deploy(args, ft_deploy_key, ft_group, ft_connection, hd_agent_id, configuration)
1811
1851
 
1812
1852
  elif args.command.lower() == "debug":
1813
1853
  connector_object.debug(args.project_path, configuration, state)
1814
-
1815
1854
  else:
1816
1855
  if not suggest_correct_command(args.command):
1817
1856
  raise NotImplementedError(f"Invalid command: {args.command}, see `fivetran --help`")
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: fivetran_connector_sdk
3
- Version: 1.2.0
3
+ Version: 1.3.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
@@ -1,4 +1,4 @@
1
- fivetran_connector_sdk/__init__.py,sha256=XlVgreErkBABrP22wD702qUH9XsxFyqVGe_f9lb1HRI,79263
1
+ fivetran_connector_sdk/__init__.py,sha256=ubzp6kUWV4j8A3hgC-GRqtcX4WIQV5vMk5gdVkOZw4s,80578
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.2.0.dist-info/METADATA,sha256=vxP6elBzDjGbZ-e67pjRf8MyPLEJISbEx9UAdsXM25U,2967
10
- fivetran_connector_sdk-1.2.0.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
11
- fivetran_connector_sdk-1.2.0.dist-info/entry_points.txt,sha256=uQn0KPnFlQmXJfxlk0tifdNsSXWfVlnAFzNqjXZM_xM,57
12
- fivetran_connector_sdk-1.2.0.dist-info/top_level.txt,sha256=-_xk2MFY4psIh7jw1lJePMzFb5-vask8_ZtX-UzYWUI,23
13
- fivetran_connector_sdk-1.2.0.dist-info/RECORD,,
9
+ fivetran_connector_sdk-1.3.0.dist-info/METADATA,sha256=ilFpUA6zFnHz4_tEpKpG7IZxORmHqdcMdW0wb0z2sME,2967
10
+ fivetran_connector_sdk-1.3.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
11
+ fivetran_connector_sdk-1.3.0.dist-info/entry_points.txt,sha256=uQn0KPnFlQmXJfxlk0tifdNsSXWfVlnAFzNqjXZM_xM,57
12
+ fivetran_connector_sdk-1.3.0.dist-info/top_level.txt,sha256=-_xk2MFY4psIh7jw1lJePMzFb5-vask8_ZtX-UzYWUI,23
13
+ fivetran_connector_sdk-1.3.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.2)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5