fivetran-connector-sdk 1.3.3__tar.gz → 1.4.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 (18) hide show
  1. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/PKG-INFO +1 -1
  2. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk/__init__.py +60 -24
  3. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk.egg-info/PKG-INFO +1 -1
  4. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/README.md +0 -0
  5. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/pyproject.toml +0 -0
  6. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/setup.cfg +0 -0
  7. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk/protos/__init__.py +0 -0
  8. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk/protos/common_pb2.py +0 -0
  9. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk/protos/common_pb2.pyi +0 -0
  10. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk/protos/common_pb2_grpc.py +0 -0
  11. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.py +0 -0
  12. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.pyi +0 -0
  13. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk/protos/connector_sdk_pb2_grpc.py +0 -0
  14. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk.egg-info/SOURCES.txt +0 -0
  15. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk.egg-info/dependency_links.txt +0 -0
  16. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk.egg-info/entry_points.txt +0 -0
  17. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.0}/src/fivetran_connector_sdk.egg-info/requires.txt +0 -0
  18. {fivetran_connector_sdk-1.3.3 → fivetran_connector_sdk-1.4.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.3.3
3
+ Version: 1.4.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
@@ -32,13 +32,13 @@ from fivetran_connector_sdk.protos import connector_sdk_pb2_grpc
32
32
 
33
33
  # Version format: <major_version>.<minor_version>.<patch_version>
34
34
  # (where Major Version = 1 for GA, Minor Version is incremental MM from Jan 25 onwards, Patch Version is incremental within a month)
35
- __version__ = "1.3.3"
35
+ __version__ = "1.4.0"
36
36
 
37
37
  MAC_OS = "mac"
38
38
  WIN_OS = "windows"
39
39
  LINUX_OS = "linux"
40
40
 
41
- TESTER_VERSION = "0.25.0423.001"
41
+ TESTER_VERSION = "0.25.0424.001"
42
42
  TESTER_FILENAME = "run_sdk_tester.jar"
43
43
  VERSION_FILENAME = "version.txt"
44
44
  UPLOAD_FILENAME = "code.zip"
@@ -110,12 +110,24 @@ class Logging:
110
110
  if DEBUGGING:
111
111
  current_time = datetime.now().strftime("%b %d, %Y %I:%M:%S %p")
112
112
  escaped_message = json.dumps(message).strip('"')
113
- print(f"{current_time} {level.name}: {escaped_message}")
113
+ print(f"{Logging._get_color(level)}{current_time} {level.name}: {escaped_message} {Logging._reset_color()}")
114
114
  else:
115
115
  escaped_message = json.dumps(message)
116
116
  log_message = f'{{"level":"{level.name}", "message": {escaped_message}, "message_origin": "connector_sdk"}}'
117
117
  print(log_message)
118
118
 
119
+ @staticmethod
120
+ def _get_color(level):
121
+ if level == Logging.Level.WARNING:
122
+ return "\033[93m" # Yellow
123
+ elif level == Logging.Level.SEVERE:
124
+ return "\033[91m" # Red
125
+ return ""
126
+
127
+ @staticmethod
128
+ def _reset_color():
129
+ return "\033[0m"
130
+
119
131
  @staticmethod
120
132
  def fine(message: str):
121
133
  """Logs a fine-level message.
@@ -313,7 +325,7 @@ def check_newer_version():
313
325
  latest_version = data["info"]["version"]
314
326
  if __version__ < latest_version:
315
327
  print_library_log(f"[notice] A new release of 'fivetran-connector-sdk' is available: {latest_version}\n" +
316
- f"[notice] To update, run: pip install --upgrade fivetran-connector-sdk\n")
328
+ "[notice] To update, run: pip install --upgrade fivetran-connector-sdk\n")
317
329
 
318
330
  with open(last_check_file_path, 'w', encoding=UTF_8) as f_out:
319
331
  f_out.write(f"{int(time.time())}")
@@ -573,7 +585,7 @@ def print_library_log(message: str, level: Logging.Level = Logging.Level.INFO):
573
585
  if DEBUGGING or EXECUTED_VIA_CLI:
574
586
  current_time = datetime.now().strftime("%b %d, %Y %I:%M:%S %p")
575
587
  escaped_message = json.dumps(message).strip('"')
576
- print(f"{current_time} {level.name} {LOGGING_PREFIX}: {escaped_message}")
588
+ print(f"{Logging._get_color(level)}{current_time} {level.name} {LOGGING_PREFIX}: {escaped_message} {Logging._reset_color()}")
577
589
  else:
578
590
  escaped_message = json.dumps(LOGGING_PREFIX + LOGGING_DELIMITER + message)
579
591
  log_message = f'{{"level":"{level.name}", "message": {escaped_message}, "message_origin": "library"}}'
@@ -794,6 +806,8 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
794
806
 
795
807
  # tmp_requirements is only generated when pipreqs command is successful
796
808
  tmp_requirements_file_path = os.path.join(project_path, 'tmp_requirements.txt')
809
+ # copying packages of requirements file to tmp file to handle pipreqs fail use-case
810
+ self.copy_requirements_file_to_tmp_requirements_file(os.path.join(project_path, REQUIREMENTS_TXT), tmp_requirements_file_path)
797
811
  # Run the pipreqs command and capture stderr
798
812
  attempt = 0
799
813
  while attempt < MAX_RETRIES:
@@ -815,13 +829,11 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
815
829
  time.sleep(retry_after)
816
830
  else:
817
831
  print_library_log(f"pipreqs failed after {MAX_RETRIES} attempts with:", Logging.Level.SEVERE)
818
- print(result.stderr)
819
- sys.exit(1)
832
+ print_library_log(result.stderr, Logging.Level.SEVERE)
833
+ print_library_log(f"Skipping validation of requirements.txt due to error connecting to PyPI (Python Package Index) APIs. Continuing with {'deploy' if is_deploy else 'debug'}...", Logging.Level.SEVERE)
820
834
 
821
835
  tmp_requirements = self.fetch_requirements_as_dict(self, tmp_requirements_file_path)
822
- tmp_requirements.pop("fivetran_connector_sdk")
823
- if tmp_requirements.get('requests') is not None:
824
- tmp_requirements.pop("requests")
836
+ self.remove_unwanted_packages(tmp_requirements)
825
837
  os.remove(tmp_requirements_file_path)
826
838
 
827
839
  # remove corrupt requirements listed by pipreqs
@@ -894,7 +906,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
894
906
  if 'requests' in unused_deps:
895
907
  log_unused_deps_error("requests", "2.32.3")
896
908
  print_library_log("The following dependencies are not needed, "
897
- f"they are not used or already installed. Please remove them from {REQUIREMENTS_TXT}:")
909
+ f"they are not used or already installed. Please remove them from {REQUIREMENTS_TXT}:", Logging.Level.WARNING)
898
910
  print(*unused_deps)
899
911
 
900
912
  def handle_missing_deps(self, missing_deps):
@@ -915,6 +927,19 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
915
927
  print_library_log("Adding `requirements.txt` file to your project folder.", Logging.Level.WARNING)
916
928
  return requirements
917
929
 
930
+ def copy_requirements_file_to_tmp_requirements_file(self, requirements_file_path: str, tmp_requirements_file_path):
931
+ requirements_file_content = self.fetch_requirements_from_file(requirements_file_path)
932
+ with open(tmp_requirements_file_path, 'w') as file:
933
+ file.write("\n".join(requirements_file_content))
934
+
935
+ @staticmethod
936
+ def remove_unwanted_packages(requirements: dict):
937
+ # remove the `fivetran_connector_sdk` and `requests` packages from requirements as we already pre-installed them.
938
+ if requirements.get("fivetran_connector_sdk") is not None:
939
+ requirements.pop("fivetran_connector_sdk")
940
+ if requirements.get('requests') is not None:
941
+ requirements.pop("requests")
942
+
918
943
  # Call this method to deploy the connector to Fivetran platform
919
944
  def deploy(self, args: dict, deploy_key: str, group: str, connection: str, hd_agent_id: str, configuration: dict = None):
920
945
  """Deploys the connector to the Fivetran platform.
@@ -1188,7 +1213,7 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
1188
1213
  if INSTALLATION_SCRIPT in files:
1189
1214
  custom_driver_installation_script_exists = True
1190
1215
  for file in files:
1191
- if file == "connector.py":
1216
+ if file == ROOT_FILENAME:
1192
1217
  connector_file_exists = True
1193
1218
  file_path = os.path.join(root, file)
1194
1219
  arcname = os.path.relpath(file_path, project_path)
@@ -1542,10 +1567,10 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
1542
1567
 
1543
1568
  popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
1544
1569
  for line in Connector.process_stream(popen.stderr):
1545
- yield line
1570
+ yield Connector._maybe_colorize_jar_output(line)
1546
1571
 
1547
1572
  for line in Connector.process_stream(popen.stdout):
1548
- yield line
1573
+ yield Connector._maybe_colorize_jar_output(line)
1549
1574
  popen.stdout.close()
1550
1575
  return_code = popen.wait()
1551
1576
  if return_code:
@@ -1726,19 +1751,30 @@ class Connector(connector_sdk_pb2_grpc.ConnectorServicer):
1726
1751
  print_library_log(error_message, Logging.Level.SEVERE)
1727
1752
  raise RuntimeError(error_message) from e
1728
1753
 
1754
+ @staticmethod
1755
+ def _maybe_colorize_jar_output(line: str) -> str:
1756
+ if not DEBUGGING:
1757
+ return line
1758
+
1759
+ if "SEVERE" in line or "ERROR" in line or "Exception" in line or "FAILED" in line:
1760
+ return f"\033[91m{line}\033[0m" # Red
1761
+ elif "WARN" in line or "WARNING" in line:
1762
+ return f"\033[93m{line}\033[0m" # Yellow
1763
+ return line
1764
+
1729
1765
 
1730
- def find_connector_object(project_path) -> Connector:
1766
+ def find_connector_object(project_path) -> Optional[Connector]:
1731
1767
  """Finds the connector object in the given project path.
1732
1768
  Args:
1733
1769
  project_path (str): The path to the project.
1734
1770
 
1735
1771
  Returns:
1736
- object: The connector object.
1772
+ Optional[Connector]: The connector object or None if not found.
1737
1773
  """
1738
1774
 
1739
1775
  sys.path.append(project_path) # Allows python interpreter to search for modules in this path
1740
1776
  module_name = "connector_connector_code"
1741
- connector_py = os.path.join(project_path, "connector.py")
1777
+ connector_py = os.path.join(project_path, ROOT_FILENAME)
1742
1778
  try:
1743
1779
  spec = importlib.util.spec_from_file_location(module_name, connector_py)
1744
1780
  module = importlib.util.module_from_spec(spec)
@@ -1752,11 +1788,11 @@ def find_connector_object(project_path) -> Connector:
1752
1788
  except FileNotFoundError:
1753
1789
  print_library_log(
1754
1790
  "The connector object is missing in the current directory. Please ensure that you are running the command from correct directory or that you have defined a connector object using the correct syntax in your `connector.py` file. Reference: https://fivetran.com/docs/connectors/connector-sdk/technical-reference#technicaldetailsrequiredobjectconnector", Logging.Level.SEVERE)
1755
- return
1791
+ return None
1756
1792
 
1757
1793
  print_library_log(
1758
1794
  "The connector object is missing. Please ensure that you have defined a connector object using the correct syntax in your `connector.py` file. Reference: https://fivetran.com/docs/connectors/connector-sdk/technical-reference#technicaldetailsrequiredobjectconnector", Logging.Level.SEVERE)
1759
- return
1795
+ return None
1760
1796
 
1761
1797
 
1762
1798
  def suggest_correct_command(input_command: str) -> bool:
@@ -1782,9 +1818,9 @@ def suggest_correct_command(input_command: str) -> bool:
1782
1818
 
1783
1819
 
1784
1820
  def print_suggested_command_message(valid_command: str, input_command: str) -> None:
1785
- print(f"`fivetran {input_command}` is not a valid command.")
1786
- print(f"Did you mean `fivetran {valid_command}`?")
1787
- print("Use `fivetran --help` for more details.")
1821
+ print_library_log(f"`fivetran {input_command}` is not a valid command.", Logging.Level.SEVERE)
1822
+ print_library_log(f"Did you mean `fivetran {valid_command}`?", Logging.Level.SEVERE)
1823
+ print_library_log("Use `fivetran --help` for more details.", Logging.Level.SEVERE)
1788
1824
 
1789
1825
 
1790
1826
  def edit_distance(first_string: str, second_string: str) -> int:
@@ -1829,7 +1865,7 @@ def get_input_from_cli(prompt : str, default_value: str) -> str:
1829
1865
 
1830
1866
  if not value:
1831
1867
  raise ValueError("Missing required input: Expected a value but received None")
1832
- return value or None
1868
+ return value
1833
1869
 
1834
1870
 
1835
1871
  def main():
@@ -1854,7 +1890,7 @@ def main():
1854
1890
  parser.add_argument("--connection", type=str, default=None, help="Connection name (aka 'destination schema')")
1855
1891
  parser.add_argument("-f", "--force", action="store_true", help="Force update an existing connection")
1856
1892
  parser.add_argument("--python-version", "--python", type=str, help=f"Supported Python versions you can use: {SUPPORTED_PYTHON_VERSIONS}. Defaults to 3.12.8")
1857
- parser.add_argument("--hybrid-deployment-agent-id", type=str, help=argparse.SUPPRESS)
1893
+ parser.add_argument("--hybrid-deployment-agent-id", type=str, help="The Hybrid Deployment agent within the Fivetran system. If nothing is passed, the default agent of the destination is used.")
1858
1894
 
1859
1895
  args = parser.parse_args()
1860
1896
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fivetran_connector_sdk
3
- Version: 1.3.3
3
+ Version: 1.4.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