fivetran-connector-sdk 2.1.1__tar.gz → 2.2.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 (24) hide show
  1. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/PKG-INFO +3 -3
  2. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/pyproject.toml +2 -2
  3. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/__init__.py +31 -4
  4. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/connector_helper.py +63 -0
  5. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/constants.py +2 -1
  6. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/operations.py +8 -8
  7. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk.egg-info/PKG-INFO +3 -3
  8. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk.egg-info/requires.txt +2 -2
  9. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/README.md +0 -0
  10. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/setup.cfg +0 -0
  11. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/helpers.py +0 -0
  12. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/logger.py +0 -0
  13. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/operation_stream.py +0 -0
  14. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/protos/__init__.py +0 -0
  15. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/protos/common_pb2.py +0 -0
  16. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/protos/common_pb2.pyi +0 -0
  17. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/protos/common_pb2_grpc.py +0 -0
  18. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.py +0 -0
  19. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.pyi +0 -0
  20. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk/protos/connector_sdk_pb2_grpc.py +0 -0
  21. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk.egg-info/SOURCES.txt +0 -0
  22. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk.egg-info/dependency_links.txt +0 -0
  23. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/src/fivetran_connector_sdk.egg-info/entry_points.txt +0 -0
  24. {fivetran_connector_sdk-2.1.1 → fivetran_connector_sdk-2.2.1}/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: 2.1.1
3
+ Version: 2.2.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
@@ -11,8 +11,8 @@ Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=3.9
13
13
  Description-Content-Type: text/markdown
14
- Requires-Dist: grpcio==1.71.0
15
- Requires-Dist: grpcio-tools==1.71.0
14
+ Requires-Dist: grpcio==1.74.0
15
+ Requires-Dist: grpcio-tools==1.74.0
16
16
  Requires-Dist: requests==2.32.5
17
17
  Requires-Dist: pipreqs-fivetran==1.0.1
18
18
  Requires-Dist: prompt-toolkit==3.0.51
@@ -13,8 +13,8 @@ classifiers = [
13
13
  "Operating System :: OS Independent",
14
14
  ]
