fivetran-connector-sdk 1.7.1__tar.gz → 1.7.3__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.
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/PKG-INFO +1 -1
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/__init__.py +44 -8
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/connector_helper.py +56 -67
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/constants.py +1 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/logger.py +2 -2
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/operations.py +97 -25
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk.egg-info/PKG-INFO +1 -1
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/README.md +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/pyproject.toml +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/setup.cfg +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/helpers.py +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/protos/__init__.py +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/protos/common_pb2.py +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/protos/common_pb2.pyi +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/protos/common_pb2_grpc.py +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.py +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.pyi +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/protos/connector_sdk_pb2_grpc.py +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk.egg-info/SOURCES.txt +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk.egg-info/dependency_links.txt +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk.egg-info/entry_points.txt +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk.egg-info/requires.txt +0 -0
- {fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/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.7.
|
3
|
+
Version: 1.7.3
|
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
|
{fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/__init__.py
RENAMED
@@ -6,6 +6,9 @@ import shutil
|
|
6
6
|
import argparse
|
7
7
|
import traceback
|
8
8
|
import requests as rq
|
9
|
+
import threading
|
10
|
+
import queue
|
11
|
+
from types import GeneratorType
|
9
12
|
from http import HTTPStatus
|
10
13
|
from zipfile import ZipFile
|
11
14
|
from concurrent import futures
|
@@ -19,7 +22,8 @@ from fivetran_connector_sdk.operations import Operations
|
|
19
22
|
from fivetran_connector_sdk import constants
|
20
23
|
from fivetran_connector_sdk.constants import (
|
21
24
|
TESTER_VER, VERSION_FILENAME, UTF_8,
|
22
|
-
VALID_COMMANDS, DEFAULT_PYTHON_VERSION, SUPPORTED_PYTHON_VERSIONS, TABLES
|
25
|
+
VALID_COMMANDS, DEFAULT_PYTHON_VERSION, SUPPORTED_PYTHON_VERSIONS, TABLES,
|
26
|
+
CONNECTOR_SDK_NO_YIELD_LABEL
|
23
27
|
)
|
24
28
|
from fivetran_connector_sdk.helpers import (
|
25
29
|
print_library_log, reset_local_file_directory, find_connector_object, suggest_correct_command,
|
@@ -39,7 +43,7 @@ from fivetran_connector_sdk.connector_helper import (
|
|
39
43
|
|
40
44
|
# Version format: <major_version>.<minor_version>.<patch_version>
|
41
45
|
# (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.7.
|
46
|
+
__version__ = "1.7.3"
|
43
47
|
TESTER_VERSION = TESTER_VER
|
44
48
|
MAX_MESSAGE_LENGTH = 32 * 1024 * 1024 # 32MB
|
45
49
|
|
@@ -367,15 +371,47 @@ class Connector(connector_sdk_pb2_grpc.SourceConnectorServicer):
|
|
367
371
|
"""
|
368
372
|
configuration = self.configuration if self.configuration else request.configuration
|
369
373
|
state = self.state if self.state else json.loads(request.state_json)
|
374
|
+
exception_queue = queue.Queue()
|
370
375
|
|
371
376
|
try:
|
372
377
|
print_library_log("Initiating the 'update' method call...", Logging.Level.INFO)
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
378
|
+
|
379
|
+
if os.environ.get(CONNECTOR_SDK_NO_YIELD_LABEL, "false").lower() == "true":
|
380
|
+
def run_update():
|
381
|
+
try:
|
382
|
+
result = self.update_method(configuration=configuration, state=state)
|
383
|
+
# If the customer's update method returns a generator (i.e., uses yield),
|
384
|
+
# exhaust the generator responses, they are None. From this point on, all operations
|
385
|
+
# push update_response to a queue, and we yield from the queue instead.
|
386
|
+
# We return None here intentionally.
|
387
|
+
if isinstance(result, GeneratorType):
|
388
|
+
for _ in result:
|
389
|
+
pass
|
390
|
+
# If the update method doesn't use yield, skip the response returned.
|
391
|
+
else:
|
392
|
+
pass
|
393
|
+
except Exception as exc:
|
394
|
+
exception_queue.put(exc)
|
395
|
+
finally:
|
396
|
+
Operations.operation_stream.mark_done()
|
397
|
+
|
398
|
+
thread = threading.Thread(target=run_update)
|
399
|
+
thread.start()
|
400
|
+
|
401
|
+
yield from Operations.operation_stream
|
402
|
+
|
403
|
+
thread.join()
|
404
|
+
|
405
|
+
# Check if any exception was raised during the update
|
406
|
+
if not exception_queue.empty():
|
407
|
+
raise exception_queue.get()
|
408
|
+
else:
|
409
|
+
for update_response in self.update_method(configuration=configuration, state=state):
|
410
|
+
if isinstance(update_response, list):
|
411
|
+
for response in update_response:
|
412
|
+
yield response
|
413
|
+
else:
|
414
|
+
yield update_response
|
379
415
|
|
380
416
|
except TypeError as e:
|
381
417
|
if str(e) != "'NoneType' object is not iterable":
|
@@ -378,72 +378,61 @@ def validate_requirements_file(project_path: str, is_deploy: bool, version: str
|
|
378
378
|
update_version_requirements = False
|
379
379
|
update_missing_requirements = False
|
380
380
|
update_unused_requirements = False
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
381
|
+
requirements = load_or_add_requirements_file(requirements_file_path)
|
382
|
+
|
383
|
+
version_mismatch_deps = {key: tmp_requirements[key] for key in
|
384
|
+
(requirements.keys() & tmp_requirements.keys())
|
385
|
+
if requirements[key] != tmp_requirements[key]}
|
386
|
+
if version_mismatch_deps:
|
387
|
+
print_library_log("We recommend using the current stable version for the following libraries:", Logging.Level.WARNING)
|
388
|
+
print(version_mismatch_deps)
|
389
|
+
if is_deploy and not force:
|
390
|
+
confirm = input(
|
391
|
+
f"Would you like us to update {REQUIREMENTS_TXT} to the current stable versions of the dependent libraries? (y/N):")
|
392
|
+
if confirm.lower() == "y":
|
393
|
+
update_version_requirements = True
|
394
|
+
for requirement in version_mismatch_deps:
|
395
|
+
requirements[requirement] = tmp_requirements[requirement]
|
396
|
+
print_library_log(
|
397
|
+
f"Successfully updated {REQUIREMENTS_TXT} to the current stable versions of the dependent libraries.")
|
398
|
+
elif confirm.lower() == "n":
|
399
|
+
print_library_log(f"Changes identified for libraries with version conflicts have been ignored. These changes have NOT been made to {REQUIREMENTS_TXT}.")
|
400
|
+
|
401
|
+
missing_deps = {key: tmp_requirements[key] for key in (tmp_requirements.keys() - requirements.keys())}
|
402
|
+
if missing_deps:
|
403
|
+
handle_missing_deps(missing_deps)
|
404
|
+
if is_deploy and not force:
|
405
|
+
confirm = input(
|
406
|
+
f"Would you like us to update {REQUIREMENTS_TXT} to add missing dependent libraries? (y/N):")
|
407
|
+
if confirm.lower() == "n":
|
408
|
+
print_library_log(f"Changes identified as missing dependencies for libraries have been ignored. These changes have NOT been made to {REQUIREMENTS_TXT}.")
|
409
|
+
elif confirm.lower() == "y":
|
410
|
+
update_missing_requirements = True
|
411
|
+
for requirement in missing_deps:
|
412
|
+
requirements[requirement] = tmp_requirements[requirement]
|
413
|
+
print_library_log(f"Successfully added missing dependencies to {REQUIREMENTS_TXT}.")
|
414
|
+
|
415
|
+
unused_deps = list(requirements.keys() - tmp_requirements.keys())
|
416
|
+
if unused_deps:
|
417
|
+
handle_unused_deps(unused_deps, version)
|
418
|
+
if is_deploy and not force:
|
419
|
+
confirm = input(f"Would you like us to update {REQUIREMENTS_TXT} to remove the unused libraries? (y/N):")
|
420
|
+
if confirm.lower() == "n":
|
421
|
+
if 'fivetran_connector_sdk' in unused_deps or 'requests' in unused_deps:
|
397
422
|
print_library_log(
|
398
|
-
f"
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
update_missing_requirements = True
|
412
|
-
for requirement in missing_deps:
|
413
|
-
requirements[requirement] = tmp_requirements[requirement]
|
414
|
-
print_library_log(f"Successfully added missing dependencies to {REQUIREMENTS_TXT}.")
|
415
|
-
|
416
|
-
unused_deps = list(requirements.keys() - tmp_requirements.keys())
|
417
|
-
if unused_deps:
|
418
|
-
handle_unused_deps(unused_deps, version)
|
419
|
-
if is_deploy and not force:
|
420
|
-
confirm = input(f"Would you like us to update {REQUIREMENTS_TXT} to remove the unused libraries? (y/N):")
|
421
|
-
if confirm.lower() == "n":
|
422
|
-
if 'fivetran_connector_sdk' in unused_deps or 'requests' in unused_deps:
|
423
|
-
print_library_log(
|
424
|
-
f"Fix your {REQUIREMENTS_TXT} file by removing pre-installed dependencies [fivetran_connector_sdk, requests] to proceed with the deployment.")
|
425
|
-
sys.exit(1)
|
426
|
-
print_library_log(f"Changes identified for unused libraries have been ignored. These changes have NOT been made to {REQUIREMENTS_TXT}.")
|
427
|
-
elif confirm.lower() == "y":
|
428
|
-
update_unused_requirements = True
|
429
|
-
for requirement in unused_deps:
|
430
|
-
del requirements[requirement]
|
431
|
-
print_library_log(f"Successfully removed unused libraries from {REQUIREMENTS_TXT}.")
|
432
|
-
|
433
|
-
|
434
|
-
if update_version_requirements or update_missing_requirements or update_unused_requirements:
|
435
|
-
with open(requirements_file_path, "w", encoding=UTF_8) as file:
|
436
|
-
file.write("\n".join(requirements.values()))
|
437
|
-
print_library_log(f"`{REQUIREMENTS_TXT}` has been updated successfully.")
|
438
|
-
|
439
|
-
else:
|
440
|
-
if os.path.exists(requirements_file_path):
|
441
|
-
print_library_log(f"{REQUIREMENTS_TXT} is not required as no additional "
|
442
|
-
"Python libraries are required or all required libraries for "
|
443
|
-
"your code are pre-installed.", Logging.Level.WARNING)
|
444
|
-
with open(requirements_file_path, 'w') as file:
|
445
|
-
file.write("")
|
446
|
-
|
423
|
+
f"Fix your {REQUIREMENTS_TXT} file by removing pre-installed dependencies [fivetran_connector_sdk, requests] to proceed with the deployment.")
|
424
|
+
sys.exit(1)
|
425
|
+
print_library_log(f"Changes identified for unused libraries have been ignored. These changes have NOT been made to {REQUIREMENTS_TXT}.")
|
426
|
+
elif confirm.lower() == "y":
|
427
|
+
update_unused_requirements = True
|
428
|
+
for requirement in unused_deps:
|
429
|
+
del requirements[requirement]
|
430
|
+
print_library_log(f"Successfully removed unused libraries from {REQUIREMENTS_TXT}.")
|
431
|
+
|
432
|
+
if update_version_requirements or update_missing_requirements or update_unused_requirements:
|
433
|
+
with open(requirements_file_path, "w", encoding=UTF_8) as file:
|
434
|
+
file.write("\n".join(requirements.values()))
|
435
|
+
print_library_log(f"`{REQUIREMENTS_TXT}` has been updated successfully.")
|
447
436
|
|
448
437
|
if is_deploy: print_library_log(f"Validation of {REQUIREMENTS_TXT} completed.")
|
449
438
|
|
@@ -909,9 +898,9 @@ def _maybe_colorize_jar_output(line: str) -> str:
|
|
909
898
|
return line
|
910
899
|
|
911
900
|
if "SEVERE" in line or "ERROR" in line or "Exception" in line or "FAILED" in line:
|
912
|
-
return f"\033[
|
901
|
+
return f"\033[196m{line}\033[0m" # ANSI Red color #ff0000
|
913
902
|
elif "WARN" in line or "WARNING" in line:
|
914
|
-
return f"\033[
|
903
|
+
return f"\033[130m{line}\033[0m" # ANSI Orange-like color #af5f00
|
915
904
|
return line
|
916
905
|
|
917
906
|
def process_tables(response, table_list):
|
@@ -39,6 +39,7 @@ LOGGING_PREFIX = "Fivetran-Connector-SDK"
|
|
39
39
|
LOGGING_DELIMITER = ": "
|
40
40
|
VIRTUAL_ENV_CONFIG = "pyvenv.cfg"
|
41
41
|
ROOT_FILENAME = "connector.py"
|
42
|
+
CONNECTOR_SDK_NO_YIELD_LABEL = "CONNECTOR_SDK_NO_YIELD_APPROACH"
|
42
43
|
|
43
44
|
# Compile patterns used in the implementation
|
44
45
|
WORD_DASH_DOT_PATTERN = re.compile(r'^[\w.-]*$')
|
{fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/logger.py
RENAMED
@@ -41,9 +41,9 @@ class Logging:
|
|
41
41
|
@staticmethod
|
42
42
|
def get_color(level):
|
43
43
|
if level == Logging.Level.WARNING:
|
44
|
-
return "\033[
|
44
|
+
return "\033[130m" # ANSI Orange-like color #af5f00
|
45
45
|
elif level == Logging.Level.SEVERE:
|
46
|
-
return "\033[
|
46
|
+
return "\033[196m" # ANSI Red color #ff0000
|
47
47
|
return ""
|
48
48
|
|
49
49
|
@staticmethod
|
@@ -1,14 +1,14 @@
|
|
1
1
|
import json
|
2
|
-
import
|
2
|
+
import os
|
3
3
|
import sys
|
4
|
+
import queue
|
4
5
|
|
5
6
|
from datetime import datetime
|
6
7
|
from google.protobuf import timestamp_pb2
|
7
8
|
|
8
|
-
from fivetran_connector_sdk import constants
|
9
9
|
from fivetran_connector_sdk.constants import (
|
10
10
|
JAVA_LONG_MAX_VALUE,
|
11
|
-
TABLES,
|
11
|
+
TABLES, CONNECTOR_SDK_NO_YIELD_LABEL,
|
12
12
|
)
|
13
13
|
from fivetran_connector_sdk.helpers import (
|
14
14
|
get_renamed_table_name,
|
@@ -18,6 +18,65 @@ 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
|
+
class _OperationStream:
|
22
|
+
"""
|
23
|
+
A simple iterator-based stream backed by a queue for producing and consuming operations.
|
24
|
+
|
25
|
+
This class allows adding data items into a queue and consuming them using standard iteration.
|
26
|
+
It uses a sentinel object to signal the end of the stream.
|
27
|
+
|
28
|
+
Example:
|
29
|
+
stream = _OperationStream()
|
30
|
+
stream.add("response1")
|
31
|
+
stream.mark_done()
|
32
|
+
|
33
|
+
for response in stream:
|
34
|
+
print(response) # prints "response1"
|
35
|
+
"""
|
36
|
+
|
37
|
+
def __init__(self):
|
38
|
+
"""
|
39
|
+
Initializes the operation stream with a queue and a sentinel object.
|
40
|
+
"""
|
41
|
+
self._queue = queue.Queue(maxsize=1)
|
42
|
+
self._sentinel = object()
|
43
|
+
|
44
|
+
def __iter__(self):
|
45
|
+
"""
|
46
|
+
Returns the iterator instance itself.
|
47
|
+
"""
|
48
|
+
return self
|
49
|
+
|
50
|
+
def add(self, data):
|
51
|
+
"""
|
52
|
+
Adds an item to the stream.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
data (object): The data item to add to the stream.
|
56
|
+
"""
|
57
|
+
self._queue.put(data)
|
58
|
+
|
59
|
+
def mark_done(self):
|
60
|
+
"""
|
61
|
+
Marks the end of the stream by putting a sentinel in the queue.
|
62
|
+
"""
|
63
|
+
self._queue.put(self._sentinel)
|
64
|
+
|
65
|
+
def __next__(self):
|
66
|
+
"""
|
67
|
+
Retrieves the next item from the stream. Raises StopIteration when the sentinel is encountered.
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
object: The next item in the stream.
|
71
|
+
|
72
|
+
Raises:
|
73
|
+
StopIteration: If the sentinel object is encountered.
|
74
|
+
"""
|
75
|
+
item = self._queue.get()
|
76
|
+
if item is self._sentinel:
|
77
|
+
raise StopIteration
|
78
|
+
return item
|
79
|
+
|
21
80
|
_LOG_DATA_TYPE_INFERENCE = {
|
22
81
|
"boolean": True,
|
23
82
|
"binary": True,
|
@@ -25,8 +84,11 @@ _LOG_DATA_TYPE_INFERENCE = {
|
|
25
84
|
}
|
26
85
|
|
27
86
|
class Operations:
|
87
|
+
operation_stream = _OperationStream()
|
88
|
+
use_no_yield_approach = os.environ.get(CONNECTOR_SDK_NO_YIELD_LABEL, "false").lower() == "true"
|
89
|
+
|
28
90
|
@staticmethod
|
29
|
-
def upsert(table: str, data: dict)
|
91
|
+
def upsert(table: str, data: dict):
|
30
92
|
"""Updates records with the same primary key if already present in the destination. Inserts new records if not already present in the destination.
|
31
93
|
|
32
94
|
Args:
|
@@ -36,11 +98,6 @@ class Operations:
|
|
36
98
|
Returns:
|
37
99
|
list[connector_sdk_pb2.UpdateResponse]: A list of update responses.
|
38
100
|
"""
|
39
|
-
if constants.DEBUGGING:
|
40
|
-
_yield_check(inspect.stack())
|
41
|
-
|
42
|
-
responses = []
|
43
|
-
|
44
101
|
table = get_renamed_table_name(table)
|
45
102
|
columns = _get_columns(table)
|
46
103
|
if not columns:
|
@@ -58,13 +115,17 @@ class Operations:
|
|
58
115
|
type=common_pb2.RecordType.UPSERT,
|
59
116
|
data=mapped_data
|
60
117
|
)
|
118
|
+
update_response = connector_sdk_pb2.UpdateResponse(record=record)
|
61
119
|
|
62
|
-
|
120
|
+
if Operations.use_no_yield_approach:
|
121
|
+
Operations.operation_stream.add(update_response)
|
122
|
+
return None
|
123
|
+
else:
|
124
|
+
return [update_response]
|
63
125
|
|
64
|
-
return responses
|
65
126
|
|
66
127
|
@staticmethod
|
67
|
-
def update(table: str, modified: dict)
|
128
|
+
def update(table: str, modified: dict):
|
68
129
|
"""Performs an update operation on the specified table with the given modified data.
|
69
130
|
|
70
131
|
Args:
|
@@ -74,9 +135,6 @@ class Operations:
|
|
74
135
|
Returns:
|
75
136
|
connector_sdk_pb2.UpdateResponse: The update response.
|
76
137
|
"""
|
77
|
-
if constants.DEBUGGING:
|
78
|
-
_yield_check(inspect.stack())
|
79
|
-
|
80
138
|
table = get_renamed_table_name(table)
|
81
139
|
columns = _get_columns(table)
|
82
140
|
mapped_data = _map_data_to_columns(modified, columns)
|
@@ -87,10 +145,16 @@ class Operations:
|
|
87
145
|
data=mapped_data
|
88
146
|
)
|
89
147
|
|
90
|
-
|
148
|
+
update_response = connector_sdk_pb2.UpdateResponse(record=record)
|
149
|
+
|
150
|
+
if Operations.use_no_yield_approach:
|
151
|
+
Operations.operation_stream.add(update_response)
|
152
|
+
return None
|
153
|
+
else:
|
154
|
+
return update_response
|
91
155
|
|
92
156
|
@staticmethod
|
93
|
-
def delete(table: str, keys: dict)
|
157
|
+
def delete(table: str, keys: dict):
|
94
158
|
"""Performs a soft delete operation on the specified table with the given keys.
|
95
159
|
|
96
160
|
Args:
|
@@ -100,9 +164,6 @@ class Operations:
|
|
100
164
|
Returns:
|
101
165
|
connector_sdk_pb2.UpdateResponse: The delete response.
|
102
166
|
"""
|
103
|
-
if constants.DEBUGGING:
|
104
|
-
_yield_check(inspect.stack())
|
105
|
-
|
106
167
|
table = get_renamed_table_name(table)
|
107
168
|
columns = _get_columns(table)
|
108
169
|
mapped_data = _map_data_to_columns(keys, columns)
|
@@ -113,10 +174,16 @@ class Operations:
|
|
113
174
|
data=mapped_data
|
114
175
|
)
|
115
176
|
|
116
|
-
|
177
|
+
update_response = connector_sdk_pb2.UpdateResponse(record=record)
|
178
|
+
|
179
|
+
if Operations.use_no_yield_approach:
|
180
|
+
Operations.operation_stream.add(update_response)
|
181
|
+
return None
|
182
|
+
else:
|
183
|
+
return update_response
|
117
184
|
|
118
185
|
@staticmethod
|
119
|
-
def checkpoint(state: dict)
|
186
|
+
def checkpoint(state: dict):
|
120
187
|
"""Checkpoint saves the connector's state. State is a dict which stores information to continue the
|
121
188
|
sync from where it left off in the previous sync. For example, you may choose to have a field called
|
122
189
|
"cursor" with a timestamp value to indicate up to when the data has been synced. This makes it possible
|
@@ -136,9 +203,14 @@ class Operations:
|
|
136
203
|
Returns:
|
137
204
|
connector_sdk_pb2.UpdateResponse: The checkpoint response.
|
138
205
|
"""
|
139
|
-
|
140
|
-
|
141
|
-
|
206
|
+
update_response = connector_sdk_pb2.UpdateResponse(checkpoint=connector_sdk_pb2.Checkpoint(state_json=json.dumps(state)))
|
207
|
+
|
208
|
+
if Operations.use_no_yield_approach:
|
209
|
+
Operations.operation_stream.add(update_response)
|
210
|
+
return None
|
211
|
+
else:
|
212
|
+
return update_response
|
213
|
+
|
142
214
|
|
143
215
|
def _get_columns(table: str) -> dict:
|
144
216
|
"""Retrieves the columns for the specified table.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fivetran_connector_sdk
|
3
|
-
Version: 1.7.
|
3
|
+
Version: 1.7.3
|
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
|
File without changes
|
File without changes
|
File without changes
|
{fivetran_connector_sdk-1.7.1 → fivetran_connector_sdk-1.7.3}/src/fivetran_connector_sdk/helpers.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|