15
15
  dependencies = [
16
- "grpcio==1.71.0",
17
- "grpcio-tools==1.71.0",
16
+ "grpcio==1.74.0",
17
+ "grpcio-tools==1.74.0",
18
18
  "requests==2.32.5",
19
19
  "pipreqs-fivetran==1.0.1",
20
20
  "prompt-toolkit==3.0.51",
@@ -1,5 +1,6 @@
1
1
  import os
2
2
  import sys
3
+ import uuid
3
4
  import grpc
4
5
  import json
5
6
  import shutil
@@ -8,6 +9,7 @@ import traceback
8
9
  import requests as rq
9
10
  import threading
10
11
  import queue
12
+ import subprocess
11
13
  from types import GeneratorType
12
14
  from http import HTTPStatus
13
15
  from zipfile import ZipFile
@@ -37,12 +39,12 @@ from fivetran_connector_sdk.connector_helper import (
37
39
  get_available_port, tester_root_dir_helper,
38
40
  check_dict, check_newer_version, cleanup_uploaded_project,
39
41
  get_destination_group, get_connection_name, get_api_key, get_state,
40
- get_python_version, get_hd_agent_id, get_configuration
42
+ get_python_version, get_hd_agent_id, get_configuration, evaluate_project
41
43
  )
42
44
 
43
45
  # Version format: <major_version>.<minor_version>.<patch_version>
44
46
  # (where Major Version = 2, Minor Version is incremental MM from Aug 25 onwards, Patch Version is incremental within a month)
45
- __version__ = "2.1.1"
47
+ __version__ = "2.2.1"
46
48
  TESTER_VERSION = TESTER_VER
47
49
  MAX_MESSAGE_LENGTH = 32 * 1024 * 1024 # 32MB
48
50
 
@@ -64,6 +66,9 @@ class Connector(connector_sdk_pb2_grpc.SourceConnectorServicer):
64
66
 
65
67
  update_base_url_if_required()
66
68
 
69
+ def evaluate(self, project_path: str, deploy_key: str):
70
+ evaluate_project(project_path, deploy_key)
71
+
67
72
  # Call this method to deploy the connector to Fivetran platform
68
73
  def deploy(self, project_path: str, deploy_key: str, group: str, connection: str, hd_agent_id: str,
69
74
  configuration: dict = None, config_path = None, python_version: str = None, force: bool = False):
@@ -299,8 +304,12 @@ class Connector(connector_sdk_pb2_grpc.SourceConnectorServicer):
299
304
  print_library_log("Running connector tester...")
300
305
  for log_msg in run_tester(java_exe, tester_root_dir, project_path, available_port, json.dumps(self.state), json.dumps(self.configuration)):
301
306
  print(log_msg, end="")
302
- except:
307
+ except subprocess.CalledProcessError as e:
308
+ print(traceback.format_exc())
309
+ raise e
310
+ except Exception as e:
303
311
  print(traceback.format_exc())
312
+ raise e
304
313
  finally:
305
314
  server.stop(grace=2.0)
306
315
 
@@ -471,6 +480,12 @@ def main():
471
480
  if not connector_object:
472
481
  sys.exit(1)
473
482
 
483
+ if args.command.lower() == "evaluate":
484
+ print_library_log("Evaluating the connector code...")
485
+ ft_deploy_key = get_api_key(args)
486
+ connector_object.evaluate(args.project_path, ft_deploy_key)
487
+ sys.exit(0)
488
+
474
489
  if args.command.lower() == "deploy":
475
490
  ft_group = get_destination_group(args)
476
491
  ft_connection = get_connection_name(args)
@@ -486,7 +501,19 @@ def main():
486
501
  elif args.command.lower() == "debug":
487
502
  configuration, config_path = get_configuration(args)
488
503
  state = get_state(args)
489
- connector_object.debug(args.project_path, configuration, state)
504
+ try:
505
+ os.environ["FIVETRAN_CONNECTION_ID"] = "test_connection_id"
506
+ os.environ["FIVETRAN_DEPLOYMENT_MODEL"] = "local_debug"
507
+ connector_object.debug(args.project_path, configuration, state)
508
+ except subprocess.CalledProcessError as e:
509
+ print_library_log(f"Connector tester failed with exit code: {e.returncode}", Logging.Level.SEVERE)
510
+ sys.exit(e.returncode)
511
+ except Exception as e:
512
+ print_library_log(f"Debug command failed: {str(e)}", Logging.Level.SEVERE)
513
+ sys.exit(1)
514
+ finally:
515
+ del os.environ["FIVETRAN_CONNECTION_ID"]
516
+ del os.environ["FIVETRAN_DEPLOYMENT_MODEL"]
490
517
  else:
491
518
  if not suggest_correct_command(args.command):
492
519
  raise NotImplementedError(f"Invalid command: {args.command}, see `fivetran --help`")
@@ -1,3 +1,4 @@
1
+ import io
1
2
  import os
2
3
  import re
3
4
  import ast
@@ -476,6 +477,19 @@ def remove_unwanted_packages(requirements: dict):
476
477
  if requirements.get('requests') is not None:
477
478
  requirements.pop("requests")
478
479
 
480
+ def evaluate_project(project_path: str, deploy_key: str):
481
+ print_library_log(f"Evaluating '{project_path}'...")
482
+ upload_file_path = create_upload_file(project_path)
483
+ try:
484
+ evaluation_report = evaluate(upload_file_path, deploy_key)
485
+ if not evaluation_report:
486
+ print_library_log(
487
+ "Project evaluation failed. No evaluation report was generated. Please check your project for errors and try again.",
488
+ Logging.Level.SEVERE
489
+ )
490
+ sys.exit(1)
491
+ finally:
492
+ delete_file_if_exists(upload_file_path)
479
493
 
480
494
  def upload_project(project_path: str, deploy_key: str, group_id: str, group_name: str, connection: str):
481
495
  print_library_log(
@@ -702,6 +716,55 @@ def dir_walker(top):
702
716
  for x in dir_walker(new_path):
703
717
  yield x
704
718
 
719
+
720
+ def evaluate(local_path: str, deploy_key: str):
721
+ """Uploads the local code file for evaluation and returns the evaluation report.
722
+
723
+ The server responds with a file containing JSON. This function streams the
724
+ file safely, parses the JSON, and prints it.
725
+
726
+ Args:
727
+ local_path (str): The local file path.
728
+ deploy_key (str): The deployment key.
729
+
730
+ Returns:
731
+ dict | None: Parsed evaluation report if successful, None otherwise.
732
+ """
733
+ print_library_log("Uploading your project for evaluation...")
734
+
735
+ with open(local_path, 'rb') as f:
736
+ response = rq.post(
737
+ f"{constants.PRODUCTION_BASE_URL}{constants.EVALUATE_ENDPOINT}",
738
+ files={'file': f},
739
+ headers={"Authorization": f"Basic {deploy_key}"},
740
+ stream=True # stream to handle file responses safely
741
+ )
742
+
743
+ if response.ok:
744
+ try:
745
+ buffer = io.BytesIO()
746
+ for chunk in response.iter_content(chunk_size=8192):
747
+ buffer.write(chunk)
748
+ buffer.seek(0)
749
+
750
+ evaluation_data = json.load(buffer)
751
+
752
+ print_library_log("✓ Evaluation Report:")
753
+ print(json.dumps(evaluation_data, indent=4))
754
+
755
+ return evaluation_data
756
+
757
+ except json.JSONDecodeError as e:
758
+ print_library_log(f"Failed to parse evaluation report: {e}", Logging.Level.SEVERE)
759
+ return None
760
+
761
+ print_library_log(
762
+ f"Unable to upload the project for evaluation, failed with error: {response.text}",
763
+ Logging.Level.SEVERE
764
+ )
765
+ return None
766
+
767
+
705
768
  def upload(local_path: str, deploy_key: str, group_id: str, connection: str) -> bool:
706
769
  """Uploads the local code file for the specified group and connection.
707
770
 
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import re
3
3
 
4
- TESTER_VER = "2.25.0903.001"
4
+ TESTER_VER = "2.25.0918.001"
5
5
 
6
6
  WIN_OS = "windows"
7
7
  ARM_64 = "arm64"
@@ -64,6 +64,7 @@ COMMANDS_AND_SYNONYMS = {
64
64
 
65
65
  CONNECTION_SCHEMA_NAME_PATTERN = r'^[_a-z][_a-z0-9]*$'
66
66
  PRODUCTION_BASE_URL = "https://api.fivetran.com"
67
+ EVALUATE_ENDPOINT = "/v1/evaluate"
67
68
  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."
68
69
  INSTALLATION_SCRIPT = "installation.sh"
69
70
  DRIVERS = "drivers"
@@ -181,20 +181,20 @@ def _map_data_to_columns(data: dict, columns: dict, table: str = "") -> dict:
181
181
 
182
182
  def map_inferred_data_type(k, mapped_data, v, table=""):
183
183
  # We can infer type from the value
184
- if isinstance(v, int):
185
- if abs(v) > JAVA_LONG_MAX_VALUE:
186
- mapped_data[k] = common_pb2.ValueType(float=v)
187
- else:
188
- mapped_data[k] = common_pb2.ValueType(long=v)
189
- if _LOG_DATA_TYPE_INFERENCE.get("boolean_" + table, True) and isinstance(v, bool):
184
+ if isinstance(v, bool):
185
+ mapped_data[k] = common_pb2.ValueType(bool=v)
186
+ if _LOG_DATA_TYPE_INFERENCE.get("boolean_" + table, True):
190
187
  print_library_log("Fivetran: Boolean Datatype has been inferred for " + table, Logging.Level.INFO, True)
191
188
  if not _get_table_pk(table):
192
189
  print_library_log("Fivetran: Boolean Datatype inference issue for " + table, Logging.Level.INFO, True)
193
190
  _LOG_DATA_TYPE_INFERENCE["boolean_" + table] = False
191
+ elif isinstance(v, int):
192
+ if abs(v) > JAVA_LONG_MAX_VALUE:
193
+ mapped_data[k] = common_pb2.ValueType(float=v)
194
+ else:
195
+ mapped_data[k] = common_pb2.ValueType(long=v)
194
196
  elif isinstance(v, float):
195
197
  mapped_data[k] = common_pb2.ValueType(float=v)
196
- elif isinstance(v, bool):
197
- mapped_data[k] = common_pb2.ValueType(bool=v)
198
198
  elif isinstance(v, bytes):
199
199
  mapped_data[k] = common_pb2.ValueType(binary=v)
200
200
  elif isinstance(v, list):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fivetran_connector_sdk
3
- Version: 2.1.1
3
+ Version: 2.2.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
@@ -11,8 +11,8 @@ Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=3.9
13
13
  Description-Content-Type: text/markdown
14
- Requires-Dist: grpcio==1.71.0
15
- Requires-Dist: grpcio-tools==1.71.0
14
+ Requires-Dist: grpcio==1.74.0
15
+ Requires-Dist: grpcio-tools==1.74.0
16
16
  Requires-Dist: requests==2.32.5
17
17
  Requires-Dist: pipreqs-fivetran==1.0.1
18
18
  Requires-Dist: prompt-toolkit==3.0.51
@@ -1,5 +1,5 @@
1
- grpcio==1.71.0
2
- grpcio-tools==1.71.0
1
+ grpcio==1.74.0
2
+ grpcio-tools==1.74.0
3
3
  requests==2.32.5
4
4
  pipreqs-fivetran==1.0.1
5
5
  prompt-toolkit==3.0.51